Merge lp:~sil/bindwood/dbus-application-name into lp:bindwood

Proposed by Stuart Langridge
Status: Merged
Approved by: Rick McBride
Approved revision: 22
Merged at revision: not available
Proposed branch: lp:~sil/bindwood/dbus-application-name
Merge into: lp:bindwood
Diff against target: None lines
To merge this branch: bzr merge lp:~sil/bindwood/dbus-application-name
Reviewer Review Type Date Requested Status
Rick McBride (community) Approve
Zachery Bir (community) Approve
Review via email: mp+11420@code.launchpad.net

Commit message

Show "Bindwood" as application name when Bindwood D-Bus Python script requests access to the keyring.

To post a comment you must log in.
Revision history for this message
Stuart Langridge (sil) wrote :

Show "Bindwood" as application name when Bindwood D-Bus Python script requests access to the keyring.

Revision history for this message
Zachery Bir (urbanape) wrote :

Clarity is better than muddity.

review: Approve
Revision history for this message
Stuart Langridge (sil) wrote :

NOTE: this is a tiny one-line change, but it's stacked on urbanape's using-oauth branch. Waiting until that has landed will make this much easier to review.

Revision history for this message
Rick McBride (rmcbride) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'content/browserOverlay.xul'
2--- content/browserOverlay.xul 2009-08-18 14:17:30 +0000
3+++ content/browserOverlay.xul 2009-09-02 17:07:11 +0000
4@@ -19,6 +19,8 @@
5 <overlay id="bindwood"
6 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
7
8+ <script type="application/x-javascript" src="chrome://bindwood/content/sha1.js" />
9+ <script type="application/x-javascript" src="chrome://bindwood/content/oauth.js" />
10 <script type="application/x-javascript" src="chrome://bindwood/content/couch.js" />
11 <script type="application/x-javascript" src="chrome://bindwood/content/sync.js" />
12
13
14=== modified file 'content/couch.js'
15--- content/couch.js 2009-07-08 01:24:33 +0000
16+++ content/couch.js 2009-09-08 15:54:16 +0000
17@@ -1,12 +1,12 @@
18 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
19-// use this file except in compliance with the License. You may obtain a copy
20-// of the License at
21+// use this file except in compliance with the License. You may obtain a copy of
22+// the License at
23 //
24 // http://www.apache.org/licenses/LICENSE-2.0
25 //
26 // Unless required by applicable law or agreed to in writing, software
27 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
30 // License for the specific language governing permissions and limitations under
31 // the License.
32
33@@ -22,17 +22,26 @@
34 this.last_req = null;
35
36 this.request = function(method, uri, requestOptions) {
37- requestOptions = requestOptions || {}
38- requestOptions.headers = combine(requestOptions.headers, httpHeaders)
39+ CouchDB.message.action = uri;
40+ Bindwood.writeMessage("Set the action of the CouchDB.message to: " + uri);
41+ CouchDB.message.method = method;
42+ Bindwood.writeMessage("Set the method of the CouchDB.message to: " + method);
43+ OAuth.completeRequest(CouchDB.message, CouchDB.accessor);
44+ Bindwood.writeMessage("Signed the message");
45+ var parameters = CouchDB.message.parameters;
46+ requestOptions = requestOptions || {};
47+ requestOptions.headers = combine(requestOptions.headers, httpHeaders);
48+ requestOptions.headers = combine(requestOptions.headers, {Authorization: OAuth.getAuthorizationHeader('', parameters)});
49+ Bindwood.writeMessage("Request headers: " + JSON.stringify(requestOptions.headers));
50 return CouchDB.request(method, uri, requestOptions);
51- }
52+ };
53
54 // Creates the database on the server
55 this.createDb = function() {
56 this.last_req = this.request("PUT", this.uri);
57 CouchDB.maybeThrowError(this.last_req);
58 return JSON.parse(this.last_req.responseText);
59- }
60+ };
61
62 // Deletes the database on the server
63 this.deleteDb = function() {
64@@ -41,7 +50,7 @@
65 return false;
66 CouchDB.maybeThrowError(this.last_req);
67 return JSON.parse(this.last_req.responseText);
68- }
69+ };
70
71 // Save a document to the database
72 this.save = function(doc, options) {
73@@ -55,7 +64,7 @@
74 var result = JSON.parse(this.last_req.responseText);
75 doc._rev = result.rev;
76 return result;
77- }
78+ };
79
80 // Open a document from the database
81 this.open = function(docId, options) {
82@@ -64,7 +73,7 @@
83 return null;
84 CouchDB.maybeThrowError(this.last_req);
85 return JSON.parse(this.last_req.responseText);
86- }
87+ };
88
89 // Deletes a document from the database
90 this.deleteDoc = function(doc) {
91@@ -74,7 +83,7 @@
92 doc._rev = result.rev; //record rev in input document
93 doc._deleted = true;
94 return result;
95- }
96+ };
97
98 // Deletes an attachment from a document
99 this.deleteDocAttachment = function(doc, attachment_name) {
100@@ -83,17 +92,17 @@
101 var result = JSON.parse(this.last_req.responseText);
102 doc._rev = result.rev; //record rev in input document
103 return result;
104- }
105+ };
106
107 this.bulkSave = function(docs, options) {
108 // first prepoulate the UUIDs for new documents
109- var newCount = 0
110+ var newCount = 0;
111 for (var i=0; i<docs.length; i++) {
112 if (docs[i]._id == undefined)
113 newCount++;
114 }
115 var newUuids = CouchDB.newUuids(docs.length);
116- var newCount = 0
117+ var newCount = 0;
118 for (var i=0; i<docs.length; i++) {
119 if (docs[i]._id == undefined)
120 docs[i]._id = newUuids.pop();
121@@ -118,17 +127,17 @@
122 }
123 return results;
124 }
125- }
126+ };
127
128 this.ensureFullCommit = function() {
129 this.last_req = this.request("POST", this.uri + "_ensure_full_commit");
130 CouchDB.maybeThrowError(this.last_req);
131 return JSON.parse(this.last_req.responseText);
132- }
133+ };
134
135 // Applies the map function to the contents of database and returns the results.
136- this.query = function(mapFun, reduceFun, options, keys) {
137- var body = {language: "javascript"};
138+ this.query = function(mapFun, reduceFun, options, keys, language) {
139+ var body = {language: language || "javascript"};
140 if(keys) {
141 body.keys = keys ;
142 }
143@@ -144,13 +153,16 @@
144 body.options = options.options;
145 delete options.options;
146 }
147- this.last_req = this.request("POST", this.uri + "_temp_view" + encodeOptions(options), {
148+ var uri = this.uri + "_temp_view" + encodeOptions(options);
149+ Bindwood.writeMessage("Query URI: " + uri);
150+ Bindwood.writeMessage("Query body: " + JSON.stringify(body));
151+ this.last_req = this.request("POST", uri , {
152 headers: {"Content-Type": "application/json"},
153 body: JSON.stringify(body)
154 });
155 CouchDB.maybeThrowError(this.last_req);
156 return JSON.parse(this.last_req.responseText);
157- }
158+ };
159
160 this.view = function(viewname, options, keys) {
161 var viewParts = viewname.split('/');
162@@ -168,14 +180,27 @@
163 return null;
164 CouchDB.maybeThrowError(this.last_req);
165 return JSON.parse(this.last_req.responseText);
166- }
167+ };
168
169 // gets information about the database
170 this.info = function() {
171 this.last_req = this.request("GET", this.uri);
172 CouchDB.maybeThrowError(this.last_req);
173 return JSON.parse(this.last_req.responseText);
174- }
175+ };
176+
177+ // gets information about a design doc
178+ this.designInfo = function(docid) {
179+ this.last_req = this.request("GET", this.uri + docid + "/_info");
180+ CouchDB.maybeThrowError(this.last_req);
181+ return JSON.parse(this.last_req.responseText);
182+ };
183+
184+ this.viewCleanup = function() {
185+ this.last_req = this.request("POST", this.uri + "_view_cleanup");
186+ CouchDB.maybeThrowError(this.last_req);
187+ return JSON.parse(this.last_req.responseText);
188+ };
189
190 this.allDocs = function(options,keys) {
191 if(!keys) {
192@@ -188,7 +213,7 @@
193 }
194 CouchDB.maybeThrowError(this.last_req);
195 return JSON.parse(this.last_req.responseText);
196- }
197+ };
198
199 this.designDocs = function() {
200 return this.allDocs({startkey:"_design", endkey:"_design0"});
201@@ -206,13 +231,13 @@
202 }
203 CouchDB.maybeThrowError(req);
204 return JSON.parse(req.responseText);
205- }
206+ };
207
208 this.compact = function() {
209 this.last_req = this.request("POST", this.uri + "_compact");
210 CouchDB.maybeThrowError(this.last_req);
211 return JSON.parse(this.last_req.responseText);
212- }
213+ };
214
215 this.setDbProperty = function(propId, propValue) {
216 this.last_req = this.request("PUT", this.uri + propId,{
217@@ -220,13 +245,13 @@
218 });
219 CouchDB.maybeThrowError(this.last_req);
220 return JSON.parse(this.last_req.responseText);
221- }
222+ };
223
224 this.getDbProperty = function(propId) {
225 this.last_req = this.request("GET", this.uri + propId);
226 CouchDB.maybeThrowError(this.last_req);
227 return JSON.parse(this.last_req.responseText);
228- }
229+ };
230
231 this.setAdmins = function(adminsArray) {
232 this.last_req = this.request("PUT", this.uri + "_admins",{
233@@ -234,18 +259,18 @@
234 });
235 CouchDB.maybeThrowError(this.last_req);
236 return JSON.parse(this.last_req.responseText);
237- }
238+ };
239
240 this.getAdmins = function() {
241 this.last_req = this.request("GET", this.uri + "_admins");
242 CouchDB.maybeThrowError(this.last_req);
243 return JSON.parse(this.last_req.responseText);
244- }
245+ };
246
247 // Convert a options object to an url query string.
248 // ex: {key:'value',key2:'value2'} becomes '?key="value"&key2="value2"'
249 function encodeOptions(options) {
250- var buf = []
251+ var buf = [];
252 if (typeof(options) == "object" && options !== null) {
253 for (var name in options) {
254 if (!options.hasOwnProperty(name)) continue;
255@@ -278,22 +303,82 @@
256 return object1;
257 }
258
259-
260 }
261
262-CouchDB.PORT_NUMBER = 5984; // default
263-
264 // this is the XMLHttpRequest object from last request made by the following
265 // CouchDB.* functions (except for calls to request itself).
266 // Use this from callers to check HTTP status or header values of requests.
267 CouchDB.last_req = null;
268
269+CouchDB.login = function(username, password) {
270+ CouchDB.last_req = CouchDB.request("POST", "/_session", {
271+ headers: {"Content-Type": "application/x-www-form-urlencoded",
272+ "X-CouchDB-WWW-Authenticate": "Cookie"},
273+ body: "username=" + encodeURIComponent(username) + "&password=" + encodeURIComponent(password)
274+ });
275+ return JSON.parse(CouchDB.last_req.responseText);
276+};
277+
278+CouchDB.logout = function() {
279+ CouchDB.last_req = CouchDB.request("DELETE", "/_session", {
280+ headers: {"Content-Type": "application/x-www-form-urlencoded",
281+ "X-CouchDB-WWW-Authenticate": "Cookie"}
282+ });
283+ return JSON.parse(CouchDB.last_req.responseText);
284+};
285+
286+CouchDB.createUser = function(username, password, email, roles, basicAuth) {
287+ var roles_str = "";
288+ if (roles) {
289+ for (var i=0; i< roles.length; i++) {
290+ roles_str += "&roles=" + encodeURIComponent(roles[i]);
291+ }
292+ }
293+ var headers = {"Content-Type": "application/x-www-form-urlencoded"};
294+ if (basicAuth) {
295+ headers['Authorization'] = basicAuth;
296+ } else {
297+ headers['X-CouchDB-WWW-Authenticate'] = 'Cookie';
298+ }
299+
300+ CouchDB.last_req = CouchDB.request("POST", "/_user/", {
301+ headers: headers,
302+ body: "username=" + encodeURIComponent(username) + "&password=" + encodeURIComponent(password)
303+ + "&email="+ encodeURIComponent(email)+ roles_str
304+
305+ });
306+ return JSON.parse(CouchDB.last_req.responseText);
307+};
308+
309+CouchDB.updateUser = function(username, email, roles, password, old_password) {
310+ var roles_str = "";
311+ if (roles) {
312+ for (var i=0; i< roles.length; i++) {
313+ roles_str += "&roles=" + encodeURIComponent(roles[i]);
314+ }
315+ }
316+
317+ var body = "email="+ encodeURIComponent(email)+ roles_str;
318+
319+ if (typeof(password) != "undefined" && password)
320+ body += "&password=" + password;
321+
322+ if (typeof(old_password) != "undefined" && old_password)
323+ body += "&old_password=" + old_password;
324+
325+ CouchDB.last_req = CouchDB.request("PUT", "/_user/"+encodeURIComponent(username), {
326+ headers: {"Content-Type": "application/x-www-form-urlencoded",
327+ "X-CouchDB-WWW-Authenticate": "Cookie"},
328+ body: body
329+ });
330+ return JSON.parse(CouchDB.last_req.responseText);
331+};
332
333 CouchDB.allDbs = function() {
334 CouchDB.last_req = CouchDB.request("GET", "/_all_dbs");
335 CouchDB.maybeThrowError(CouchDB.last_req);
336 return JSON.parse(CouchDB.last_req.responseText);
337-}
338+};
339
340 CouchDB.allDesignDocs = function() {
341 var ddocs = {}, dbs = CouchDB.allDbs();
342@@ -308,7 +393,7 @@
343 CouchDB.last_req = CouchDB.request("GET", "/");
344 CouchDB.maybeThrowError(CouchDB.last_req);
345 return JSON.parse(CouchDB.last_req.responseText).version;
346-}
347+};
348
349 CouchDB.replicate = function(source, target, rep_options) {
350 rep_options = rep_options || {};
351@@ -319,29 +404,40 @@
352 });
353 CouchDB.maybeThrowError(CouchDB.last_req);
354 return JSON.parse(CouchDB.last_req.responseText);
355-}
356+};
357
358-CouchDB.request = function(method, uri, options) {
359- options = options || {};
360- var req = null;
361+CouchDB.newXhr = function() {
362 if (typeof(XMLHttpRequest) != "undefined") {
363- req = new XMLHttpRequest();
364+ return new XMLHttpRequest();
365 } else if (typeof(ActiveXObject) != "undefined") {
366- req = new ActiveXObject("Microsoft.XMLHTTP");
367+ return new ActiveXObject("Microsoft.XMLHTTP");
368 } else {
369 throw new Error("No XMLHTTPRequest support detected");
370 }
371- req.open(method, "http://localhost:" + CouchDB.PORT_NUMBER + uri, false);
372+};
373+
374+CouchDB.request = function(method, uri, options) {
375+ options = options || {};
376+ var req = CouchDB.newXhr();
377+ var computed_uri = "http://localhost:" + CouchDB.port + uri;
378+ Bindwood.writeMessage("Opening a request to: " + computed_uri);
379+ req.open(method, computed_uri, false);
380 if (options.headers) {
381+ Bindwood.writeMessage("Setting optional headers");
382 var headers = options.headers;
383 for (var headerName in headers) {
384 if (!headers.hasOwnProperty(headerName)) continue;
385 req.setRequestHeader(headerName, headers[headerName]);
386 }
387 }
388- req.send(options.body || "");
389+ Bindwood.writeMessage("Sending the request");
390+ try {
391+ req.send(options.body || "");
392+ } catch(e) {
393+ Bindwood.writeError("Problem sending request: ", e);
394+ }
395 return req;
396-}
397+};
398
399 CouchDB.requestStats = function(module, key, test) {
400 var query_arg = "";
401@@ -351,7 +447,7 @@
402
403 var stat = CouchDB.request("GET", "/_stats/" + module + "/" + key + query_arg).responseText;
404 return JSON.parse(stat)[module][key];
405-}
406+};
407
408 CouchDB.uuids_cache = [];
409
410@@ -373,7 +469,7 @@
411 CouchDB.uuids_cache.concat(result.uuids.slice(0, 100));
412 return result.uuids.slice(100);
413 }
414-}
415+};
416
417 CouchDB.maybeThrowError = function(req) {
418 if (req.status >= 400) {
419@@ -384,7 +480,7 @@
420 }
421 throw result;
422 }
423-}
424+};
425
426 CouchDB.params = function(options) {
427 options = options || {};
428@@ -394,4 +490,4 @@
429 returnArray.push(key + "=" + value);
430 }
431 return returnArray.join("&");
432-}
433+};
434
435=== added file 'content/oauth.js'
436--- content/oauth.js 1970-01-01 00:00:00 +0000
437+++ content/oauth.js 2009-09-04 14:10:27 +0000
438@@ -0,0 +1,515 @@
439+/*
440+ * Copyright 2008 Netflix, Inc.
441+ *
442+ * Licensed under the Apache License, Version 2.0 (the "License");
443+ * you may not use this file except in compliance with the License.
444+ * You may obtain a copy of the License at
445+ *
446+ * http://www.apache.org/licenses/LICENSE-2.0
447+ *
448+ * Unless required by applicable law or agreed to in writing, software
449+ * distributed under the License is distributed on an "AS IS" BASIS,
450+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
451+ * See the License for the specific language governing permissions and
452+ * limitations under the License.
453+ */
454+
455+/* Here's some JavaScript software for implementing OAuth.
456+
457+ This isn't as useful as you might hope. OAuth is based around
458+ allowing tools and websites to talk to each other. However,
459+ JavaScript running in web browsers is hampered by security
460+ restrictions that prevent code running on one website from
461+ accessing data stored or served on another.
462+
463+ Before you start hacking, make sure you understand the limitations
464+ posed by cross-domain XMLHttpRequest.
465+
466+ On the bright side, some platforms use JavaScript as their
467+ language, but enable the programmer to access other web sites.
468+ Examples include Google Gadgets, and Microsoft Vista Sidebar.
469+ For those platforms, this library should come in handy.
470+*/
471+
472+// The HMAC-SHA1 signature method calls b64_hmac_sha1, defined by
473+// http://pajhome.org.uk/crypt/md5/sha1.js
474+
475+/* An OAuth message is represented as an object like this:
476+ {method: "GET", action: "http://server.com/path", parameters: ...}
477+
478+ The parameters may be either a map {name: value, name2: value2}
479+ or an Array of name-value pairs [[name, value], [name2, value2]].
480+ The latter representation is more powerful: it supports parameters
481+ in a specific sequence, or several parameters with the same name;
482+ for example [["a", 1], ["b", 2], ["a", 3]].
483+
484+ Parameter names and values are NOT percent-encoded in an object.
485+ They must be encoded before transmission and decoded after reception.
486+ For example, this message object:
487+ {method: "GET", action: "http://server/path", parameters: {p: "x y"}}
488+ ... can be transmitted as an HTTP request that begins:
489+ GET /path?p=x%20y HTTP/1.0
490+ (This isn't a valid OAuth request, since it lacks a signature etc.)
491+ Note that the object "x y" is transmitted as x%20y. To encode
492+ parameters, you can call OAuth.addToURL, OAuth.formEncode or
493+ OAuth.getAuthorization.
494+
495+ This message object model harmonizes with the browser object model for
496+ input elements of an form, whose value property isn't percent encoded.
497+ The browser encodes each value before transmitting it. For example,
498+ see consumer.setInputs in example/consumer.js.
499+ */
500+var OAuth; if (OAuth == null) OAuth = {};
501+
502+OAuth.setProperties = function setProperties(into, from) {
503+ if (into != null && from != null) {
504+ for (var key in from) {
505+ into[key] = from[key];
506+ }
507+ }
508+ return into;
509+}
510+
511+OAuth.setProperties(OAuth, // utility functions
512+{
513+ percentEncode: function percentEncode(s) {
514+ if (s == null) {
515+ return "";
516+ }
517+ if (s instanceof Array) {
518+ var e = "";
519+ for (var i = 0; i < s.length; ++s) {
520+ if (e != "") e += '&';
521+ e += percentEncode(s[i]);
522+ }
523+ return e;
524+ }
525+ s = encodeURIComponent(s);
526+ // Now replace the values which encodeURIComponent doesn't do
527+ // encodeURIComponent ignores: - _ . ! ~ * ' ( )
528+ // OAuth dictates the only ones you can ignore are: - _ . ~
529+ // Source: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:encodeURIComponent
530+ s = s.replace(/\!/g, "%21");
531+ s = s.replace(/\*/g, "%2A");
532+ s = s.replace(/\'/g, "%27");
533+ s = s.replace(/\(/g, "%28");
534+ s = s.replace(/\)/g, "%29");
535+ return s;
536+ }
537+,
538+ decodePercent: function decodePercent(s) {
539+ if (s != null) {
540+ // Handle application/x-www-form-urlencoded, which is defined by
541+ // http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1
542+ s = s.replace(/\+/g, " ");
543+ }
544+ return decodeURIComponent(s);
545+ }
546+,
547+ /** Convert the given parameters to an Array of name-value pairs. */
548+ getParameterList: function getParameterList(parameters) {
549+ if (parameters == null) {
550+ return [];
551+ }
552+ if (typeof parameters != "object") {
553+ return decodeForm(parameters + "");
554+ }
555+ if (parameters instanceof Array) {
556+ return parameters;
557+ }
558+ var list = [];
559+ for (var p in parameters) {
560+ list.push([p, parameters[p]]);
561+ }
562+ return list;
563+ }
564+,
565+ /** Convert the given parameters to a map from name to value. */
566+ getParameterMap: function getParameterMap(parameters) {
567+ if (parameters == null) {
568+ return {};
569+ }
570+ if (typeof parameters != "object") {
571+ return getParameterMap(decodeForm(parameters + ""));
572+ }
573+ if (parameters instanceof Array) {
574+ var map = {};
575+ for (var p = 0; p < parameters.length; ++p) {
576+ var key = parameters[p][0];
577+ if (map[key] === undefined) { // first value wins
578+ map[key] = parameters[p][1];
579+ }
580+ }
581+ return map;
582+ }
583+ return parameters;
584+ }
585+,
586+ getParameter: function getParameter(parameters, name) {
587+ if (parameters instanceof Array) {
588+ for (var p = 0; p < parameters.length; ++p) {
589+ if (parameters[p][0] == name) {
590+ return parameters[p][1]; // first value wins
591+ }
592+ }
593+ } else {
594+ return OAuth.getParameterMap(parameters)[name];
595+ }
596+ return null;
597+ }
598+,
599+ formEncode: function formEncode(parameters) {
600+ var form = "";
601+ var list = OAuth.getParameterList(parameters);
602+ for (var p = 0; p < list.length; ++p) {
603+ var value = list[p][1];
604+ if (value == null) value = "";
605+ if (form != "") form += '&';
606+ form += OAuth.percentEncode(list[p][0])
607+ +'='+ OAuth.percentEncode(value);
608+ }
609+ return form;
610+ }
611+,
612+ decodeForm: function decodeForm(form) {
613+ var list = [];
614+ var nvps = form.split('&');
615+ for (var n = 0; n < nvps.length; ++n) {
616+ var nvp = nvps[n];
617+ if (nvp == "") {
618+ continue;
619+ }
620+ var equals = nvp.indexOf('=');
621+ var name;
622+ var value;
623+ if (equals < 0) {
624+ name = OAuth.decodePercent(nvp);
625+ value = null;
626+ } else {
627+ name = OAuth.decodePercent(nvp.substring(0, equals));
628+ value = OAuth.decodePercent(nvp.substring(equals + 1));
629+ }
630+ list.push([name, value]);
631+ }
632+ return list;
633+ }
634+,
635+ setParameter: function setParameter(message, name, value) {
636+ var parameters = message.parameters;
637+ if (parameters instanceof Array) {
638+ for (var p = 0; p < parameters.length; ++p) {
639+ if (parameters[p][0] == name) {
640+ if (value === undefined) {
641+ parameters.splice(p, 1);
642+ } else {
643+ parameters[p][1] = value;
644+ value = undefined;
645+ }
646+ }
647+ }
648+ if (value !== undefined) {
649+ parameters.push([name, value]);
650+ }
651+ } else {
652+ parameters = OAuth.getParameterMap(parameters);
653+ parameters[name] = value;
654+ message.parameters = parameters;
655+ }
656+ }
657+,
658+ setParameters: function setParameters(message, parameters) {
659+ var list = OAuth.getParameterList(parameters);
660+ for (var i = 0; i < list.length; ++i) {
661+ OAuth.setParameter(message, list[i][0], list[i][1]);
662+ }
663+ }
664+,
665+ /** Fill in parameters to help construct a request message.
666+ This function doesn't fill in every parameter.
667+ The accessor object should be like:
668+ {consumerKey:'foo', consumerSecret:'bar', accessorSecret:'nurn', token:'krelm', tokenSecret:'blah'}
669+ The accessorSecret property is optional.
670+ */
671+ completeRequest: function completeRequest(message, accessor) {
672+ if (message.method == null) {
673+ message.method = "GET";
674+ }
675+ var map = OAuth.getParameterMap(message.parameters);
676+ if (map.oauth_consumer_key == null) {
677+ OAuth.setParameter(message, "oauth_consumer_key", accessor.consumerKey || "");
678+ }
679+ if (map.oauth_token == null && accessor.token != null) {
680+ OAuth.setParameter(message, "oauth_token", accessor.token);
681+ }
682+ if (map.oauth_version == null) {
683+ OAuth.setParameter(message, "oauth_version", "1.0");
684+ }
685+ if (map.oauth_timestamp == null) {
686+ OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
687+ }
688+ if (map.oauth_nonce == null) {
689+ OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(6));
690+ }
691+ OAuth.SignatureMethod.sign(message, accessor);
692+ }
693+,
694+ setTimestampAndNonce: function setTimestampAndNonce(message) {
695+ OAuth.setParameter(message, "oauth_timestamp", OAuth.timestamp());
696+ OAuth.setParameter(message, "oauth_nonce", OAuth.nonce(6));
697+ }
698+,
699+ addToURL: function addToURL(url, parameters) {
700+ newURL = url;
701+ if (parameters != null) {
702+ var toAdd = OAuth.formEncode(parameters);
703+ if (toAdd.length > 0) {
704+ var q = url.indexOf('?');
705+ if (q < 0) newURL += '?';
706+ else newURL += '&';
707+ newURL += toAdd;
708+ }
709+ }
710+ return newURL;
711+ }
712+,
713+ /** Construct the value of the Authorization header for an HTTP request. */
714+ getAuthorizationHeader: function getAuthorizationHeader(realm, parameters) {
715+ var header = 'OAuth realm="' + OAuth.percentEncode(realm) + '"';
716+ var list = OAuth.getParameterList(parameters);
717+ for (var p = 0; p < list.length; ++p) {
718+ var parameter = list[p];
719+ var name = parameter[0];
720+ if (name.indexOf("oauth_") == 0) {
721+ header += ',' + OAuth.percentEncode(name) + '="' + OAuth.percentEncode(parameter[1]) + '"';
722+ }
723+ }
724+ return header;
725+ }
726+,
727+ timestamp: function timestamp() {
728+ var d = new Date();
729+ return Math.floor(d.getTime()/1000);
730+ }
731+,
732+ nonce: function nonce(length) {
733+ var chars = OAuth.nonce.CHARS;
734+ var result = "";
735+ for (var i = 0; i < length; ++i) {
736+ var rnum = Math.floor(Math.random() * chars.length);
737+ result += chars.substring(rnum, rnum+1);
738+ }
739+ return result;
740+ }
741+});
742+
743+OAuth.nonce.CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
744+
745+/** Define a constructor function,
746+ without causing trouble to anyone who was using it as a namespace.
747+ That is, if parent[name] already existed and had properties,
748+ copy those properties into the new constructor.
749+ */
750+OAuth.declareClass = function declareClass(parent, name, newConstructor) {
751+ var previous = parent[name];
752+ parent[name] = newConstructor;
753+ if (newConstructor != null && previous != null) {
754+ for (var key in previous) {
755+ if (key != "prototype") {
756+ newConstructor[key] = previous[key];
757+ }
758+ }
759+ }
760+ return newConstructor;
761+}
762+
763+/** An abstract algorithm for signing messages. */
764+OAuth.declareClass(OAuth, "SignatureMethod", function OAuthSignatureMethod(){});
765+
766+OAuth.setProperties(OAuth.SignatureMethod.prototype, // instance members
767+{
768+ /** Add a signature to the message. */
769+ sign: function sign(message) {
770+ var baseString = OAuth.SignatureMethod.getBaseString(message);
771+ var signature = this.getSignature(baseString);
772+ OAuth.setParameter(message, "oauth_signature", signature);
773+ return signature; // just in case someone's interested
774+ }
775+,
776+ /** Set the key string for signing. */
777+ initialize: function initialize(name, accessor) {
778+ var consumerSecret;
779+ if (accessor.accessorSecret != null
780+ && name.length > 9
781+ && name.substring(name.length-9) == "-Accessor")
782+ {
783+ consumerSecret = accessor.accessorSecret;
784+ } else {
785+ consumerSecret = accessor.consumerSecret;
786+ }
787+ this.key = OAuth.percentEncode(consumerSecret)
788+ +"&"+ OAuth.percentEncode(accessor.tokenSecret);
789+ }
790+});
791+
792+/* SignatureMethod expects an accessor object to be like this:
793+ {tokenSecret: "lakjsdflkj...", consumerSecret: "QOUEWRI..", accessorSecret: "xcmvzc..."}
794+ The accessorSecret property is optional.
795+ */
796+// Class members:
797+OAuth.setProperties(OAuth.SignatureMethod, // class members
798+{
799+ sign: function sign(message, accessor) {
800+ var name = OAuth.getParameterMap(message.parameters).oauth_signature_method;
801+ if (name == null || name == "") {
802+ name = "HMAC-SHA1";
803+ OAuth.setParameter(message, "oauth_signature_method", name);
804+ }
805+ OAuth.SignatureMethod.newMethod(name, accessor).sign(message);
806+ }
807+,
808+ /** Instantiate a SignatureMethod for the given method name. */
809+ newMethod: function newMethod(name, accessor) {
810+ var impl = OAuth.SignatureMethod.REGISTERED[name];
811+ if (impl != null) {
812+ var method = new impl();
813+ method.initialize(name, accessor);
814+ return method;
815+ }
816+ var err = new Error("signature_method_rejected");
817+ var acceptable = "";
818+ for (var r in OAuth.SignatureMethod.REGISTERED) {
819+ if (acceptable != "") acceptable += '&';
820+ acceptable += OAuth.percentEncode(r);
821+ }
822+ err.oauth_acceptable_signature_methods = acceptable;
823+ throw err;
824+ }
825+,
826+ /** A map from signature method name to constructor. */
827+ REGISTERED : {}
828+,
829+ /** Subsequently, the given constructor will be used for the named methods.
830+ The constructor will be called with no parameters.
831+ The resulting object should usually implement getSignature(baseString).
832+ You can easily define such a constructor by calling makeSubclass, below.
833+ */
834+ registerMethodClass: function registerMethodClass(names, classConstructor) {
835+ for (var n = 0; n < names.length; ++n) {
836+ OAuth.SignatureMethod.REGISTERED[names[n]] = classConstructor;
837+ }
838+ }
839+,
840+ /** Create a subclass of OAuth.SignatureMethod, with the given getSignature function. */
841+ makeSubclass: function makeSubclass(getSignatureFunction) {
842+ var superClass = OAuth.SignatureMethod;
843+ var subClass = function() {
844+ superClass.call(this);
845+ };
846+ subClass.prototype = new superClass();
847+ // Delete instance variables from prototype:
848+ // delete subclass.prototype... There aren't any.
849+ subClass.prototype.getSignature = getSignatureFunction;
850+ subClass.prototype.constructor = subClass;
851+ return subClass;
852+ }
853+,
854+ getBaseString: function getBaseString(message) {
855+ var URL = message.action;
856+ var q = URL.indexOf('?');
857+ var parameters;
858+ if (q < 0) {
859+ parameters = message.parameters;
860+ } else {
861+ // Combine the URL query string with the other parameters:
862+ parameters = OAuth.decodeForm(URL.substring(q + 1));
863+ var toAdd = OAuth.getParameterList(message.parameters);
864+ for (var a = 0; a < toAdd.length; ++a) {
865+ parameters.push(toAdd[a]);
866+ }
867+ }
868+ return OAuth.percentEncode(message.method.toUpperCase())
869+ +'&'+ OAuth.percentEncode(OAuth.SignatureMethod.normalizeUrl(URL))
870+ +'&'+ OAuth.percentEncode(OAuth.SignatureMethod.normalizeParameters(parameters));
871+ }
872+,
873+ normalizeUrl: function normalizeUrl(url) {
874+ var uri = OAuth.SignatureMethod.parseUri(url);
875+ var scheme = uri.protocol.toLowerCase();
876+ var authority = uri.authority.toLowerCase();
877+ var dropPort = (scheme == "http" && uri.port == 80)
878+ || (scheme == "https" && uri.port == 443);
879+ if (dropPort) {
880+ // find the last : in the authority
881+ var index = authority.lastIndexOf(":");
882+ if (index >= 0) {
883+ authority = authority.substring(0, index);
884+ }
885+ }
886+ var path = uri.path;
887+ /* This actually produces different signatures from the python lib
888+ if (!path) {
889+ path = "/"; // conforms to RFC 2616 section 3.2.2
890+ }
891+ */
892+ // we know that there is no query and no fragment here.
893+ return scheme + "://" + authority + path;
894+ }
895+,
896+ parseUri: function parseUri (str) {
897+ /* This function was adapted from parseUri 1.2.1
898+ http://stevenlevithan.com/demo/parseuri/js/assets/parseuri.js
899+ */
900+ var o = {key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
901+ parser: {strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/ }};
902+ var m = o.parser.strict.exec(str);
903+ var uri = {};
904+ var i = 14;
905+ while (i--) uri[o.key[i]] = m[i] || "";
906+ return uri;
907+ }
908+,
909+ normalizeParameters: function normalizeParameters(parameters) {
910+ if (parameters == null) {
911+ return "";
912+ }
913+ var list = OAuth.getParameterList(parameters);
914+ var sortable = [];
915+ for (var p = 0; p < list.length; ++p) {
916+ var nvp = list[p];
917+ if (nvp[0] == "oauth_signature" || nvp[0] == "realm") {
918+ continue;
919+ } else {
920+ sortable.push([ OAuth.percentEncode(nvp[0])
921+ + " " // because it comes before any character that can appear in a percentEncoded string.
922+ + OAuth.percentEncode(nvp[1])
923+ , nvp]);
924+ }
925+ }
926+ sortable.sort(function(a,b) {
927+ if (a[0] < b[0]) return -1;
928+ if (a[0] > b[0]) return 1;
929+ return 0;
930+ });
931+ var sorted = [];
932+ for (var s = 0; s < sortable.length; ++s) {
933+ sorted.push(sortable[s][1]);
934+ }
935+ return OAuth.formEncode(sorted);
936+ }
937+});
938+
939+OAuth.SignatureMethod.registerMethodClass(["PLAINTEXT", "PLAINTEXT-Accessor"],
940+ OAuth.SignatureMethod.makeSubclass(
941+ function getSignature(baseString) {
942+ return this.key;
943+ }
944+ ));
945+
946+OAuth.SignatureMethod.registerMethodClass(["HMAC-SHA1", "HMAC-SHA1-Accessor"],
947+ OAuth.SignatureMethod.makeSubclass(
948+ function getSignature(baseString) {
949+ b64pad = '=';
950+ var signature = b64_hmac_sha1(this.key, baseString);
951+ return signature;
952+ }
953+ ));
954
955=== added file 'content/sha1.js'
956--- content/sha1.js 1970-01-01 00:00:00 +0000
957+++ content/sha1.js 2009-09-02 17:07:11 +0000
958@@ -0,0 +1,202 @@
959+/*
960+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
961+ * in FIPS PUB 180-1
962+ * Version 2.1a Copyright Paul Johnston 2000 - 2002.
963+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
964+ * Distributed under the BSD License
965+ * See http://pajhome.org.uk/crypt/md5 for details.
966+ */
967+
968+/*
969+ * Configurable variables. You may need to tweak these to be compatible with
970+ * the server-side, but the defaults work in most cases.
971+ */
972+var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
973+var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
974+var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
975+
976+/*
977+ * These are the functions you'll usually want to call
978+ * They take string arguments and return either hex or base-64 encoded strings
979+ */
980+function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
981+function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
982+function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
983+function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
984+function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
985+function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
986+
987+/*
988+ * Perform a simple self-test to see if the VM is working
989+ */
990+function sha1_vm_test()
991+{
992+ return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
993+}
994+
995+/*
996+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
997+ */
998+function core_sha1(x, len)
999+{
1000+ /* append padding */
1001+ x[len >> 5] |= 0x80 << (24 - len % 32);
1002+ x[((len + 64 >> 9) << 4) + 15] = len;
1003+
1004+ var w = Array(80);
1005+ var a = 1732584193;
1006+ var b = -271733879;
1007+ var c = -1732584194;
1008+ var d = 271733878;
1009+ var e = -1009589776;
1010+
1011+ for(var i = 0; i < x.length; i += 16)
1012+ {
1013+ var olda = a;
1014+ var oldb = b;
1015+ var oldc = c;
1016+ var oldd = d;
1017+ var olde = e;
1018+
1019+ for(var j = 0; j < 80; j++)
1020+ {
1021+ if(j < 16) w[j] = x[i + j];
1022+ else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
1023+ var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
1024+ safe_add(safe_add(e, w[j]), sha1_kt(j)));
1025+ e = d;
1026+ d = c;
1027+ c = rol(b, 30);
1028+ b = a;
1029+ a = t;
1030+ }
1031+
1032+ a = safe_add(a, olda);
1033+ b = safe_add(b, oldb);
1034+ c = safe_add(c, oldc);
1035+ d = safe_add(d, oldd);
1036+ e = safe_add(e, olde);
1037+ }
1038+ return Array(a, b, c, d, e);
1039+
1040+}
1041+
1042+/*
1043+ * Perform the appropriate triplet combination function for the current
1044+ * iteration
1045+ */
1046+function sha1_ft(t, b, c, d)
1047+{
1048+ if(t < 20) return (b & c) | ((~b) & d);
1049+ if(t < 40) return b ^ c ^ d;
1050+ if(t < 60) return (b & c) | (b & d) | (c & d);
1051+ return b ^ c ^ d;
1052+}
1053+
1054+/*
1055+ * Determine the appropriate additive constant for the current iteration
1056+ */
1057+function sha1_kt(t)
1058+{
1059+ return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
1060+ (t < 60) ? -1894007588 : -899497514;
1061+}
1062+
1063+/*
1064+ * Calculate the HMAC-SHA1 of a key and some data
1065+ */
1066+function core_hmac_sha1(key, data)
1067+{
1068+ var bkey = str2binb(key);
1069+ if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
1070+
1071+ var ipad = Array(16), opad = Array(16);
1072+ for(var i = 0; i < 16; i++)
1073+ {
1074+ ipad[i] = bkey[i] ^ 0x36363636;
1075+ opad[i] = bkey[i] ^ 0x5C5C5C5C;
1076+ }
1077+
1078+ var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
1079+ return core_sha1(opad.concat(hash), 512 + 160);
1080+}
1081+
1082+/*
1083+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
1084+ * to work around bugs in some JS interpreters.
1085+ */
1086+function safe_add(x, y)
1087+{
1088+ var lsw = (x & 0xFFFF) + (y & 0xFFFF);
1089+ var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
1090+ return (msw << 16) | (lsw & 0xFFFF);
1091+}
1092+
1093+/*
1094+ * Bitwise rotate a 32-bit number to the left.
1095+ */
1096+function rol(num, cnt)
1097+{
1098+ return (num << cnt) | (num >>> (32 - cnt));
1099+}
1100+
1101+/*
1102+ * Convert an 8-bit or 16-bit string to an array of big-endian words
1103+ * In 8-bit function, characters >255 have their hi-byte silently ignored.
1104+ */
1105+function str2binb(str)
1106+{
1107+ var bin = Array();
1108+ var mask = (1 << chrsz) - 1;
1109+ for(var i = 0; i < str.length * chrsz; i += chrsz)
1110+ bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
1111+ return bin;
1112+}
1113+
1114+/*
1115+ * Convert an array of big-endian words to a string
1116+ */
1117+function binb2str(bin)
1118+{
1119+ var str = "";
1120+ var mask = (1 << chrsz) - 1;
1121+ for(var i = 0; i < bin.length * 32; i += chrsz)
1122+ str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
1123+ return str;
1124+}
1125+
1126+/*
1127+ * Convert an array of big-endian words to a hex string.
1128+ */
1129+function binb2hex(binarray)
1130+{
1131+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
1132+ var str = "";
1133+ for(var i = 0; i < binarray.length * 4; i++)
1134+ {
1135+ str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
1136+ hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
1137+ }
1138+ return str;
1139+}
1140+
1141+/*
1142+ * Convert an array of big-endian words to a base-64 string
1143+ */
1144+function binb2b64(binarray)
1145+{
1146+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1147+ var str = "";
1148+ for(var i = 0; i < binarray.length * 4; i += 3)
1149+ {
1150+ var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
1151+ | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
1152+ | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
1153+ for(var j = 0; j < 4; j++)
1154+ {
1155+ if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
1156+ else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
1157+ }
1158+ }
1159+ return str;
1160+}
1161
1162=== modified file 'content/sync.js'
1163--- content/sync.js 2009-08-27 18:45:48 +0000
1164+++ content/sync.js 2009-09-08 15:29:55 +0000
1165@@ -112,11 +112,11 @@
1166 .getService(Components.interfaces.nsIWindowMediator)
1167 .getEnumerator("").getNext() == window) {
1168 Bindwood.writeMessage("First window opened. Getting a Couch Port");
1169- Bindwood.getCouchPortNumber(Bindwood.startProcess);
1170+ Bindwood.getCouchEnvironment(Bindwood.startProcess);
1171 }
1172 },
1173
1174- getCouchPortNumber: function(continueFunction) {
1175+ getCouchEnvironment: function(continueFunction) {
1176 // find the desktop Couch port number by making a D-Bus call
1177 // we call D-Bus by shelling out to a bash script which calls
1178 // it for us, and writes the port number into a temp file
1179@@ -139,12 +139,12 @@
1180 var MY_ID = "bindwood@ubuntu.com";
1181 var em = Components.classes["@mozilla.org/extensions/manager;1"].
1182 getService(Components.interfaces.nsIExtensionManager);
1183- var dbus_script = em.getInstallLocation(MY_ID).getItemFile(MY_ID, "dbus.sh");
1184- Bindwood.writeMessage("Found path to dbus_script: " + dbus_script.path);
1185+ var couchdb_env_script = em.getInstallLocation(MY_ID).getItemFile(MY_ID, "couchdb_env.sh");
1186+ Bindwood.writeMessage("Found path to dbus_script: " + couchdb_env_script.path);
1187 // create an nsILocalFile for the executable
1188 var nsifile = Components.classes["@mozilla.org/file/local;1"]
1189 .createInstance(Components.interfaces.nsILocalFile);
1190- nsifile.initWithPath(dbus_script.path);
1191+ nsifile.initWithPath(couchdb_env_script.path);
1192
1193 // create an nsIProcess2 to execute this bash script
1194 var process = Components.classes["@mozilla.org/process/util;1"]
1195@@ -153,14 +153,16 @@
1196
1197 // Run the process, passing the tmpfile path
1198 var args = [tmpfile.path];
1199- Bindwood.writeMessage("Running dbus script");
1200+ Bindwood.writeMessage("Running couchdb env script");
1201 process.runAsync(args, args.length, {
1202 observe: function(process, finishState, unused_data) {
1203- var port = 5984;
1204+ // If the script exists cleanly, we should have a file
1205+ // containing the port couch is running on as well as
1206+ // the various OAuth tokens necessary to talk to it.
1207 if (finishState == "process-finished") {
1208- // read temp file to find port number
1209+ // read temp file to find couch environment
1210 // https://developer.mozilla.org/en/Code_snippets/File_I%2f%2fO#Reading_from_a_file
1211- var data = "";
1212+ var environment;
1213 var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
1214 createInstance(Components.interfaces.nsIFileInputStream);
1215 var cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
1216@@ -169,28 +171,56 @@
1217 cstream.init(fstream, "UTF-8", 0, 0);
1218 let (str = {}) {
1219 cstream.readString(-1, str); // read the whole file and put it in str.value
1220- data = str.value;
1221+ environment = str.value;
1222 };
1223 cstream.close(); // this closes fstream
1224- data = data.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
1225- if (/^[0-9]+$/.test(data)) {
1226- port = data;
1227- } else {
1228- Bindwood.writeMessage("D-Bus port data is not a number (" + data + ")");
1229- }
1230+ environment = environment.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
1231 } else {
1232 // fall back to system CouchDB
1233 Bindwood.writeMessage("D-Bus port find failed");
1234 }
1235 tmpfile.remove(false);
1236- continueFunction(port);
1237- }
1238+
1239+ if (environment == 'ENOCOUCH') {
1240+ // No Couch environment found. Just spit out a
1241+ // message and return, stopping Bindwood from
1242+ // doing anything further.
1243+ Bindwood.writeError("No suitable Couch environment found. Not proceeding.", e);
1244+ } else {
1245+ // If we don't have a Couch environment, don't bother
1246+ // trying to fall back on the system CouchDB.
1247+ continueFunction(environment);
1248+ }
1249+ }
1250 });
1251 },
1252
1253- startProcess: function(couchPortNumber) {
1254- Bindwood.writeMessage("Starting process with Couch on port " + couchPortNumber);
1255- CouchDB.PORT_NUMBER = couchPortNumber;
1256+ startProcess: function(couchEnvironment) {
1257+ Bindwood.writeMessage("Starting process with Couch environment: " + couchEnvironment);
1258+
1259+ var env_array = couchEnvironment.split(':');
1260+ var port = env_array[0];
1261+ var consumer_key = env_array[1];
1262+ var consumer_secret = env_array[2];
1263+ var token = env_array[3];
1264+ var token_secret = env_array[4];
1265+
1266+ CouchDB.port = port;
1267+ CouchDB.accessor = {
1268+ consumerSecret: consumer_secret,
1269+ tokenSecret: token_secret
1270+ };
1271+ CouchDB.message = {
1272+ parameters: {
1273+ oauth_callback: "None",
1274+ oauth_consumer_key: consumer_key,
1275+ oauth_signature_method: "HMAC-SHA1",
1276+ oauth_token: token,
1277+ oauth_verifier: "None",
1278+ oauth_version: "1.0"
1279+ }
1280+ };
1281+
1282 try {
1283 Bindwood.writeMessage("Pushing bookmarks");
1284 Bindwood.pushBookmarks();
1285@@ -260,10 +290,19 @@
1286 }
1287 }
1288
1289- Bindwood.pushBookmarksFromList(Bindwood.bookmarksService.toolbarFolder,
1290- "toolbarFolder", couch);
1291- Bindwood.pushBookmarksFromList(Bindwood.bookmarksService.bookmarksMenuFolder,
1292- "bookmarksMenuFolder", couch);
1293+ try {
1294+ Bindwood.pushBookmarksFromList(Bindwood.bookmarksService.toolbarFolder,
1295+ "toolbarFolder", couch);
1296+ } catch(e) {
1297+ Bindwood.writeError("Error pushing toolbarFolder bookmarks: ", e);
1298+ }
1299+
1300+ try {
1301+ Bindwood.pushBookmarksFromList(Bindwood.bookmarksService.bookmarksMenuFolder,
1302+ "bookmarksMenuFolder", couch);
1303+ } catch(e) {
1304+ Bindwood.writeError("Error pushing bookmarksMenuFolder bookmarks: ", e);
1305+ }
1306 },
1307
1308 getBookmarksFromList: function(bookmarksList) {
1309@@ -320,15 +359,19 @@
1310
1311 Bindwood.uuidItemIdMap[uuid] = itemId;
1312
1313- var results = db.query(function(doc) {
1314- if (doc.application_annotations &&
1315- doc.application_annotations.Firefox &&
1316- doc.application_annotations.Firefox.uuid) {
1317- emit(doc.application_annotations.Firefox.uuid, doc);
1318- }
1319- }, null, {
1320- startkey: uuid, endkey: uuid
1321- });
1322+ try {
1323+ var results = db.query(function(doc) {
1324+ if (doc.application_annotations &&
1325+ doc.application_annotations.Firefox &&
1326+ doc.application_annotations.Firefox.uuid) {
1327+ emit(doc.application_annotations.Firefox.uuid, doc);
1328+ }
1329+ }, null, {
1330+ startkey: uuid, endkey: uuid
1331+ });
1332+ } catch(e) {
1333+ Bindwood.writeError("Error querying couch: ", e);
1334+ }
1335
1336 if (results.rows.length === 0) {
1337 // this bookmark is not in CouchDB, so write it
1338@@ -440,7 +483,7 @@
1339 Bindwood.writeMessage("The URI from Couch (" + bm.uri + ") is different from local (" + metadata.spec + ")");
1340 try {
1341 var new_uri = Bindwood.ioService.newURI(bm.uri, null, null);
1342- Bindowod.writeMessage("Creating a new URI for our local bookmark");
1343+ Bindwood.writeMessage("Creating a new URI for our local bookmark");
1344 Bindwood.bookmarksService.changeBookmarkURI(itemId, new_uri);
1345 } catch(e) {
1346 Bindwood.writeError("Problem creating a new URI for bookmark: ", e);
1347@@ -482,7 +525,7 @@
1348
1349 try {
1350 var new_uri = Bindwood.ioService.newURI(bm.uri, null, null);
1351- Bindowod.writeMessage("Creating a new URI for our local bookmark");
1352+ Bindwood.writeMessage("Creating a new URI for our local bookmark");
1353 Bindwood.bookmarksService.changeBookmarkURI(itemId, new_uri);
1354 } catch(e) {
1355 Bindwood.writeError("Problem creating a new URI for bookmark: ", e);
1356
1357=== renamed file 'dbus.sh' => 'couchdb_env.sh'
1358--- dbus.sh 2009-08-18 14:17:30 +0000
1359+++ couchdb_env.sh 2009-09-09 08:39:09 +0000
1360@@ -13,12 +13,16 @@
1361 # You should have received a copy of the GNU General Public License along
1362 # with this program. If not, see <http://www.gnu.org/licenses/>.
1363 OUT=$1
1364-PORT=$(dbus-send --session --dest=org.desktopcouch.CouchDB --print-reply --type=method_call / org.desktopcouch.CouchDB.getPort 2>/dev/null | grep int32 | awk '{print $2}' )
1365+
1366+PORT=$(dbus-send --session --dest=org.desktopcouch.CouchDB --print-reply --type=method_call / org.desktopcouch.CouchDB.getPort 2>/dev/null | grep int32 | awk '{print $2}')
1367+
1368+TOKENS=$(python -c "import gnomekeyring,gobject; gobject.set_application_name('Bindwood'); print gnomekeyring.find_items_sync(gnomekeyring.ITEM_GENERIC_SECRET, {'desktopcouch': 'oauth'})[0].secret" 2>/dev/null)
1369+
1370 if [ -z "$PORT" ]; then
1371- # D-Bus call failed for some reason, so use default port
1372- echo 5984 > $OUT
1373+ # D-Bus call failed for some reason, so just punt
1374+ echo ENOCOUCH > $OUT
1375 else
1376- echo $PORT > $OUT
1377+ echo $PORT:$TOKENS > $OUT
1378 fi
1379
1380

Subscribers

People subscribed via source and target branches