summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rwxr-xr-xsrc/components/xriProtocolHandler.js2
1 files changed, 2 insertions, 0 deletions
diff --git a/src/components/xriProtocolHandler.js b/src/components/xriProtocolHandler.js
index 3d27784..2e09f64 100755
--- a/src/components/xriProtocolHandler.js
+++ b/src/components/xriProtocolHandler.js
@@ -1,1063 +1,1065 @@
1/*********************************************************** 1/***********************************************************
2 constants 2 constants
3 ***********************************************************/ 3 ***********************************************************/
4 4
5// The interface we implement - nsIProtocolHandler 5// The interface we implement - nsIProtocolHandler
6const nsIProtocolHandler = Components.interfaces.nsIProtocolHandler; 6const nsIProtocolHandler = Components.interfaces.nsIProtocolHandler;
7 7
8// Interfaces that we require 8// Interfaces that we require
9 const nsISupports = Components.interfaces.nsISupports; 9 const nsISupports = Components.interfaces.nsISupports;
10 const nsIIOService = Components.interfaces.nsIIOService; 10 const nsIIOService = Components.interfaces.nsIIOService;
11 const nsIURI = Components.interfaces.nsIURI; 11 const nsIURI = Components.interfaces.nsIURI;
12 const nsIURL = Components.interfaces.nsIURL; 12 const nsIURL = Components.interfaces.nsIURL;
13 const nsIRequest = Components.interfaces.nsIRequest; 13 const nsIRequest = Components.interfaces.nsIRequest;
14const nsIRequestObserver = Components.interfaces.nsIRequestObserver; 14const nsIRequestObserver = Components.interfaces.nsIRequestObserver;
15 const nsIChannel = Components.interfaces.nsIChannel; 15 const nsIChannel = Components.interfaces.nsIChannel;
16 const nsIHttpChannel = Components.interfaces.nsIHttpChannel; 16 const nsIHttpChannel = Components.interfaces.nsIHttpChannel;
17 const nsIStreamListener = Components.interfaces.nsIStreamListener; 17 const nsIStreamListener = Components.interfaces.nsIStreamListener;
18 18
19 19
20// UUID uniquely identifying our component 20// UUID uniquely identifying our component
21// You can get from: http://kruithof.xs4all.nl/uuid/uuidgen here 21// You can get from: http://kruithof.xs4all.nl/uuid/uuidgen here
22const CLASS_ID = Components.ID("{ea00b610-215a-11db-a98b-0800200c9a66}"); 22const CLASS_ID = Components.ID("{ea00b610-215a-11db-a98b-0800200c9a66}");
23 23
24// textual unique identifier 24// textual unique identifier
25const CONTRACT_ID = "@mozilla.org/network/protocol;1?name=xri"; 25const CONTRACT_ID = "@mozilla.org/network/protocol;1?name=xri";
26 26
27// Components that we require 27// Components that we require
28const CID_URI = "@mozilla.org/network/simple-uri;1"; 28const CID_URI = "@mozilla.org/network/simple-uri;1";
29const kIOSERVICE_CID_STR = "{9ac9e770-18bc-11d3-9337-00104ba0fd40}"; 29const kIOSERVICE_CID_STR = "{9ac9e770-18bc-11d3-9337-00104ba0fd40}";
30const CID_URL = "@mozilla.org/network/standard-url;1"; 30const CID_URL = "@mozilla.org/network/standard-url;1";
31 31
32// description 32// description
33const CLASS_NAME = "XRI Protocol Handler"; 33const CLASS_NAME = "XRI Protocol Handler";
34 34
35const PROXY_URI = "http://xri.net/"; 35const PROXY_URI = "http://xri.net/";
36 36
37const XP_ANY_TYPE = 0; 37const XP_ANY_TYPE = 0;
38const XP_NUMBER_TYPE = 1; 38const XP_NUMBER_TYPE = 1;
39const XP_STRING_TYPE = 2; 39const XP_STRING_TYPE = 2;
40const XP_BOOLEAN_TYPE = 3; 40const XP_BOOLEAN_TYPE = 3;
41const XP_UNORDERED_NODE_ITERATOR_TYPE = 4; 41const XP_UNORDERED_NODE_ITERATOR_TYPE = 4;
42const XP_ORDERED_NODE_ITERATOR_TYPE = 5; 42const XP_ORDERED_NODE_ITERATOR_TYPE = 5;
43const XP_UNORDERED_NODE_SNAPSHOT_TYPE = 6; 43const XP_UNORDERED_NODE_SNAPSHOT_TYPE = 6;
44const XP_ORDERED_NODE_SNAPSHOT_TYPE = 7; 44const XP_ORDERED_NODE_SNAPSHOT_TYPE = 7;
45const XP_ANY_UNORDERED_NODE_TYPE = 8; 45const XP_ANY_UNORDERED_NODE_TYPE = 8;
46const XP_FIRST_ORDERED_NODE_TYPE = 9; 46const XP_FIRST_ORDERED_NODE_TYPE = 9;
47 47
48 48
49var SERVICE_CLASSES = { 49var SERVICE_CLASSES = {
50 'xri://+i-service*(+contact)*($v*1.0)': 'i-contact', 50 'xri://+i-service*(+contact)*($v*1.0)': 'i-contact',
51 'http://openid.net/signon/1.0': 'openid', 51 'http://openid.net/signon/1.0': 'openid',
52 'http://openid.net/signon/1.1': 'openid', 52 'http://openid.net/signon/1.1': 'openid',
53 'http://specs.openid.net/auth/2.0/signon': 'openid', 53 'http://specs.openid.net/auth/2.0/signon': 'openid',
54 'http://specs.openid.net/auth/2.0/server': 'openid', 54 'http://specs.openid.net/auth/2.0/server': 'openid',
55 'xri://$res*auth*($v*2.0)': 'res-auth', 55 'xri://$res*auth*($v*2.0)': 'res-auth',
56 'xri://+i-service*(+authn)*(+saml)*($v*1.0)': 'authn-saml', 56 'xri://+i-service*(+authn)*(+saml)*($v*1.0)': 'authn-saml',
57 'xri://+i-service*(+metadata)*(+saml)*($v*1.0)' : 'metadata-saml', 57 'xri://+i-service*(+metadata)*(+saml)*($v*1.0)' : 'metadata-saml',
58 'xri://+i-service*(+forwarding)*($v*1.0)': 'i-forwarding' 58 'xri://+i-service*(+forwarding)*($v*1.0)': 'i-forwarding'
59}; 59};
60 60
61 61
62const HTML_HEAD = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n\ 62const HTML_HEAD = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n\
63 <html xmlns=\"http://www.w3.org/1999/xhtml\">\n\ 63 <html xmlns=\"http://www.w3.org/1999/xhtml\">\n\
64 <head>\n\ 64 <head>\n\
65 <title>FoXRI Explorer - #QXRI#</title>\n\ 65 <title>FoXRI Explorer - #QXRI#</title>\n\
66 <link href=\"chrome://foxri/content/foxri_explorer.css\" rel=\"stylesheet\" type=\"text/css\" />\n\ 66 <link href=\"chrome://foxri/content/foxri_explorer.css\" rel=\"stylesheet\" type=\"text/css\" />\n\
67 <body>\n\ 67 <body>\n\
68 <h1>FoXRI Explorer</h1>\n\ 68 <h1>FoXRI Explorer</h1>\n\
69 <div id=\"explorer_body\">\n"; 69 <div id=\"explorer_body\">\n";
70 70
71const HTML_FOOT = "</div>\n\ 71const HTML_FOOT = "</div>\n\
72 </body>\n\ 72 </body>\n\
73 </html>"; 73 </html>";
74 74
75 75
76 76
77/// Generic object method wrapper 77/// Generic object method wrapper
78function methodWrapper(obj, method) 78function methodWrapper(obj, method)
79{ 79{
80 return ( 80 return (
81 function() { 81 function() {
82 /* pass it this inner closure's arguments */ 82 /* pass it this inner closure's arguments */
83 obj[method](arguments); 83 obj[method](arguments);
84 } 84 }
85 ); 85 );
86} 86}
87 87
88 88
89 89
90/// XRDS utility functions 90/// XRDS utility functions
91 91
92 92
93var nsResolver = { 93var nsResolver = {
94 lookupNamespaceURI: function(prefix) 94 lookupNamespaceURI: function(prefix)
95 { 95 {
96 if (prefix == "xrds") 96 if (prefix == "xrds")
97 return "xri://$xrds"; 97 return "xri://$xrds";
98 else if (prefix == "xrd") 98 else if (prefix == "xrd")
99 return "xri://$xrd*($v*2.0)"; 99 return "xri://$xrd*($v*2.0)";
100 return ""; 100 return "";
101 } 101 }
102}; 102};
103 103
104 104
105 105
106function runExpr(doc, context, expr, returnType) 106function runExpr(doc, context, expr, returnType)
107{ 107{
108 if (!returnType) 108 if (!returnType)
109 returnType = XP_ANY_TYPE; 109 returnType = XP_ANY_TYPE;
110 var res = doc.evaluate(expr, context, nsResolver, returnType, null); 110 var res = doc.evaluate(expr, context, nsResolver, returnType, null);
111 return res; 111 return res;
112} 112}
113 113
114 114
115function getNumeric(doc, context, expr) 115function getNumeric(doc, context, expr)
116{ 116{
117 var res = runExpr(doc, context, expr, XP_NUMBER_TYPE); 117 var res = runExpr(doc, context, expr, XP_NUMBER_TYPE);
118 if (res) 118 if (res)
119 return res.numberValue; 119 return res.numberValue;
120 return null; 120 return null;
121} 121}
122 122
123 123
124function getString(doc, context, expr) 124function getString(doc, context, expr)
125{ 125{
126 // var res = runExpr(doc, context, expr, XPathResult.STRING_TYPE); 126 // var res = runExpr(doc, context, expr, XPathResult.STRING_TYPE);
127 var res = runExpr(doc, context, expr, XP_STRING_TYPE); 127 var res = runExpr(doc, context, expr, XP_STRING_TYPE);
128 if (res) 128 if (res)
129 return res.stringValue; 129 return res.stringValue;
130 return null; 130 return null;
131} 131}
132 132
133function getNode(doc, context, expr) 133function getNode(doc, context, expr)
134{ 134{
135 var res = runExpr(doc, context, expr, XP_FIRST_ORDERED_NODE_TYPE); 135 var res = runExpr(doc, context, expr, XP_FIRST_ORDERED_NODE_TYPE);
136 if (res) 136 if (res)
137 return res.singleNodeValue; 137 return res.singleNodeValue;
138 return null; 138 return null;
139} 139}
140 140
141 141
142function getFinalXRD(doc) 142function getFinalXRD(doc)
143{ 143{
144 var lastNode = doc.firstChild; 144 var lastNode = doc.firstChild;
145 while (true) { 145 while (true) {
146 var node = getNode(doc, lastNode, "xrds:XRDS[position()=last()]"); 146 var node = getNode(doc, lastNode, "xrds:XRDS[position()=last()]");
147 if (!node) 147 if (!node)
148 break; 148 break;
149 lastNode = node; 149 lastNode = node;
150 } 150 }
151 151
152 return getNode(doc, lastNode, "xrd:XRD[position()=last()]"); 152 return getNode(doc, lastNode, "xrd:XRD[position()=last()]");
153} 153}
154 154
155 155
156function isIName(xri) 156function isIName(xri)
157{ 157{
158 if (xri.match('^xri://.!', 'i')) { 158 if (xri.match('^xri://.!', 'i')) {
159 return false; 159 return false;
160 } 160 }
161 if (xri.match('^.!', 'i')) { 161 if (xri.match('^.!', 'i')) {
162 return false; 162 return false;
163 } 163 }
164 return true; 164 return true;
165} 165}
166 166
167 167
168function arraySearch(a, re) 168function arraySearch(a, re)
169{ 169{
170 var returnArr = new Array(); 170 var returnArr = new Array();
171 var i; 171 var i;
172 for (i = 0; i < a.length; i++) { 172 for (i = 0; i < a.length; i++) {
173 if (a[i].match(re)) { 173 if (a[i].match(re)) {
174 returnArr.push(a[i]); 174 returnArr.push(a[i]);
175 } 175 }
176 } 176 }
177 177
178 return returnArr; 178 return returnArr;
179} 179}
180 180
181 181
182function renderService(srv, doc, qxri) 182function renderService(srv, doc, qxri)
183{ 183{
184 var html_types = ''; 184 var html_types = '';
185 var html_paths = ''; 185 var html_paths = '';
186 var html_mediatypes = ''; 186 var html_mediatypes = '';
187 var html_uris = ''; 187 var html_uris = '';
188 var html_actions = ''; 188 var html_actions = '';
189 189
190 var serviceName = friendlyServiceName(null); 190 var serviceName = friendlyServiceName(null);
191 var serviceType; // the last non-null Type 191 var serviceType; // the last non-null Type
192 var knownServiceType; // first recognized service type 192 var knownServiceType; // first recognized service type
193 193
194 // get the types 194 // get the types
195 var res = runExpr(doc, srv, "xrd:Type/text()"); 195 var res = runExpr(doc, srv, "xrd:Type/text()");
196 var t; 196 var t;
197 while (t = res.iterateNext()) { 197 while (t = res.iterateNext()) {
198 if (t.nodeValue) { 198 if (t.nodeValue) {
199 if (!knownServiceType && isKnownServiceType(t.nodeValue)) { 199 if (!knownServiceType && isKnownServiceType(t.nodeValue)) {
200 knownServiceType = t.nodeValue; 200 knownServiceType = t.nodeValue;
201 } 201 }
202 202
203 serviceType = t.nodeValue; 203 serviceType = t.nodeValue;
204 html_types += "<strong>Type:</strong> " + t.nodeValue + "<br/>"; 204 html_types += "<strong>Type:</strong> " + t.nodeValue + "<br/>";
205 } 205 }
206 } 206 }
207 207
208 // get the paths 208 // get the paths
209 res = runExpr(doc, srv, "xrd:Path/text()"); 209 res = runExpr(doc, srv, "xrd:Path/text()");
210 var p; 210 var p;
211 var qxri_prefix = qxri; 211 var qxri_prefix = qxri;
212 if (qxri_prefix.charAt(qxri_prefix.length - 1) != '/') { 212 if (qxri_prefix.charAt(qxri_prefix.length - 1) != '/') {
213 qxri_prefix += '/'; 213 qxri_prefix += '/';
214 } 214 }
215 215
216 while (p = res.iterateNext()) { 216 while (p = res.iterateNext()) {
217 if (p.nodeValue) { 217 if (p.nodeValue) {
218 html_paths += "<strong>Path:</strong> " + p.nodeValue 218 html_paths += "<strong>Path:</strong> " + p.nodeValue
219 + " [ <tt><a href=\"" + qxri_prefix + p.nodeValue + "\">" 219 + " [ <tt><a href=\"" + qxri_prefix + p.nodeValue + "\">"
220 + qxri_prefix + p.nodeValue + "</a></tt> ]" 220 + qxri_prefix + p.nodeValue + "</a></tt> ]"
221 + "<br/>\n"; 221 + "<br/>\n";
222 } 222 }
223 } 223 }
224 224
225 225
226 // get the mediatypes 226 // get the mediatypes
227 mediaTypes = new Array(); 227 mediaTypes = new Array();
228 res = runExpr(doc, srv, "xrd:MediaType/text()"); 228 res = runExpr(doc, srv, "xrd:MediaType/text()");
229 var m; 229 var m;
230 while (m = res.iterateNext()) { 230 while (m = res.iterateNext()) {
231 if (!knownServiceType) { 231 if (!knownServiceType) {
232 var srvType = guessServiceTypeByMime(m.nodeValue); 232 var srvType = guessServiceTypeByMime(m.nodeValue);
233 knownServiceType = srvType? srvType : null; 233 knownServiceType = srvType? srvType : null;
234 } 234 }
235 235
236 mediaTypes.push(m.nodeValue); 236 mediaTypes.push(m.nodeValue);
237 if (m.nodeValue) { 237 if (m.nodeValue) {
238 html_mediatypes += "<strong>Media Type:</strong> " + m.nodeValue + "<br/>"; 238 html_mediatypes += "<strong>Media Type:</strong> " + m.nodeValue + "<br/>";
239 } 239 }
240 } 240 }
241 241
242 242
243 res = runExpr(doc, srv, "xrd:URI"); 243 res = runExpr(doc, srv, "xrd:URI");
244 var uu; 244 var uu;
245 while (uu = res.iterateNext()) { 245 while (uu = res.iterateNext()) {
246 var u = uu.firstChild; 246 var u = uu.firstChild;
247 if (!(u.nodeValue && u.nodeType==3)) 247 if (!(u.nodeValue && u.nodeType==3))
248 continue; 248 continue;
249 249
250 var srvType = guessServiceTypeByURI(u.nodeValue); 250 var srvType = guessServiceTypeByURI(u.nodeValue);
251 if (!knownServiceType) { 251 if (!knownServiceType) {
252 knownServiceType = srvType; 252 knownServiceType = srvType;
253 } 253 }
254 254
255 html_uris += "<div class=\"" + getServiceClass(srvType) + "\">"; 255 html_uris += "<div class=\"" + getServiceClass(srvType) + "\">";
256 256
257 var linkContent = u.nodeValue; 257 var linkContent = u.nodeValue;
258 var uriParts = u.nodeValue.match('^(.*):(.*)$'); 258 var uriParts = u.nodeValue.match('^(.*):(.*)$');
259 if (!uriParts) 259 if (!uriParts)
260 continue; 260 continue;
261 261
262 if (uriParts[1] == 'data') { 262 if (uriParts[1] == 'data') {
263 uriParts = uriParts[2].match('^(.*/.*),(.*)'); 263 uriParts = uriParts[2].match('^(.*/.*),(.*)');
264 if (uriParts && uriParts[1].match('^image/', 'i')) { 264 if (uriParts && uriParts[1].match('^image/', 'i')) {
265 linkContent = "<img src=\"" + u.nodeValue + "\"/>"; 265 linkContent = "<img src=\"" + u.nodeValue + "\"/>";
266 } 266 }
267 else if (uriParts) { 267 else if (uriParts) {
268 linkContent = uriParts[1] + " data"; 268 linkContent = uriParts[1] + " data";
269 } 269 }
270 } 270 }
271 else if (uriParts[1] == 'skype') { 271 else if (uriParts[1] == 'skype') {
272 uriParts = uriParts[2].match('^(.*)\\?(.*)'); 272 uriParts = uriParts[2].match('^(.*)\\?(.*)');
273 if (uriParts) { 273 if (uriParts) {
274 if (uriParts[2] == "call") { 274 if (uriParts[2] == "call") {
275 linkContent = "<img src=\"chrome://foxri/content/skype_call_large.png\" alt=\"Call " + uriParts[1] + "\"/>"; 275 linkContent = "<img src=\"chrome://foxri/content/skype_call_large.png\" alt=\"Call " + uriParts[1] + "\"/>";
276 } 276 }
277 else if (uriParts[2] == "chat") { 277 else if (uriParts[2] == "chat") {
278 linkContent = "<img src=\"chrome://foxri/content/skype_chat_large.png\" alt=\"Chat with " + uriParts[1] + "\"/>"; 278 linkContent = "<img src=\"chrome://foxri/content/skype_chat_large.png\" alt=\"Chat with " + uriParts[1] + "\"/>";
279 } 279 }
280 else if (uriParts[2] == "add") { 280 else if (uriParts[2] == "add") {
281 linkContent = "<img src=\"chrome://foxri/content/skype_add_large.png\" alt=\"Add " + uriParts[1] + " to Skype\"/>"; 281 linkContent = "<img src=\"chrome://foxri/content/skype_add_large.png\" alt=\"Add " + uriParts[1] + " to Skype\"/>";
282 } 282 }
283 } 283 }
284 } 284 }
285 else if (uriParts[1] == 'aim') { 285 else if (uriParts[1] == 'aim') {
286 uriParts = uriParts[2].match('^(.*)\\?.*screenname=([^&]*)', 'i'); 286 uriParts = uriParts[2].match('^(.*)\\?.*screenname=([^&]*)', 'i');
287 if (uriParts) { 287 if (uriParts) {
288 linkContent = "<img src=\"chrome://foxri/content/aim_logo.gif\" alt=\"Chat with " + uriParts[2] + "\"/> Chat with " + uriParts[2]; 288 linkContent = "<img src=\"chrome://foxri/content/aim_logo.gif\" alt=\"Chat with " + uriParts[2] + "\"/> Chat with " + uriParts[2];
289 } 289 }
290 } 290 }
291 291
292 var linkhref = u.nodeValue; 292 var linkhref = u.nodeValue;
293 var xrap = uu.getAttribute('append'); 293 var xrap = uu.getAttribute('append');
294 if(xrap=='qxri') { 294 if(xrap=='qxri') {
295 linkhref += qxri.replace(/^xri:\/\//,''); 295 linkhref += qxri.replace(/^xri:\/\//,'');
296 }else if(xrap=='authority') {
297 linkhref += qxri.replace(/^xri:\/\//,'').replace(/\//.*,'');
296 }else if(xrap!=null){ 298 }else if(xrap!=null){
297 dump("Unhandled @append: "+xrap+"\n"); 299 dump("Unhandled @append: "+xrap+"\n");
298 } 300 }
299 html_uris += "<a href=\""+linkhref+"\">" 301 html_uris += "<a href=\""+linkhref+"\">"
300 + linkContent + "</a>"; 302 + linkContent + "</a>";
301 html_uris += "</div>"; 303 html_uris += "</div>";
302 } 304 }
303 305
304 var html = "<div class=\"service srv_" + getServiceClass(knownServiceType) + "\">\n"; 306 var html = "<div class=\"service srv_" + getServiceClass(knownServiceType) + "\">\n";
305 html += html_types; 307 html += html_types;
306 html += html_paths; 308 html += html_paths;
307 html += html_mediatypes; 309 html += html_mediatypes;
308 if (html_uris) { 310 if (html_uris) {
309 html += "<strong>URI(s):</strong><br/>\n"; 311 html += "<strong>URI(s):</strong><br/>\n";
310 html += html_uris; 312 html += html_uris;
311 } 313 }
312 html += "</div>"; 314 html += "</div>";
313 315
314 return html; 316 return html;
315} 317}
316 318
317 319
318 320
319function isKnownServiceType(type) 321function isKnownServiceType(type)
320{ 322{
321 if (type.toLowerCase() in SERVICE_CLASSES) { 323 if (type.toLowerCase() in SERVICE_CLASSES) {
322 return true; 324 return true;
323 } 325 }
324 return false; 326 return false;
325} 327}
326 328
327function getServiceClass(type) 329function getServiceClass(type)
328{ 330{
329 if (type && isKnownServiceType(type)) { 331 if (type && isKnownServiceType(type)) {
330 return SERVICE_CLASSES[type.toLowerCase()]; 332 return SERVICE_CLASSES[type.toLowerCase()];
331 } 333 }
332 return type; 334 return type;
333} 335}
334 336
335 337
336function guessServiceTypeByURI(uri) 338function guessServiceTypeByURI(uri)
337{ 339{
338 if (uri == null || uri == "") { 340 if (uri == null || uri == "") {
339 return "unknown"; 341 return "unknown";
340 } 342 }
341 if (uri.match(/^https?:/i)) { 343 if (uri.match(/^https?:/i)) {
342 return "www"; 344 return "www";
343 } 345 }
344 else if (uri.match(/^skype:/i)) { 346 else if (uri.match(/^skype:/i)) {
345 return "skype"; 347 return "skype";
346 } 348 }
347 else if (uri.match(/^aim:/i)) { 349 else if (uri.match(/^aim:/i)) {
348 return "aim"; 350 return "aim";
349 } 351 }
350 else if (uri.match(/^xmpp:/i)) { 352 else if (uri.match(/^xmpp:/i)) {
351 return "jabber"; 353 return "jabber";
352 } 354 }
353 else if (uri.match(/^tel:/i)) { 355 else if (uri.match(/^tel:/i)) {
354 return "tel"; 356 return "tel";
355 } 357 }
356 else if (uri.match(/^callto:/i)) { 358 else if (uri.match(/^callto:/i)) {
357 return "callto"; 359 return "callto";
358 } 360 }
359 else if (uri.match(/^telnet:/i)) { 361 else if (uri.match(/^telnet:/i)) {
360 return "telnet"; 362 return "telnet";
361 } 363 }
362 else if (uri.match(/^news:/i)) { 364 else if (uri.match(/^news:/i)) {
363 return "news"; 365 return "news";
364 } 366 }
365 else if (uri.match(/^nntp:/i)) { 367 else if (uri.match(/^nntp:/i)) {
366 return "nntp"; 368 return "nntp";
367 } 369 }
368 else if (uri.match(/^ftp:/i)) { 370 else if (uri.match(/^ftp:/i)) {
369 return "ftp"; 371 return "ftp";
370 } 372 }
371 else if (uri.match(/^mailto:/i)) { 373 else if (uri.match(/^mailto:/i)) {
372 return "email"; 374 return "email";
373 } 375 }
374 else if (uri.match(/^urn:/i)) { 376 else if (uri.match(/^urn:/i)) {
375 return "urn"; 377 return "urn";
376 } 378 }
377 else if (uri.match(/^data:/i)) { 379 else if (uri.match(/^data:/i)) {
378 return "data"; 380 return "data";
379 } 381 }
380 else if (uri.match(/^feed:/i)) { 382 else if (uri.match(/^feed:/i)) {
381 return "feed"; 383 return "feed";
382 } 384 }
383 return "unknown"; 385 return "unknown";
384} 386}
385 387
386 388
387function guessServiceTypeByMime(mimeType) 389function guessServiceTypeByMime(mimeType)
388{ 390{
389 if (mimeType.match(/^application\/(rss|atom)\+xml/i)) { 391 if (mimeType.match(/^application\/(rss|atom)\+xml/i)) {
390 dump("feed detected!\n"); 392 dump("feed detected!\n");
391 return "feed"; 393 return "feed";
392 } 394 }
393 else if (mimeType.match(/^image\//i)) { 395 else if (mimeType.match(/^image\//i)) {
394 return "image"; 396 return "image";
395 } 397 }
396 return null; 398 return null;
397} 399}
398 400
399 401
400 402
401function friendlyServiceName(srvType, uri) 403function friendlyServiceName(srvType, uri)
402{ 404{
403 if (srvType && srvType == "xri://+i-service*(+contact)*($v*1.0)") { 405 if (srvType && srvType == "xri://+i-service*(+contact)*($v*1.0)") {
404 return "Contact Service"; 406 return "Contact Service";
405 } 407 }
406 else if (srvType && ( 408 else if (srvType && (
407 srvType == "http://openid.net/signon/1.0" 409 srvType == "http://openid.net/signon/1.0"
408 || srvType == "http://openid.net/signon/1.1" 410 || srvType == "http://openid.net/signon/1.1"
409 || srvType == "http://specs.openid.net/auth/2.0/signon" 411 || srvType == "http://specs.openid.net/auth/2.0/signon"
410 || srcType == "http://specs.openid.net/auth/2.0/server" 412 || srcType == "http://specs.openid.net/auth/2.0/server"
411 ) ) { 413 ) ) {
412 return "OpenID Authentication Service"; 414 return "OpenID Authentication Service";
413 } 415 }
414 else if (srvType && srvType == "xri://$res*auth*($v*2.0)") { 416 else if (srvType && srvType == "xri://$res*auth*($v*2.0)") {
415 return "Authority Resolution Service"; 417 return "Authority Resolution Service";
416 } 418 }
417 else { 419 else {
418 if (uri == null) { 420 if (uri == null) {
419 return "Generic Service"; 421 return "Generic Service";
420 } 422 }
421 if (uri.match(/^https?:/i)) { 423 if (uri.match(/^https?:/i)) {
422 return "Web Link"; 424 return "Web Link";
423 } 425 }
424 else if (uri.match(/^skype:/i)) { 426 else if (uri.match(/^skype:/i)) {
425 var user = uri.substring("skype:".length, uri.indexOf('?')); 427 var user = uri.substring("skype:".length, uri.indexOf('?'));
426 return "Skype <a href=\"" + uri + "\"><img src=\"chrome://foxri/content/skype_call.png\"></a>"; 428 return "Skype <a href=\"" + uri + "\"><img src=\"chrome://foxri/content/skype_call.png\"></a>";
427 } 429 }
428 else if (uri.match(/^mailto:/i)) { 430 else if (uri.match(/^mailto:/i)) {
429 var qmark = uri.indexOf('?'); 431 var qmark = uri.indexOf('?');
430 var email = (qmark == -1)? 432 var email = (qmark == -1)?
431 uri.substr("mailto:".length) : 433 uri.substr("mailto:".length) :
432 uri.substring("mailto:".length, qmark); 434 uri.substring("mailto:".length, qmark);
433 return "Email (address: " + email + ")"; 435 return "Email (address: " + email + ")";
434 } 436 }
435 else if (srvType != null) { 437 else if (srvType != null) {
436 return srvType; // return verbatim 438 return srvType; // return verbatim
437 } 439 }
438 return "Generic Service"; 440 return "Generic Service";
439 } 441 }
440} 442}
441 443
442 444
443 445
444 446
445function subHTML(template, vars) 447function subHTML(template, vars)
446{ 448{
447 for (key in vars) { 449 for (key in vars) {
448 template = template.replace(key, vars[key], 'g'); 450 template = template.replace(key, vars[key], 'g');
449 } 451 }
450 return template; 452 return template;
451} 453}
452 454
453 455
454/// Given the completed XMLHttpRequest object, renders the XRDS 456/// Given the completed XMLHttpRequest object, renders the XRDS
455function renderXRDS(xmlDoc) 457function renderXRDS(xmlDoc)
456{ 458{
457 var x = xmlDoc; 459 var x = xmlDoc;
458 var qxri = getString(x, x, "/xrds:XRDS/@ref"); 460 var qxri = getString(x, x, "/xrds:XRDS/@ref");
459 461
460 var html = subHTML(HTML_HEAD, { '#QXRI#': qxri }); 462 var html = subHTML(HTML_HEAD, { '#QXRI#': qxri });
461 463
462 // TODO: render parents as well 464 // TODO: render parents as well
463 465
464 var lastNode = getFinalXRD(x); 466 var lastNode = getFinalXRD(x);
465 if (lastNode) { 467 if (lastNode) {
466 var stat = getString(x, lastNode, "xrd:Status/@code"); 468 var stat = getString(x, lastNode, "xrd:Status/@code");
467 if (stat == "100") { 469 if (stat == "100") {
468 html += "<h3>Exploring <strong>" + qxri + "</strong></h3>"; 470 html += "<h3>Exploring <strong>" + qxri + "</strong></h3>";
469 } 471 }
470 else { 472 else {
471 var msg = getString(x, lastNode, "xrd:Status/text()"); 473 var msg = getString(x, lastNode, "xrd:Status/text()");
472 html += "<h3 class=\"error\"><strong>" + qxri + "</strong> failed to resolve (reason: " + stat + " - " + msg + ")</h3>"; 474 html += "<h3 class=\"error\"><strong>" + qxri + "</strong> failed to resolve (reason: " + stat + " - " + msg + ")</h3>";
473 } 475 }
474 476
475 html += "<br/>"; 477 html += "<br/>";
476 478
477 var services = runExpr(x, lastNode, "xrd:Service"); 479 var services = runExpr(x, lastNode, "xrd:Service");
478 var s; 480 var s;
479 var count = getNumeric(x, lastNode, "count(xrd:Service)"); 481 var count = getNumeric(x, lastNode, "count(xrd:Service)");
480 if (count > 0) { 482 if (count > 0) {
481 while (s = services.iterateNext()) { 483 while (s = services.iterateNext()) {
482 count++; 484 count++;
483 html += renderService(s, x, qxri); 485 html += renderService(s, x, qxri);
484 } 486 }
485 } 487 }
486 else if (stat == '222') { 488 else if (stat == '222') {
487 var xriType = isIName(qxri)? 'I-name' : 'I-number'; 489 var xriType = isIName(qxri)? 'I-name' : 'I-number';
488 html += "<p class='error'>" + xriType + " does not exist.</p>\n"; 490 html += "<p class='error'>" + xriType + " does not exist.</p>\n";
489 } 491 }
490 else { 492 else {
491 html += "<p>No service has been configured for this XRI</p>"; 493 html += "<p>No service has been configured for this XRI</p>";
492 } 494 }
493 495
494 } 496 }
495 497
496 html += "</html>"; 498 html += "</html>";
497 499
498 return html; 500 return html;
499} 501}
500 502
501 503
502 504
503 505
504 506
505 507
506/*********************************************************** 508/***********************************************************
507 XriServiceExplorer class definition 509 XriServiceExplorer class definition
508 ***********************************************************/ 510 ***********************************************************/
509 511
510 512
511function XRIChannel(uri) { 513function XRIChannel(uri) {
512 this.URI = uri; 514 this.URI = uri;
513 var r = uri.spec.indexOf('#'); 515 var r = uri.spec.indexOf('#');
514 if (r >= 0) { 516 if (r >= 0) {
515 this.qxri = uri.spec.substring(0, r); 517 this.qxri = uri.spec.substring(0, r);
516 this.fragment = uri.spec.substring(r); 518 this.fragment = uri.spec.substring(r);
517 } 519 }
518 else { 520 else {
519 this.qxri = uri.spec; 521 this.qxri = uri.spec;
520 } 522 }
521}; 523};
522 524
523 525
524XRIChannel.prototype = { 526XRIChannel.prototype = {
525 527
526 fragment: null, 528 fragment: null,
527 529
528/* private fields used internally */ 530/* private fields used internally */
529 qxri: null, 531 qxri: null,
530 532
531 xmlRequest: null, 533 xmlRequest: null,
532 534
533 renderedHTML: null, 535 renderedHTML: null,
534 536
535 scriptableInStream: null, 537 scriptableInStream: null,
536 538
537 buf: null, 539 buf: null,
538 540
539 mChannel: null, 541 mChannel: null,
540 542
541 543
542 copyFields: function(request) 544 copyFields: function(request)
543 { 545 {
544 dump("copyFields(loadFlags=" + request.loadFlags + ")\n"); 546 dump("copyFields(loadFlags=" + request.loadFlags + ")\n");
545 dump("loadGroup = " + request.loadGroup + "\n"); 547 dump("loadGroup = " + request.loadGroup + "\n");
546 dump("notificationCallbacks = " + request.notificationCallbacks + "\n"); 548 dump("notificationCallbacks = " + request.notificationCallbacks + "\n");
547 549
548 // copy request fields 550 // copy request fields
549 this.loadFlags = request.loadFlags; 551 this.loadFlags = request.loadFlags;
550 this.loadGroup = request.loadGroup; 552 this.loadGroup = request.loadGroup;
551 this.name = request.name; 553 this.name = request.name;
552 this.status = request.status; 554 this.status = request.status;
553 555
554 var channel = request.QueryInterface(nsIChannel); 556 var channel = request.QueryInterface(nsIChannel);
555 if (channel) { 557 if (channel) {
556 this.contentCharset = channel.contentCharset; 558 this.contentCharset = channel.contentCharset;
557 this.contentLength = channel.contentLength; 559 this.contentLength = channel.contentLength;
558 this.contentType = channel.contentType; // XXX 560 this.contentType = channel.contentType; // XXX
559 this.contentType = "text/html"; 561 this.contentType = "text/html";
560 this.notificationCallbacks = channel.notificationCallbacks; 562 this.notificationCallbacks = channel.notificationCallbacks;
561 this.originalURI = this.originalURI; 563 this.originalURI = this.originalURI;
562 this.URI = this.URI; 564 this.URI = this.URI;
563 this.owner = channel.owner; 565 this.owner = channel.owner;
564 this.securityInfo = channel.securityInfo; 566 this.securityInfo = channel.securityInfo;
565 567
566 channel = channel.QueryInterface(nsIHttpChannel); 568 channel = channel.QueryInterface(nsIHttpChannel);
567 if (channel) { 569 if (channel) {
568 this.allowPipelining = channel.allowPipelining; 570 this.allowPipelining = channel.allowPipelining;
569 this.redirectionLimit = channel.redirectionLimit; 571 this.redirectionLimit = channel.redirectionLimit;
570 this.referrer = channel.referrer; 572 this.referrer = channel.referrer;
571 this.requestMethod = channel.requestMethod; 573 this.requestMethod = channel.requestMethod;
572 this.requestSucceeded = channel.requestSucceeded; 574 this.requestSucceeded = channel.requestSucceeded;
573 this.responseStatus = channel.responseStatus; 575 this.responseStatus = channel.responseStatus;
574 this.responseStatusText = channel.responseStatusText; 576 this.responseStatusText = channel.responseStatusText;
575 } 577 }
576 } 578 }
577 579
578 }, 580 },
579 581
580 /* nsIStreamListener */ 582 /* nsIStreamListener */
581 asyncOpenListener: null, 583 asyncOpenListener: null,
582 584
583 /* nsISupports (but we really don't care) */ 585 /* nsISupports (but we really don't care) */
584 asyncOpenContext: null, 586 asyncOpenContext: null,
585 587
586 588
587 /* has the XML finished loading? */ 589 /* has the XML finished loading? */
588 loadDone: false, 590 loadDone: false,
589 591
590 592
591 593
592/* public fields (nsIStreamListener implementation) */ 594/* public fields (nsIStreamListener implementation) */
593 onDataAvailable : function(request, ctx, inputStream, offset, count) 595 onDataAvailable : function(request, ctx, inputStream, offset, count)
594 { 596 {
595 dump("\nonDataAvailable, offset=" + offset + ", count=" + count + "\n"); 597 dump("\nonDataAvailable, offset=" + offset + ", count=" + count + "\n");
596 598
597 // XXX 599 // XXX
598/* 600/*
599 this.copyFields(request); 601 this.copyFields(request);
600 this.asyncOpenListener.onDataAvailable(this, this.asyncOpenContext, inputStream, offset, count); 602 this.asyncOpenListener.onDataAvailable(this, this.asyncOpenContext, inputStream, offset, count);
601 return; 603 return;
602*/ 604*/
603 605
604 606
605 if (offset == 0) { 607 if (offset == 0) {
606 this.scriptableInStream.init(inputStream); 608 this.scriptableInStream.init(inputStream);
607 } 609 }
608 610
609 this.buf += this.scriptableInStream.read(count); 611 this.buf += this.scriptableInStream.read(count);
610 612
611 if (!request.isPending()) { 613 if (!request.isPending()) {
612 dump("request finished, buf = " + this.buf + "\n"); 614 dump("request finished, buf = " + this.buf + "\n");
613 615
614 this.scriptableInStream = null; 616 this.scriptableInStream = null;
615 } 617 }
616 else { 618 else {
617 dump("request pending...\n"); 619 dump("request pending...\n");
618 dump("buf so far = " + this.buf + "\n"); 620 dump("buf so far = " + this.buf + "\n");
619 } 621 }
620 }, 622 },
621 623
622 624
623/* public fields (nsIRequestObserver implementation) */ 625/* public fields (nsIRequestObserver implementation) */
624 onStartRequest : function(request, ctx) 626 onStartRequest : function(request, ctx)
625 { 627 {
626 dump("\nonStartRequest called\n"); 628 dump("\nonStartRequest called\n");
627 // XXX 629 // XXX
628 630
629 this.copyFields(request); 631 this.copyFields(request);
630 this.asyncOpenListener.onStartRequest(this, this.asyncOpenContext); 632 this.asyncOpenListener.onStartRequest(this, this.asyncOpenContext);
631 }, 633 },
632 634
633 635
634 onStopRequest : function(request, ctx, status) 636 onStopRequest : function(request, ctx, status)
635 { 637 {
636 dump("\nonStopRequest called - status " + status + "\n"); 638 dump("\nonStopRequest called - status " + status + "\n");
637 639
638 // XXX 640 // XXX
639/* 641/*
640 this.asyncOpenListener.onStopRequest(this, this.asyncOpenContext, status); 642 this.asyncOpenListener.onStopRequest(this, this.asyncOpenContext, status);
641 return; 643 return;
642*/ 644*/
643 645
644 this.copyFields(request); 646 this.copyFields(request);
645 this.loadDone = true; 647 this.loadDone = true;
646 648
647 if (status == 0) { 649 if (status == 0) {
648 650
649 var domParser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser); 651 var domParser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser);
650 var xmlDoc = domParser.parseFromString(this.buf, "text/xml"); 652 var xmlDoc = domParser.parseFromString(this.buf, "text/xml");
651 653
652 // make fake inputstream 654 // make fake inputstream
653 var renderedHTML = renderXRDS(xmlDoc); 655 var renderedHTML = renderXRDS(xmlDoc);
654 656
655 this.contentCharset = "UTF-8"; 657 this.contentCharset = "UTF-8";
656 this.contentLength = renderedHTML.length; 658 this.contentLength = renderedHTML.length;
657 this.contentType = "text/html"; 659 this.contentType = "text/html";
658 660
659 dump("rendered HTML = \n" + renderedHTML + "\n"); 661 dump("rendered HTML = \n" + renderedHTML + "\n");
660 662
661 dump("\nCalling asyncOpenListener.onStartRequest\n\n"); 663 dump("\nCalling asyncOpenListener.onStartRequest\n\n");
662 664
663 665
664 var strIStream = Components.classes["@mozilla.org/io/string-input-stream;1"].createInstance(Components.interfaces.nsIStringInputStream); 666 var strIStream = Components.classes["@mozilla.org/io/string-input-stream;1"].createInstance(Components.interfaces.nsIStringInputStream);
665 if (strIStream) { 667 if (strIStream) {
666 strIStream.setData(renderedHTML, renderedHTML.length); 668 strIStream.setData(renderedHTML, renderedHTML.length);
667/* 669/*
668 strIStream.setData(this.buf, this.buf.length); 670 strIStream.setData(this.buf, this.buf.length);
669*/ 671*/
670 dump("\nleftovers in string-input-stream = " + strIStream.available() + "\n"); 672 dump("\nleftovers in string-input-stream = " + strIStream.available() + "\n");
671 dump("\nCalling asyncOpenListener.onDataAvailable\n\n"); 673 dump("\nCalling asyncOpenListener.onDataAvailable\n\n");
672 this.asyncOpenListener.onDataAvailable(this, this.asyncOpenContext, strIStream, 0, renderedHTML.length); 674 this.asyncOpenListener.onDataAvailable(this, this.asyncOpenContext, strIStream, 0, renderedHTML.length);
673/* 675/*
674 this.asyncOpenListener.onDataAvailable(this, this.asyncOpenContext, strIStream, 0, this.buf.length); 676 this.asyncOpenListener.onDataAvailable(this, this.asyncOpenContext, strIStream, 0, this.buf.length);
675*/ 677*/
676 678
677 dump("\nleftovers in string-input-stream = " + strIStream.available() + "\n"); 679 dump("\nleftovers in string-input-stream = " + strIStream.available() + "\n");
678 } 680 }
679 } 681 }
680 else { 682 else {
681 dump("\nStatus = " + status + "\n"); 683 dump("\nStatus = " + status + "\n");
682 dump("Calling asyncOpenListener.onStartRequest\n\n"); 684 dump("Calling asyncOpenListener.onStartRequest\n\n");
683 this.asyncOpenListener.onStartRequest(this, this.asyncOpenContext); 685 this.asyncOpenListener.onStartRequest(this, this.asyncOpenContext);
684 } 686 }
685 687
686 dump("stopping request for underlying asyncOpenListener\n"); 688 dump("stopping request for underlying asyncOpenListener\n");
687 689
688 this.asyncOpenListener.onStopRequest(this, this.asyncOpenContext, status); 690 this.asyncOpenListener.onStopRequest(this, this.asyncOpenContext, status);
689 691
690 // copied from nsIWyciwygChannel 692 // copied from nsIWyciwygChannel
691 this.asyncOpenListener = null; 693 this.asyncOpenListener = null;
692 this.asyncOpenContext = null; 694 this.asyncOpenContext = null;
693 695
694/* 696/*
695 if (this.loadGroup) { 697 if (this.loadGroup) {
696 this.loadGroup.removeRequest(request, null, status); 698 this.loadGroup.removeRequest(request, null, status);
697 } 699 }
698*/ 700*/
699 701
700 this.notificationCallbacks = null; 702 this.notificationCallbacks = null;
701 this.mChannel = null; 703 this.mChannel = null;
702 704
703 dump("stopped request\n"); 705 dump("stopped request\n");
704 }, 706 },
705 707
706 708
707/* public fields (nsIInputStream implementation) */ 709/* public fields (nsIInputStream implementation) */
708 available: function() 710 available: function()
709 { 711 {
710 dump("nsIInputStream::available called\n"); 712 dump("nsIInputStream::available called\n");
711 return renderedHTML.length; 713 return renderedHTML.length;
712 }, 714 },
713 715
714 close: function() 716 close: function()
715 { 717 {
716 dump("nsIInputStream::close called\n"); 718 dump("nsIInputStream::close called\n");
717 }, 719 },
718 720
719 isNonBlocking: function() { 721 isNonBlocking: function() {
720 dump("nsIInputStream::isNonBlocking called\n"); 722 dump("nsIInputStream::isNonBlocking called\n");
721 return true; 723 return true;
722 }, 724 },
723 725
724 read: function() { dump("nsIInputStream::read() called!!!\n"); }, 726 read: function() { dump("nsIInputStream::read() called!!!\n"); },
725 727
726 728
727 729
728 730
729 731
730/* public fields (nsIRequest implmentation) */ 732/* public fields (nsIRequest implmentation) */
731 733
732 loadFlags: 0, 734 loadFlags: 0,
733 735
734 loadGroup: null, 736 loadGroup: null,
735 737
736 name: "xri://request", 738 name: "xri://request",
737 739
738 status: 0, 740 status: 0,
739 741
740 cancel: function(status) { dump("\ncancel called...\n"); }, 742 cancel: function(status) { dump("\ncancel called...\n"); },
741 743
742 isPending: function() { 744 isPending: function() {
743 dump("isPending called\n\n"); 745 dump("isPending called\n\n");
744 return !this.loadDone; 746 return !this.loadDone;
745 }, 747 },
746 748
747 resume: function() { dump("resume called\n"); }, 749 resume: function() { dump("resume called\n"); },
748 750
749 suspend: function() { dump("suspend called\n"); }, 751 suspend: function() { dump("suspend called\n"); },
750 752
751 753
752 754
753/* public fields (nsIChannel implmentation) */ 755/* public fields (nsIChannel implmentation) */
754 756
755 contentCharset: null, 757 contentCharset: null,
756 758
757 contentLength: -1, 759 contentLength: -1,
758 760
759 contentType: null, 761 contentType: null,
760 762
761 notificationCallbacks: null, 763 notificationCallbacks: null,
762 764
763 originalURI: null, 765 originalURI: null,
764 766
765 owner: null, 767 owner: null,
766 768
767 securityInfo: null, 769 securityInfo: null,
768 770
769 URI: null, 771 URI: null,
770 772
771 open: function() 773 open: function()
772 { 774 {
773 dump("open not supporteD!!!!!!\n"); 775 dump("open not supporteD!!!!!!\n");
774 }, 776 },
775 777
776 asyncOpen: function(listener, context) 778 asyncOpen: function(listener, context)
777 { 779 {
778 dump("asyncOpen called!!!!!!\n"); 780 dump("asyncOpen called!!!!!!\n");
779 this.asyncOpenListener = listener; 781 this.asyncOpenListener = listener;
780 this.asyncOpenContext = context; 782 this.asyncOpenContext = context;
781 783
782 var hxri = PROXY_URI + this.qxri 784 var hxri = PROXY_URI + this.qxri
783 + "?_xrd_r=application/xrds%2Bxml;sep=false"; 785 + "?_xrd_r=application/xrds%2Bxml;sep=false";
784 var ioService = Components.classesByID[kIOSERVICE_CID_STR].getService(); 786 var ioService = Components.classesByID[kIOSERVICE_CID_STR].getService();
785 ioService = ioService.QueryInterface(nsIIOService); 787 ioService = ioService.QueryInterface(nsIIOService);
786 var channel = ioService.newChannel(hxri, null, null); 788 var channel = ioService.newChannel(hxri, null, null);
787 789
788 if (this.scriptableInStream) { 790 if (this.scriptableInStream) {
789 dump("Hey! You can't possibly be reusing this handler?!\n"); 791 dump("Hey! You can't possibly be reusing this handler?!\n");
790 return; 792 return;
791 } 793 }
792 794
793 dump("making scriptableInStream\n"); 795 dump("making scriptableInStream\n");
794 this.scriptableInStream = Components.classes["@mozilla.org/scriptableinputstream;1"] 796 this.scriptableInStream = Components.classes["@mozilla.org/scriptableinputstream;1"]
795 .createInstance(Components.interfaces.nsIScriptableInputStream); 797 .createInstance(Components.interfaces.nsIScriptableInputStream);
796 798
797 this.buf = ''; 799 this.buf = '';
798 800
799 dump("notificationCallbacks = " + this.notificationCallbacks + "\n"); 801 dump("notificationCallbacks = " + this.notificationCallbacks + "\n");
800 dump("loadFlags = " + this.loadFlags + "\n"); 802 dump("loadFlags = " + this.loadFlags + "\n");
801 dump("loadGroup = " + this.loadGroup + "\n"); 803 dump("loadGroup = " + this.loadGroup + "\n");
802 dump("owner = " + this.owner + "\n"); 804 dump("owner = " + this.owner + "\n");
803 dump("securityInfo = " + this.securityInfo + "\n"); 805 dump("securityInfo = " + this.securityInfo + "\n");
804 806
805 // these nsIRequest attributes must be copied to the stub 807 // these nsIRequest attributes must be copied to the stub
806 // channel that we created 808 // channel that we created
807 channel.notificationCallbacks = this.notificationCallbacks; 809 channel.notificationCallbacks = this.notificationCallbacks;
808 channel.loadGroup = this.loadGroup; 810 channel.loadGroup = this.loadGroup;
809 channel.loadFlags = this.loadFlags; 811 channel.loadFlags = this.loadFlags;
810 812
811 this.mChannel = channel; 813 this.mChannel = channel;
812 channel.asyncOpen(this, null); 814 channel.asyncOpen(this, null);
813 }, 815 },
814 816
815 817
816/* public fields (nsIChannel implementation) */ 818/* public fields (nsIChannel implementation) */
817 allowPipelining: false, 819 allowPipelining: false,
818 redirectionLimit: 5, 820 redirectionLimit: 5,
819 referrer: "", 821 referrer: "",
820 requestMethod: "GET", 822 requestMethod: "GET",
821 requestSucceeded: true, 823 requestSucceeded: true,
822 responseStatus: 200, 824 responseStatus: 200,
823 responseStatusText: "OK", 825 responseStatusText: "OK",
824 getRequestHeader: function(header) { 826 getRequestHeader: function(header) {
825 dump("getRequestHeader(" + header + ")\n"); 827 dump("getRequestHeader(" + header + ")\n");
826 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel); 828 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel);
827 829
828 try { 830 try {
829 var val = httpChannel.getRequestHeader(header); 831 var val = httpChannel.getRequestHeader(header);
830 dump("getRequestHeader(" + header + ") = " + val + "\n"); 832 dump("getRequestHeader(" + header + ") = " + val + "\n");
831 return val; 833 return val;
832 } 834 }
833 catch (e) { 835 catch (e) {
834 dump("getRequestHeader - got exception: " + e + "\n"); 836 dump("getRequestHeader - got exception: " + e + "\n");
835 throw e; 837 throw e;
836 } 838 }
837 }, 839 },
838 getResponseHeader: function(header) { 840 getResponseHeader: function(header) {
839 dump("getResponseHeader(" + header + ")\n"); 841 dump("getResponseHeader(" + header + ")\n");
840 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel); 842 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel);
841 843
842 try { 844 try {
843 var val = httpChannel.getResponseHeader(header); 845 var val = httpChannel.getResponseHeader(header);
844 dump("getResponseHeader(" + header + ") = " + val + "\n"); 846 dump("getResponseHeader(" + header + ") = " + val + "\n");
845 return val; 847 return val;
846 } 848 }
847 catch (e) { 849 catch (e) {
848 dump("getResponseHeader - got exception: " + e + "\n"); 850 dump("getResponseHeader - got exception: " + e + "\n");
849 throw e; 851 throw e;
850 } 852 }
851 return null; 853 return null;
852 }, 854 },
853 isNoCacheResponse: function() { 855 isNoCacheResponse: function() {
854 dump("isNoCacheResponse()\n"); 856 dump("isNoCacheResponse()\n");
855 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel); 857 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel);
856 return httpChannel.isNoCacheResponse(); 858 return httpChannel.isNoCacheResponse();
857 }, 859 },
858 isNoStoreResponse: function() { 860 isNoStoreResponse: function() {
859 dump("isNoStoreResponse()\n"); 861 dump("isNoStoreResponse()\n");
860 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel); 862 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel);
861 return httpChannel.isNoStoreResponse(); 863 return httpChannel.isNoStoreResponse();
862 return true; 864 return true;
863 }, 865 },
864 setRequestHeader: function(header, value, merge) { 866 setRequestHeader: function(header, value, merge) {
865 dump("setRequestHeader(" + header + ", " + value + ")\n"); 867 dump("setRequestHeader(" + header + ", " + value + ")\n");
866 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel); 868 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel);
867 return httpChannel.setRequestHeader(header, value, merge); 869 return httpChannel.setRequestHeader(header, value, merge);
868 }, 870 },
869 setResponseHeader: function(header, value, merge) { 871 setResponseHeader: function(header, value, merge) {
870 dump("setResponseHeader(" + header + ", " + value + ")\n"); 872 dump("setResponseHeader(" + header + ", " + value + ")\n");
871 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel); 873 var httpChannel = this.mChannel.QueryInterface(nsIHttpChannel);
872 return httpChannel.setResponseHeader(header, value, merge); 874 return httpChannel.setResponseHeader(header, value, merge);
873 }, 875 },
874 visitRequestHeaders: function(visitor) { 876 visitRequestHeaders: function(visitor) {
875 dump("visitRequestHeaders()\n"); 877 dump("visitRequestHeaders()\n");
876 }, 878 },
877 visitResponseHeaders: function(visitor) { 879 visitResponseHeaders: function(visitor) {
878 dump("visitResponseHeaders()\n"); 880 dump("visitResponseHeaders()\n");
879 }, 881 },
880 882
881 QueryInterface: function(iid) 883 QueryInterface: function(iid)
882 { 884 {
883 dump("QI.. \n"); 885 dump("QI.. \n");
884 if (iid.equals(nsIChannel)) 886 if (iid.equals(nsIChannel))
885 dump("QI(nsIChannel)\n"); 887 dump("QI(nsIChannel)\n");
886 else if (iid.equals(nsIHttpChannel)) 888 else if (iid.equals(nsIHttpChannel))
887 dump("QI(nsIHttpChannel)\n"); 889 dump("QI(nsIHttpChannel)\n");
888 else if (iid.equals(Components.interfaces.nsIUploadChannel)) 890 else if (iid.equals(Components.interfaces.nsIUploadChannel))
889 dump("QI(nsIUploadChannel) - not supported\n"); 891 dump("QI(nsIUploadChannel) - not supported\n");
890 else if (iid.equals(Components.interfaces.nsICachingChannel)) 892 else if (iid.equals(Components.interfaces.nsICachingChannel))
891 dump("QI(nsICachingChannel) - not supported\n"); 893 dump("QI(nsICachingChannel) - not supported\n");
892 else if (iid.equals(Components.interfaces.nsIClassInfo)) 894 else if (iid.equals(Components.interfaces.nsIClassInfo))
893 dump("QI(nsIClassInfo) - not supported\n"); 895 dump("QI(nsIClassInfo) - not supported\n");
894 else if (iid.equals(Components.interfaces.nsISecurityCheckedComponent)) 896 else if (iid.equals(Components.interfaces.nsISecurityCheckedComponent))
895 dump("QI(nsISecurityCheckedComponent) - not supported\n"); 897 dump("QI(nsISecurityCheckedComponent) - not supported\n");
896 else if (iid.equals(Components.interfaces.nsIWyciwygChannel)) 898 else if (iid.equals(Components.interfaces.nsIWyciwygChannel))
897 dump("QI(nsIWyciwygChannel) - not supported\n"); 899 dump("QI(nsIWyciwygChannel) - not supported\n");
898 else if (iid.equals(Components.interfaces.nsIMultiPartChannel)) 900 else if (iid.equals(Components.interfaces.nsIMultiPartChannel))
899 dump("QI(nsIMultiPartChannel) - not supported\n"); 901 dump("QI(nsIMultiPartChannel) - not supported\n");
900 else if (iid.equals(Components.interfaces.nsIHttpChannelInternal)) 902 else if (iid.equals(Components.interfaces.nsIHttpChannelInternal))
901 dump("QI(nsIHttpChannelInternal) - not supported\n"); 903 dump("QI(nsIHttpChannelInternal) - not supported\n");
902 else if (iid.equals(Components.interfaces.nsIWritablePropertyBag2)) 904 else if (iid.equals(Components.interfaces.nsIWritablePropertyBag2))
903 dump("QI(nsIWritablePropertyBag2) - not supported\n"); 905 dump("QI(nsIWritablePropertyBag2) - not supported\n");
904 else if (iid.equals(nsIRequest)) 906 else if (iid.equals(nsIRequest))
905 dump("QI(nsIRequest)\n"); 907 dump("QI(nsIRequest)\n");
906 else if (iid.equals(nsIRequestObserver)) 908 else if (iid.equals(nsIRequestObserver))
907 dump("QI(nsIRequestObserver)\n"); 909 dump("QI(nsIRequestObserver)\n");
908 else if (iid.equals(nsISupports)) 910 else if (iid.equals(nsISupports))
909 dump("QI(nsISupports)\n"); 911 dump("QI(nsISupports)\n");
910 else if (iid.equals(nsIStreamListener)) 912 else if (iid.equals(nsIStreamListener))
911 dump("QI(nsIStreamListener)\n"); 913 dump("QI(nsIStreamListener)\n");
912 else 914 else
913 dump("unknown " + iid + "\n"); 915 dump("unknown " + iid + "\n");
914 916
915 if (iid.equals(nsISupports) || 917 if (iid.equals(nsISupports) ||
916 iid.equals(nsIRequest) || 918 iid.equals(nsIRequest) ||
917 iid.equals(nsIRequestObserver) || 919 iid.equals(nsIRequestObserver) ||
918 iid.equals(nsIChannel) || 920 iid.equals(nsIChannel) ||
919 iid.equals(nsIHttpChannel) || 921 iid.equals(nsIHttpChannel) ||
920 iid.equals(nsIStreamListener) 922 iid.equals(nsIStreamListener)
921 ) { 923 ) {
922 return this; 924 return this;
923 } 925 }
924 926
925 throw Components.results.NS_ERROR_NO_INTERFACE; 927 throw Components.results.NS_ERROR_NO_INTERFACE;
926 } 928 }
927}; 929};
928 930
929 931
930 932
931/*********************************************************** 933/***********************************************************
932 XriProtocolHandler class definition 934 XriProtocolHandler class definition
933 ***********************************************************/ 935 ***********************************************************/
934 936
935//class constructor 937//class constructor
936function XriProtocolHandler() { 938function XriProtocolHandler() {
937}; 939};
938 940
939// class definition 941// class definition
940XriProtocolHandler.prototype = { 942XriProtocolHandler.prototype = {
941 defaultPort: 80, // HTTP 943 defaultPort: 80, // HTTP
942 944
943 protocolFlags : nsIProtocolHandler.ALLOWS_PROXY | nsIProtocolHandler.ALLOWS_PROXY_HTTP, 945 protocolFlags : nsIProtocolHandler.ALLOWS_PROXY | nsIProtocolHandler.ALLOWS_PROXY_HTTP,
944 946
945 scheme: "xri", 947 scheme: "xri",
946 948
947 allowPort: function() { 949 allowPort: function() {
948 return false; // only called for blacklisted ports, should respect 950 return false; // only called for blacklisted ports, should respect
949 }, 951 },
950 952
951 _newHttpChannel: function(aURI) 953 _newHttpChannel: function(aURI)
952 { 954 {
953 var HXRI = PROXY_URI + aURI.spec; 955 var HXRI = PROXY_URI + aURI.spec;
954 var ioService = Components.classesByID[kIOSERVICE_CID_STR].getService(); 956 var ioService = Components.classesByID[kIOSERVICE_CID_STR].getService();
955 ioService = ioService.QueryInterface(nsIIOService); 957 ioService = ioService.QueryInterface(nsIIOService);
956 var channel = ioService.newChannel(HXRI, null, null); 958 var channel = ioService.newChannel(HXRI, null, null);
957 return channel; 959 return channel;
958 }, 960 },
959 961
960 newChannel: function(aURI) 962 newChannel: function(aURI)
961 { 963 {
962 // leave alone if path is not empty or just a single slash or query exists 964 // leave alone if path is not empty or just a single slash or query exists
963 965
964 dump("path='" + aURI.path + "'\n"); 966 dump("path='" + aURI.path + "'\n");
965 dump("query='" + aURI.query + "'\n"); 967 dump("query='" + aURI.query + "'\n");
966 dump("spec='" + aURI.spec + "'\n"); 968 dump("spec='" + aURI.spec + "'\n");
967 969
968 var slashPos = aURI.spec.indexOf('/', 'xri://'.length); 970 var slashPos = aURI.spec.indexOf('/', 'xri://'.length);
969 var qmarkPos = aURI.spec.indexOf('?'); 971 var qmarkPos = aURI.spec.indexOf('?');
970 dump("slashPos='" + slashPos + "'\n"); 972 dump("slashPos='" + slashPos + "'\n");
971 dump("qmarkPos='" + qmarkPos + "'\n"); 973 dump("qmarkPos='" + qmarkPos + "'\n");
972 if ((slashPos > 0 && slashPos < aURI.spec.length - 1) || qmarkPos > -1) { 974 if ((slashPos > 0 && slashPos < aURI.spec.length - 1) || qmarkPos > -1) {
973 return this._newHttpChannel(aURI); 975 return this._newHttpChannel(aURI);
974 } 976 }
975 977
976 var explorer = new XRIChannel(aURI); 978 var explorer = new XRIChannel(aURI);
977 return explorer; 979 return explorer;
978 }, 980 },
979 981
980 982
981 newURI: function(spec, originCharset, baseURI) 983 newURI: function(spec, originCharset, baseURI)
982 { 984 {
983 var newSpec = spec; 985 var newSpec = spec;
984 if (baseURI != null) { 986 if (baseURI != null) {
985 // standard-url (nsIURL) does not work with @-GCS 987 // standard-url (nsIURL) does not work with @-GCS
986 var baseURL = Components.classes[CID_URL].createInstance(nsIURL); 988 var baseURL = Components.classes[CID_URL].createInstance(nsIURL);
987 baseURL.spec = baseURI.spec; 989 baseURL.spec = baseURI.spec;
988 newSpec = baseURL.resolve(spec); 990 newSpec = baseURL.resolve(spec);
989 } 991 }
990 992
991 var uri = Components.classes[CID_URI].createInstance(nsIURI); 993 var uri = Components.classes[CID_URI].createInstance(nsIURI);
992 uri.spec = newSpec; 994 uri.spec = newSpec;
993 return uri; 995 return uri;
994 }, 996 },
995 997
996 QueryInterface: function(aIID) 998 QueryInterface: function(aIID)
997 { 999 {
998 if (!aIID.equals(nsIProtocolHandler) && 1000 if (!aIID.equals(nsIProtocolHandler) &&
999 !aIID.equals(nsISupports)) 1001 !aIID.equals(nsISupports))
1000 throw Components.results.NS_ERROR_NO_INTERFACE; 1002 throw Components.results.NS_ERROR_NO_INTERFACE;
1001 return this; 1003 return this;
1002 } 1004 }
1003}; 1005};
1004 1006
1005 1007
1006/*********************************************************** 1008/***********************************************************
1007 class factory 1009 class factory
1008 1010
1009 This object is a member of the global-scope Components.classes. 1011 This object is a member of the global-scope Components.classes.
1010 It is keyed off of the contract ID. Eg: 1012 It is keyed off of the contract ID. Eg:
1011 1013
1012 myXriProtocolHandler = Components.classes["@dietrich.ganx4.com/helloworld;1"]. 1014 myXriProtocolHandler = Components.classes["@dietrich.ganx4.com/helloworld;1"].
1013 createInstance(Components.interfaces.nsIXriProtocolHandler); 1015 createInstance(Components.interfaces.nsIXriProtocolHandler);
1014 1016
1015 ***********************************************************/ 1017 ***********************************************************/
1016var XriProtocolHandlerFactory = { 1018var XriProtocolHandlerFactory = {
1017 createInstance: function (aOuter, aIID) 1019 createInstance: function (aOuter, aIID)
1018 { 1020 {
1019 if (aOuter != null) 1021 if (aOuter != null)
1020 throw Components.results.NS_ERROR_NO_AGGREGATION; 1022 throw Components.results.NS_ERROR_NO_AGGREGATION;
1021 return (new XriProtocolHandler()).QueryInterface(aIID); 1023 return (new XriProtocolHandler()).QueryInterface(aIID);
1022 } 1024 }
1023}; 1025};
1024 1026
1025 1027
1026/*********************************************************** 1028/***********************************************************
1027 module definition (xpcom registration) 1029 module definition (xpcom registration)
1028 ***********************************************************/ 1030 ***********************************************************/
1029var XriProtocolHandlerModule = { 1031var XriProtocolHandlerModule = {
1030 1032
1031 _firstTime: true, 1033 _firstTime: true,
1032 1034
1033 registerSelf: function(aCompMgr, aFileSpec, aLocation, aType) 1035 registerSelf: function(aCompMgr, aFileSpec, aLocation, aType)
1034 { 1036 {
1035 if (this._firstTime) { 1037 if (this._firstTime) {
1036 this._firstTime = false; 1038 this._firstTime = false;
1037 throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN; 1039 throw Components.results.NS_ERROR_FACTORY_REGISTER_AGAIN;
1038 } 1040 }
1039 aCompMgr = aCompMgr. 1041 aCompMgr = aCompMgr.
1040 QueryInterface(Components.interfaces.nsIComponentRegistrar); 1042 QueryInterface(Components.interfaces.nsIComponentRegistrar);
1041 aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME, 1043 aCompMgr.registerFactoryLocation(CLASS_ID, CLASS_NAME,
1042 CONTRACT_ID, aFileSpec, aLocation, aType); 1044 CONTRACT_ID, aFileSpec, aLocation, aType);
1043 }, 1045 },
1044 1046
1045 unregisterSelf: function(aCompMgr, aLocation, aType) 1047 unregisterSelf: function(aCompMgr, aLocation, aType)
1046 { 1048 {
1047 aCompMgr = aCompMgr. 1049 aCompMgr = aCompMgr.
1048 QueryInterface(Components.interfaces.nsIComponentRegistrar); 1050 QueryInterface(Components.interfaces.nsIComponentRegistrar);
1049 aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation); 1051 aCompMgr.unregisterFactoryLocation(CLASS_ID, aLocation);
1050 }, 1052 },
1051 1053
1052 getClassObject: function(aCompMgr, aCID, aIID) 1054 getClassObject: function(aCompMgr, aCID, aIID)
1053 { 1055 {
1054 if (!aIID.equals(Components.interfaces.nsIFactory)) 1056 if (!aIID.equals(Components.interfaces.nsIFactory))
1055 throw Components.results.NS_ERROR_NOT_IMPLEMENTED; 1057 throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
1056 1058
1057 if (aCID.equals(CLASS_ID)) 1059 if (aCID.equals(CLASS_ID))
1058 return XriProtocolHandlerFactory; 1060 return XriProtocolHandlerFactory;
1059 1061
1060 throw Components.results.NS_ERROR_NO_INTERFACE; 1062 throw Components.results.NS_ERROR_NO_INTERFACE;
1061 }, 1063 },
1062 1064
1063 canUnload: function(aCompMgr) { return true; } 1065 canUnload: function(aCompMgr) { return true; }