~ubuntu-branches/debian/stretch/foxyproxy/stretch

« back to all changes in this revision

Viewing changes to src/components/foxyproxyprotocolhandler.js

  • Committer: Bazaar Package Importer
  • Author(s): Yaroslav Halchenko
  • Date: 2010-02-22 08:34:53 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20100222083453-23zgkfv5c7ybcj54
Tags: 2.19.1-1
New upstream release with a security fix on top of 2.19.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
  FoxyProxy
 
3
  Copyright (C) 2006-2010 LeahScape, Inc.
 
4
  http://foxyproxy.mozdev.org/
 
5
  eric.jung@yahoo.com
 
6
 
 
7
  This source code is released under the GPL license,
 
8
  available in the LICENSE file at the root of this installation
 
9
  and also online at http://www.gnu.org/licenses/gpl.txt
 
10
**/
 
11
 
 
12
// Thanks for the template, doron (http://www.nexgenmedia.net/docs/protocol/)
 
13
const kSCHEME = "proxy";
 
14
const kPROTOCOL_NAME = "FoxyProxy Protocol";
 
15
const kPROTOCOL_CONTRACTID = "@mozilla.org/network/protocol;1?name=" + kSCHEME;
 
16
const kPROTOCOL_CID = Components.ID("d1362868-da85-4faa-b1bf-24bfd936b0a6");
 
17
var CI = Components.interfaces, CC = Components.classes, CR = Components.results;
 
18
 
 
19
const kSIMPLEURI_CONTRACTID = "@mozilla.org/network/simple-uri;1";
 
20
const kIOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
 
21
const nsISupports = Components.interfaces.nsISupports;
 
22
const nsIIOService = Components.interfaces.nsIIOService;
 
23
const nsIProtocolHandler = Components.interfaces.nsIProtocolHandler;
 
24
const nsIURI = Components.interfaces.nsIURI;
 
25
const IOS = CC[kIOSERVICE_CONTRACTID].
 
26
        getService(nsIIOService).getProtocolHandler("file").
 
27
        QueryInterface(CI.nsIFileProtocolHandler);
 
28
 
 
29
function Protocol() {}
 
30
 
 
31
Protocol.prototype = {
 
32
  QueryInterface: function(iid) {
 
33
    if (!iid.equals(nsIProtocolHandler) &&
 
34
        !iid.equals(nsISupports))
 
35
      throw Components.results.NS_ERROR_NO_INTERFACE;
 
36
    return this;
 
37
  },
 
38
 
 
39
  scheme: kSCHEME,
 
40
  defaultPort: -1,
 
41
  protocolFlags: nsIProtocolHandler.URI_LOADABLE_BY_ANYONE,
 
42
 
 
43
  allowPort: function(port, scheme) {
 
44
    return false;
 
45
  },
 
46
 
 
47
  newURI: function(spec, charset, baseURI) {
 
48
    var uri = CC[kSIMPLEURI_CONTRACTID].createInstance(nsIURI);
 
49
    uri.spec = spec;
 
50
    return uri;
 
51
  },
 
52
 
 
53
  processURI : function(aURI) {
 
54
    // aURI is a nsIUri, so get a string from it using .spec
 
55
    var uri = aURI.spec;
 
56
    // strip away the proxy: part
 
57
    uri = uri.substring(uri.indexOf(":") + 1, uri.length);
 
58
    // and, optionally, leading // as in proxy://
 
59
    if (uri.indexOf("//") == 0)
 
60
      uri = uri.substring(2);    
 
61
    uri = decodeURI(uri);
 
62
    // e.g. proxy:ip=xx.xx.xx.xx&port=yyyyy
 
63
    // Parse query params into nameValuePairs array
 
64
    var count = 0, nameValuePairs = [], queryParams = uri.split('&'), foundSomeInput;
 
65
    for (var i in queryParams) {
 
66
      var pair = queryParams[i].split('=');
 
67
      if (pair.length == 2) {
 
68
        nameValuePairs[pair[0]] = pair[1];
 
69
        foundSomeInput = true;
 
70
      }
 
71
    }
 
72
    if (!foundSomeInput) return;
 
73
    var proxy = CC["@leahscape.org/foxyproxy/proxy;1"].createInstance().wrappedJSObject;
 
74
    proxy.fromAssociateArray(nameValuePairs);
 
75
    // We accept URIs like this:
 
76
    //   proxy:foxyProxyMode=disabled
 
77
    // with no other parameters. In cases like that, we must skip the
 
78
    // create/update/delete proxy code otherwise we'll create an empty/useless proxy
 
79
    // Note: |uri| has been stripped of its scheme at this point.
 
80
    var fp = CC["@leahscape.org/foxyproxy/service;1"].getService().wrappedJSObject;
 
81
    if (!(/^foxyProxyMode=[^&]*$/.test(uri))) {
 
82
      // Are we adding a new proxy, or deleting or updating an existing one? Default is to updateOrAdd.
 
83
      if (!nameValuePairs["action"]) { /* no action was specified */
 
84
          nameValuePairs["action"] = "updateOrAdd";
 
85
      }
 
86
      switch (nameValuePairs["action"]) {
 
87
        case "update":
 
88
          var p = fp.proxies.mergeByName(proxy, nameValuePairs);
 
89
          if (p) {
 
90
            proxy = p;
 
91
            fp.broadcast(null, "foxyproxy-proxy-change");
 
92
          }
 
93
          break;
 
94
        case "add":
 
95
          fp.proxies.insertAt(nameValuePairs["position"], proxy);
 
96
          fp.broadcast(null, "foxyproxy-proxy-change");
 
97
          break;
 
98
        case "delete": /* deliberate fall-through */
 
99
        case "deleteOne":
 
100
          fp.proxies.deleteByName(proxy.name, false);
 
101
          fp.broadcast(null, "foxyproxy-proxy-change");
 
102
          break;
 
103
        case "deleteMultiple":
 
104
          fp.proxies.deleteByName(proxy.name, true);
 
105
          fp.broadcast(null, "foxyproxy-proxy-change");
 
106
          break;
 
107
        case "updateOrAdd":
 
108
          var p = fp.proxies.mergeByName(proxy, nameValuePairs);
 
109
          if (p)
 
110
            proxy = p;
 
111
          else
 
112
            fp.proxies.insertAt(nameValuePairs["position"], proxy);
 
113
          fp.broadcast(null, "foxyproxy-proxy-change");
 
114
          break;
 
115
      }
 
116
      fp.writeSettings(); // Save to disk
 
117
    }
 
118
    
 
119
    // If foxyProxyMode was specified as "this", translate that to something that fp.setMode() understands.
 
120
    // Can't set mode to "this" if you're deleting.
 
121
    if (nameValuePairs["foxyProxyMode"] == "this") {
 
122
      nameValuePairs["foxyProxyMode"] = 
 
123
        nameValuePairs["action"] == "delete" || nameValuePairs["action"] == "deleteOne" || nameValuePairs["action"] == "deleteMultiple" ?
 
124
        null :
 
125
        proxy.id;
 
126
    }
 
127
    // If a proxy name was specifed, get its ID and use that for new foxyproxy mode.
 
128
    else if (nameValuePairs["foxyProxyMode"] != "patterns" && nameValuePairs["foxyProxyMode"] != "disabled" &&
 
129
        nameValuePairs["foxyProxyMode"] != "random" && nameValuePairs["foxyProxyMode"] != "previous" && 
 
130
        nameValuePairs["foxyProxyMode"] != "roundrobin" && !fp.proxies.getProxyById(nameValuePairs["foxyProxyMode"])) {
 
131
      var proxy = fp.proxies.getProxyByName(nameValuePairs["foxyProxyMode"]);
 
132
      if (proxy)
 
133
        nameValuePairs["foxyProxyMode"] = proxy.id;
 
134
    }     
 
135
    
 
136
    // Set mode last in case user is setting mode to the proxy we just configured.
 
137
    // (In that case, setting mode earlier will result in the proxy not being found)
 
138
    if (nameValuePairs["foxyProxyMode"]) {
 
139
      fp.setMode(nameValuePairs["foxyProxyMode"], true);  
 
140
      fp.broadcast(null, "foxyproxy-mode-change");
 
141
    }
 
142
    
 
143
    // User-feedback?
 
144
    if (nameValuePairs["confirmation"] == "popup") {
 
145
      fp.notifier.alert(fp.getMessage("foxyproxy"), fp.getMessage("proxy.configured", [nameValuePairs["name"]]));
 
146
      return;
 
147
    }
 
148
    else if (nameValuePairs["confirmation"]) {
 
149
      // Is it a valid URL?
 
150
      try {
 
151
        CC["@mozilla.org/network/io-service;1"]
 
152
           .getService(CI.nsIIOService).newURI(nameValuePairs["confirmation"], "UTF-8", null);
 
153
      }
 
154
      catch(e) {/* not a valid URL */ return; }
 
155
      CC["@leahscape.org/foxyproxy/common;1"].getService().wrappedJSObject
 
156
        .openTab(nameValuePairs["confirmation"]);
 
157
    }   
 
158
  },
 
159
  
 
160
  newChannel: function(aURI) {
 
161
    var fp = CC["@leahscape.org/foxyproxy/service;1"].getService().wrappedJSObject;
 
162
    if (fp.ignoreProxyScheme) return new nsDummyChannel();
 
163
    
 
164
    // user notification first
 
165
    var fpc = CC["@leahscape.org/foxyproxy/common;1"].getService().wrappedJSObject
 
166
      fpph = this;
 
167
    fpc.notify("proxy.scheme.warning.2", null, function() {fpph.processURI(aURI)});
 
168
    return new nsDummyChannel();
 
169
  }
 
170
}
 
171
 
 
172
// BEGIN: Dummy channel implementation - thanks mark finkle and http://mxr.mozilla.org/mobile-browser/source/components/protocols/nsTelProtocolHandler.js#49
 
173
function nsDummyChannel() {}
 
174
 
 
175
nsDummyChannel.prototype.QueryInterface =
 
176
function bc_QueryInterface(iid) {
 
177
  if (!iid.equals(CI.nsIChannel) && !iid.equals(CI.nsIRequest) &&
 
178
      !iid.equals(CI.nsISupports))
 
179
      throw CR.NS_ERROR_NO_INTERFACE;
 
180
  return this;
 
181
}
 
182
 
 
183
/* nsIChannel */
 
184
nsDummyChannel.prototype.loadAttributes = null;
 
185
nsDummyChannel.prototype.contentLength = 0;
 
186
nsDummyChannel.prototype.owner = null;
 
187
nsDummyChannel.prototype.loadGroup = null;
 
188
nsDummyChannel.prototype.notificationCallbacks = null;
 
189
nsDummyChannel.prototype.securityInfo = null;
 
190
 
 
191
nsDummyChannel.prototype.open =
 
192
nsDummyChannel.prototype.asyncOpen =
 
193
function bc_open(observer, ctxt) {
 
194
  // We don't throw this (a number, not a real 'resultcode') because it
 
195
  // upsets xpconnect if we do (error in the js console).
 
196
  Components.returnCode = CR.NS_ERROR_NO_CONTENT;
 
197
}
 
198
 
 
199
nsDummyChannel.prototype.asyncRead =
 
200
function bc_asyncRead(listener, ctxt) {
 
201
  throw CR.NS_ERROR_NOT_IMPLEMENTED;
 
202
}
 
203
 
 
204
/* nsIRequest */
 
205
nsDummyChannel.prototype.isPending =
 
206
function bc_isPending() {
 
207
    return true;
 
208
}
 
209
 
 
210
nsDummyChannel.prototype.status = CR.NS_OK;
 
211
 
 
212
nsDummyChannel.prototype.cancel =
 
213
function bc_cancel(status) {
 
214
    this.status = status;
 
215
}
 
216
 
 
217
nsDummyChannel.prototype.suspend =
 
218
nsDummyChannel.prototype.resume =
 
219
function bc_suspres() {
 
220
    throw CR.NS_ERROR_NOT_IMPLEMENTED;
 
221
}
 
222
// END: Dummy channel implementation - thanks mark finkle and http://mxr.mozilla.org/mobile-browser/source/components/protocols/nsTelProtocolHandler.js#49
 
223
 
 
224
var ProtocolFactory = new Object();
 
225
 
 
226
ProtocolFactory.createInstance = function (outer, iid) {
 
227
  if (outer != null)
 
228
    throw Components.results.NS_ERROR_NO_AGGREGATION;
 
229
  if (!iid.equals(nsIProtocolHandler) &&
 
230
      !iid.equals(nsISupports))
 
231
    throw Components.results.NS_ERROR_NO_INTERFACE;
 
232
  var p = new Protocol();
 
233
  return p;
 
234
}
 
235
 
 
236
/**
 
237
 * JS XPCOM boilerplate component registration code.
 
238
 */
 
239
var prochandler = new Object();
 
240
 
 
241
prochandler.registerSelf = function (compMgr, fileSpec, location, type) {
 
242
  compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
 
243
  compMgr.registerFactoryLocation(kPROTOCOL_CID,
 
244
                                  kPROTOCOL_NAME,
 
245
                                  kPROTOCOL_CONTRACTID,
 
246
                                  fileSpec,
 
247
                                  location,
 
248
                                  type);
 
249
}
 
250
 
 
251
prochandler.getClassObject = function (compMgr, cid, iid) {
 
252
  if (!cid.equals(kPROTOCOL_CID))
 
253
    throw Components.results.NS_ERROR_NO_INTERFACE;
 
254
 
 
255
  if (!iid.equals(Components.interfaces.nsIFactory))
 
256
    throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
 
257
  return ProtocolFactory;
 
258
}
 
259
 
 
260
prochandler.canUnload = function (compMgr) {
 
261
  return true;
 
262
}
 
263
 
 
264
function NSGetModule(compMgr, fileSpec){
 
265
  return prochandler;
 
266
}