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