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