/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Bookmarks Sync. * * The Initial Developer of the Original Code is Mozilla. * Portions created by the Initial Developer are Copyright (C) 2007 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Dan Mills * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ const EXPORTED_SYMBOLS = ['Utils']; const Cc = Components.classes; const Ci = Components.interfaces; const Cr = Components.results; const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://weave/constants.js"); Cu.import("resource://weave/log4moz.js"); /* * Utility functions */ let Utils = { // lazy load objects from a constructor on first access. It will // work with the global object ('this' in the global context). lazy: function Weave_lazy(dest, prop, ctr) { let getter = function() { delete dest[prop]; dest[prop] = new ctr(); return dest[prop]; }; dest.__defineGetter__(prop, getter); }, deepEquals: function Weave_deepEquals(a, b) { if (!a && !b) return true; if (!a || !b) return false; // if neither is an object, just use == if (typeof(a) != "object" && typeof(b) != "object") return a == b; // check if only one of them is an object if (typeof(a) != "object" || typeof(b) != "object") return false; if (a instanceof Array) dump("a is an array\n"); if (b instanceof Array) dump("b is an array\n"); if (a instanceof Array && b instanceof Array) { if (a.length != b.length) return false; for (let i = 0; i < a.length; i++) { if (!Utils.deepEquals(a[i], b[i])) return false; } } else { // check if only one of them is an array if (a instanceof Array || b instanceof Array) return false; for (let key in a) { if (!Utils.deepEquals(a[key], b[key])) return false; } } return true; }, deepCopy: function Weave_deepCopy(thing) { if (typeof(thing) != "object" || thing == null) return thing; let ret; if (thing instanceof Array) { dump("making a cipy of an array!\n\n"); ret = []; for (let i = 0; i < thing.length; i++) ret.push(Utils.deepCopy(thing[i])); } else { ret = {}; for (let key in thing) ret[key] = Utils.deepCopy(thing[key]); } return ret; }, exceptionStr: function Weave_exceptionStr(e) { let message = e.message? e.message : e; let location = e.location? " (" + e.location + ")" : ""; return message + location; }, stackTrace: function Weave_stackTrace(stackFrame, str) { if (stackFrame.caller) str = Utils.stackTrace(stackFrame.caller, str); if (!str) str = ""; str = stackFrame + "\n" + str; return str; }, checkStatus: function Weave_checkStatus(code, msg, ranges) { if (!ranges) ranges = [[200,300]]; for (let i = 0; i < ranges.length; i++) { rng = ranges[i]; if (typeof(rng) == "object" && code >= rng[0] && code < rng[1]) return true; else if (typeof(rng) == "number" && code == rng) { return true; } } if (msg) { let log = Log4Moz.Service.getLogger("Service.Util"); log.error(msg + " Error code: " + code); } return false; }, ensureStatus: function Weave_ensureStatus(args) { if (!Utils.checkStatus.apply(Utils, arguments)) throw 'checkStatus failed'; }, sha1: function Weave_sha1(string) { let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]. createInstance(Ci.nsIScriptableUnicodeConverter); converter.charset = "UTF-8"; let hasher = Cc["@mozilla.org/security/hash;1"] .createInstance(Ci.nsICryptoHash); hasher.init(hasher.SHA1); let data = converter.convertToByteArray(string, {}); hasher.update(data, data.length); let rawHash = hasher.finish(false); // return the two-digit hexadecimal code for a byte function toHexString(charCode) { return ("0" + charCode.toString(16)).slice(-2); } let hash = [toHexString(rawHash.charCodeAt(i)) for (i in rawHash)].join(""); return hash; }, makeURI: function Weave_makeURI(URIString) { if (URIString === null || URIString == "") return null; let ioservice = Cc["@mozilla.org/network/io-service;1"]. getService(Ci.nsIIOService); return ioservice.newURI(URIString, null, null); }, xpath: function Weave_xpath(xmlDoc, xpathString) { let root = xmlDoc.ownerDocument == null ? xmlDoc.documentElement : xmlDoc.ownerDocument.documentElement; let nsResolver = xmlDoc.createNSResolver(root); return xmlDoc.evaluate(xpathString, xmlDoc, nsResolver, Ci.nsIDOMXPathResult.ANY_TYPE, null); }, runCmd: function Weave_runCmd() { var binary; var args = []; for (let i = 0; i < arguments.length; ++i) { args.push(arguments[i]); } if (args[0] instanceof Ci.nsIFile) { binary = args.shift(); } else { binary = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); binary.initWithPath(args.shift()); } var p = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); p.init(binary); let log = Log4Moz.Service.getLogger("Service.Util"); log.debug("Running command: " + binary.path + " " + args.join(" ")); p.run(true, args, args.length); return p.exitValue; }, getTmp: function Weave_getTmp(name) { let ds = Cc["@mozilla.org/file/directory_service;1"]. getService(Ci.nsIProperties); let tmp = ds.get("ProfD", Ci.nsIFile); tmp.QueryInterface(Ci.nsILocalFile); tmp.append("weave"); tmp.append("tmp"); if (!tmp.exists()) tmp.create(tmp.DIRECTORY_TYPE, PERMS_DIRECTORY); if (name) tmp.append(name); return tmp; }, open: function open(pathOrFile, mode, perms) { let stream, file; if (pathOrFile instanceof Ci.nsIFile) { file = pathOrFile; } else { file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); dump("PATH IS" + pathOrFile + "\n"); file.initWithPath(pathOrFile); } if (!perms) perms = PERMS_FILE; switch(mode) { case "<": { if (!file.exists()) throw "Cannot open file for reading, file does not exist"; let fis = Cc["@mozilla.org/network/file-input-stream;1"]. createInstance(Ci.nsIFileInputStream); fis.init(file, MODE_RDONLY, perms, 0); stream = Cc["@mozilla.org/intl/converter-input-stream;1"]. createInstance(Ci.nsIConverterInputStream); stream.init(fis, "UTF-8", 4096, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); } break; case ">": { let fos = Cc["@mozilla.org/network/file-output-stream;1"]. createInstance(Ci.nsIFileOutputStream); fos.init(file, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, perms, 0); stream = Cc["@mozilla.org/intl/converter-output-stream;1"] .createInstance(Ci.nsIConverterOutputStream); stream.init(fos, "UTF-8", 4096, 0x0000); } break; case ">>": { let fos = Cc["@mozilla.org/network/file-output-stream;1"]. createInstance(Ci.nsIFileOutputStream); fos.init(file, MODE_WRONLY | MODE_CREATE | MODE_APPEND, perms, 0); stream = Cc["@mozilla.org/intl/converter-output-stream;1"] .createInstance(Ci.nsIConverterOutputStream); stream.init(fos, "UTF-8", 4096, 0x0000); } break; default: throw "Illegal mode to open(): " + mode; } return [stream, file]; }, // assumes an nsIConverterInputStream readStream: function Weave_readStream(is) { let ret = "", str = {}; while (is.readString(4096, str) != 0) { ret += str.value; } return ret; }, bind2: function Async_bind2(object, method) { return function innerBind() { return method.apply(object, arguments); }; }, _prefs: null, get prefs() { if (!this.__prefs) { this.__prefs = Cc["@mozilla.org/preferences-service;1"] .getService(Ci.nsIPrefService); this.__prefs = this.__prefs.getBranch(PREFS_BRANCH); this.__prefs.QueryInterface(Ci.nsIPrefBranch2); } return this.__prefs; }, /* * Event listener object * Used to handle XMLHttpRequest and nsITimer callbacks */ EventListener: function Weave_EventListener(handler, eventName) { this._handler = handler; this._eventName = eventName; this._log = Log4Moz.Service.getLogger("Async.EventHandler"); this._log.level = Log4Moz.Level[Utils.prefs.getCharPref("log.logger.async")]; } }; Utils.EventListener.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback, Ci.nsISupports]), // DOM event listener handleEvent: function EL_handleEvent(event) { this._log.trace("Handling event " + this._eventName); this._handler(event); }, // nsITimerCallback notify: function EL_notify(timer) { //this._log.trace("Timer fired"); this._handler(timer); } }