summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (show 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,491 +1,507 @@
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