home *** CD-ROM | disk | FTP | other *** search
/ Clickx 65 / Clickx 65.iso / software / internet / xmarks / xmarks-3.1.1.xpi / chrome / content / foxmarks-settings.js < prev    next >
Encoding:
JavaScript  |  2009-05-05  |  43.4 KB  |  1,450 lines

  1. /* 
  2.  Copyright 2005-2008 Foxmarks Inc.
  3.  
  4.  foxmarks-settings.js: implements FoxmarksSettings, an object that wraps
  5.  access to persistent settings, both user settings and internal stored values.
  6.    
  7.  */
  8.  
  9. // TO DO:
  10. // * If user changes username or password, delete our cookie.
  11.  
  12. var Cc = Components.classes;
  13. var Ci = Components.interfaces;
  14. var CCon = Components.Constructor;
  15. const FOXMARKS_SYNC_REALM = "Foxmarks Sync Login";
  16. const FOXMARKS_SYNC_REALM_PIN = "Foxmarks Sync PIN";
  17. const SYNC_REALM = "Xmarks Sync Login";
  18. const SYNC_REALM_PIN = "Xmarks Sync PIN";
  19.  
  20. function Bundle() {
  21.   var sb = Components.classes["@mozilla.org/intl/stringbundle;1"]
  22.       .getService(Components.interfaces.nsIStringBundleService)
  23.       .createBundle("chrome://foxmarks/locale/foxmarks.properties");
  24.   return sb;
  25. }
  26.  
  27. function UpdateToXMarks(){
  28.     var ps = Cc["@mozilla.org/preferences-service;1"].
  29.             getService(Ci.nsIPrefService);
  30.     var foxmarks = ps.getBranch("foxmarks.");
  31.     var doupdate = false;
  32.  
  33.     try {
  34.         doupdate = foxmarks.getIntPref("majorVersion") == 2;
  35.     } catch(e){
  36.         // do nothing
  37.     }
  38.  
  39.     if(doupdate){
  40.         var xmarks = ps.getBranch("extensions.xmarks.");
  41.         var obj = { value: 0 };
  42.         var list = xmarks.getChildList("",obj);
  43.         obj = { value: 0 };
  44.         list = foxmarks.getChildList("",obj);
  45.  
  46.         var len = list.length;
  47.         while(len--){
  48.             var name = list[len];
  49.             var valtype = foxmarks.getPrefType(name);
  50.             switch(valtype){
  51.                 case xmarks.PREF_STRING:
  52.                     xmarks.setCharPref(name, foxmarks.getCharPref(name));
  53.                     break;
  54.                 case xmarks.PREF_INT:
  55.                     xmarks.setIntPref(name, foxmarks.getIntPref(name));
  56.                     break;
  57.                 case xmarks.PREF_BOOL:
  58.                     xmarks.setBoolPref(name, foxmarks.getBoolPref(name));
  59.                     break;
  60.             }
  61.         }
  62.         foxmarks.deleteBranch("");
  63.         ps.savePrefFile(null);     // ensure it gets flushed
  64.         gSettings.correctHashes();
  65.     }
  66. }
  67. // Notify takes the given args object and passes it to observers.
  68. // By convention, args contains at least "status", an integer with
  69. // the following interpretation:
  70. //   0: operation completed successfully.
  71. //   1: operation continues; msg is status update only.
  72. //   2: operation was cancelled by user.
  73. //   3: component finished
  74. //   other: operation failed.
  75. // Similarly, "msg" contains a user-displayable message.
  76.  
  77. function Notify(args) {
  78.     var os = Cc["@mozilla.org/observer-service;1"]
  79.         .getService(Ci.nsIObserverService);
  80.  
  81.     var str = args.toSource();        
  82.     os.notifyObservers(null, "foxmarks-service", str);
  83. }
  84.  
  85. function SetProgressComponentStatus(id, phase){
  86.     Notify({status: 3, component: id, phase: phase} );
  87. }
  88. function SetProgressMessage(msgname) {
  89.     var msg;
  90.     try {
  91.         msg = Bundle().GetStringFromName(msgname);
  92.     } catch(e) {
  93.         msg = "untranslated(" + msgname + ")";
  94.     }
  95.  
  96.     Notify({status: 1, msg: msg} );
  97. }
  98.  
  99. var FoxmarksPopupCloseState = false;
  100. function FoxmarksClickNewUserPopup(){
  101.     FoxmarksPopupCloseState = true;
  102.     var panel = document.getElementById("foxmarks-newuserwiz");
  103.     if(panel){
  104.         panel.hidePopup();
  105.     }
  106.     FoxmarksOpenWizard(false, false);
  107. }
  108. function FoxmarksNewUserPopupHiding(){
  109.     if(FoxmarksPopupCloseState){
  110.         return true;
  111.     }
  112.     var panel = document.getElementById("foxmarks-newuserwiz");
  113.     if(panel){
  114.         var TOTALTIME = 1000;
  115.         var  NUMSTEPS = 20;
  116.         var ctr = 0;
  117.         var func = function() {
  118.             var opac = Number(panel.style.opacity);
  119.             if(opac > 0 && ctr < NUMSTEPS){
  120.                 panel.style.opacity = Math.max(opac - (1 / NUMSTEPS), 0);
  121.                 ctr++;
  122.                 window.setTimeout(func, Math.floor(TOTALTIME / NUMSTEPS));
  123.             } else {
  124.                 FoxmarksPopupCloseState = true;
  125.                 panel.hidePopup();
  126.             }
  127.  
  128.         };
  129.         window.setTimeout(func, 2000);
  130.         FoxmarksPopupCloseState = true;
  131.     }
  132.     return false;
  133. }
  134. function FoxmarksCloseNewUserPopup(){
  135.     var panel = document.getElementById("foxmarks-newuserwiz");
  136.     if(panel){
  137.         var os = Cc["@mozilla.org/observer-service;1"].
  138.             getService(Ci.nsIObserverService);
  139.         os.notifyObservers(null, "foxmarks-tr","closebubble"); 
  140.         FoxmarksPopupCloseState = true;
  141.         panel.hidePopup();
  142.     }
  143. }
  144. function FoxmarksNewUserPopup(data){
  145.     if(!data || data.status !== 0 || !data.use_bib){
  146.         FoxmarksOpenWizard(false, false);
  147.     } else {
  148.         FoxmarksPopupCloseState = false;
  149.         gSettings.wizardRetriesLeft = gSettings.wizardRetriesLeft - 1;
  150.         var panel = document.getElementById("foxmarks-newuserwiz");
  151.         if(panel){
  152.             panel.setAttribute("style", data.popup_style);
  153.             var box = document.getElementById("foxmarks-bubblebox");
  154.             box.setAttribute("style", data.box_style);
  155.  
  156.             box = document.getElementById("foxmarks-bubblecontainer");
  157.             box.setAttribute("style", data.container_style);
  158.  
  159.             box = document.getElementById("foxmarks-bubbletextbox");
  160.             box.setAttribute("style", data.text_style);
  161.  
  162.             box = document.getElementById("foxmarks-bubbletitle");
  163.             box.setAttribute("style", data.title_style);
  164.  
  165.             if(gSettings.is_english){
  166.                 box.setAttribute("value", data.title_english);
  167.             }
  168.  
  169.             box = document.getElementById("foxmarks-bubbleclose");
  170.             box.setAttribute("style", data.close_style);
  171.  
  172.             box = document.getElementById("foxmarks-bubbledesc");
  173.             box.setAttribute("style", data.desc_style);
  174.             if(gSettings.is_english){
  175.                 box.removeChild(box.firstChild);
  176.                 var desc = document.createTextNode(
  177.                     data.desc_english
  178.                 );
  179.                 box.appendChild(desc);
  180.             }
  181.  
  182.             var img = document.getElementById("foxmarks-bubbletr");
  183.             var attrs = [];
  184.             attrs.push("app="       + "jezebel");
  185.             attrs.push("mid="       + gSettings.machineId);
  186.             attrs.push("sess="      + gSettings.sessionID);
  187.             attrs.push("page="      + "bubblepopup");
  188.             attrs.push("flavor="    + data.flavor);
  189.             attrs.push("no_cache="  + Date.now().toString(36));
  190.  
  191.             var query = attrs.join("&");
  192.             img.src = gSettings.httpProtocol + "tr.xmarks.com/tracking/impressions.gif?" + query;
  193.             panel.openPopup(
  194.                 document.getElementById(data.anchor),
  195.                 data.position,
  196.                 data.posx,
  197.                 data.posy,
  198.                 false,
  199.                 false
  200.             );
  201.             setTimeout(function(){
  202.                 panel.style.opacity = 1.0;
  203.             }, 100);
  204.  
  205.             document.getElementById("foxmarks-bubbleclose").addEventListener(
  206.                 "click",
  207.                 function(e){
  208.                     e.stopPropagation();
  209.                     FoxmarksCloseNewUserPopup();
  210.                 }, 
  211.                 true
  212.             );
  213.         }
  214.     }
  215. }
  216. function FoxmarksAlert(str){
  217.     var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
  218.         .getService(Components.interfaces.nsIPromptService);
  219.     ps.alert(null,"Xmarks", str);
  220. }
  221.  
  222. function MapErrorUrl(status) {
  223.     var error = "";
  224.  
  225.     status = status & 0x0000ffff;
  226.  
  227.     try {
  228.         error = Bundle().GetStringFromName("errorurl." + status);
  229.     } catch (e) {
  230.         if(UnknownError(status)){
  231.             error = Bundle().GetStringFromName("errorurl.unknown");
  232.         } else {
  233.             error = "";
  234.         }
  235.     }
  236.  
  237.     return error;
  238. function UnknownError(status){
  239.     var result = false;
  240.     status = status & 0x0000ffff;
  241.  
  242.     try {
  243.         Bundle().GetStringFromName("error." + status);
  244.         result = false;
  245.     } catch (e) {
  246.         result = true;
  247.     }
  248.  
  249.     return result;
  250. }
  251. function MapErrorMessage(status) {
  252.     var error = "";
  253.  
  254.     status = status & 0x0000ffff;
  255.  
  256.     try {
  257.         error = Bundle().GetStringFromName("errormsg." + status);
  258.     } catch (e) {
  259.         if(UnknownError(status)){
  260.             error = Bundle().formatStringFromName(
  261.                 "errormsg.unknown", [status], 1);
  262.         } else {
  263.             error = "";
  264.         }
  265.     }
  266.  
  267.     return error;
  268. function MapError(status) {
  269.     var error = "";
  270.  
  271.     status = status & 0x0000ffff;
  272.  
  273.     try {
  274.         error = Bundle().GetStringFromName("error." + status);
  275.     } catch (e) {
  276.         error = Bundle().formatStringFromName("error.unknown", [status], 1);
  277.     }
  278.  
  279.     return error;
  280.  
  281. /**
  282. * Convert a string containing binary values to hex.
  283. * Shamelessly stolen from nsUpdateService.js
  284. */
  285. function binaryToHex(input) {
  286.     var result = "";
  287.     for (var i = 0; i < input.length; ++i) {
  288.         var hex = input.charCodeAt(i).toString(16);
  289.         if (hex.length == 1)
  290.             hex = "0" + hex;
  291.         result += hex;
  292.     }
  293.     return result;
  294. }
  295.  
  296. function hex_md5(string) {
  297.     var arr = new Array();
  298.     
  299.     for (var i = 0; i < string.length; ++i)
  300.         arr[i] = string.charCodeAt(i);
  301.         
  302.     try {
  303.         var hash = Components.classes["@mozilla.org/security/hash;1"].
  304.                     createInstance(Components.interfaces.nsICryptoHash);
  305.         hash.initWithString("md5");
  306.         hash.update(arr, arr.length);
  307.         var digest = binaryToHex(hash.finish(false));
  308.     } catch (e) {
  309.         var ps = Components.classes
  310.             ["@mozilla.org/embedcomp/prompt-service;1"]
  311.             .getService(Components.interfaces.nsIPromptService);
  312.         ps.alert(null, "Xmarks", e);
  313.     } 
  314.     return digest;    // 8 bytes seems sufficient for our purposes
  315. }
  316.  
  317. // Return the version string associated with the currently installed version
  318. function FoxmarksExtensionManagerLiteral(value) {
  319.     var rdfs = Components.classes["@mozilla.org/rdf/rdf-service;1"].
  320.         getService(Components.interfaces.nsIRDFService);
  321.     var ds = Components.classes["@mozilla.org/extensions/manager;1"].
  322.         getService(Components.interfaces.nsIExtensionManager).datasource;
  323.     var s = rdfs.GetResource("urn:mozilla:item:foxmarks@kei.com");
  324.     var p = rdfs.GetResource("http://www.mozilla.org/2004/em-rdf#" + value);
  325.     var t = ds.GetTarget(s, p, true);
  326.     if (t instanceof Components.interfaces.nsIRDFLiteral)
  327.         return t.Value;
  328.     else
  329.         return "unknown";
  330. }
  331.  
  332. function FoxmarksVersion() {
  333.     return FoxmarksExtensionManagerLiteral("version");
  334. }
  335.  
  336. function FoxmarksUpdateAvailable() {
  337.     var none = ["none", "unknown"];
  338.  
  339.     return none.indexOf(FoxmarksExtensionManagerLiteral(
  340.             "availableUpdateURL")) < 0;
  341. }
  342.  
  343. function FoxmarksSettings() {
  344.     // upgrade to xmarks if possible
  345.     var ps = Cc["@mozilla.org/preferences-service;1"].
  346.             getService(Ci.nsIPrefService);
  347.         
  348.     this.prefs = ps.getBranch("extensions.xmarks.");
  349.     this.ps = ps;
  350.     this._auth = "";
  351. }
  352.  
  353. FoxmarksSettings.prototype = {
  354.     prefs: null,
  355.  
  356.     // Only call this for uninstalls (it nukes all prefs)
  357.     clearAllPrefs: function(){
  358.         this.pin = "";
  359.         this.password = "";
  360.         this.prefs.deleteBranch("");
  361.     },
  362.     
  363.     getCharPref: function(string, def) {
  364.         var result;
  365.         
  366.         try {
  367.             result = this.prefs.getCharPref(string);
  368.         } catch (e) {
  369.             result = def;
  370.         }
  371.         
  372.         return result;
  373.     },
  374.  
  375.     getIntPref: function(string, def) {
  376.         var result;
  377.         
  378.         try {
  379.             result = this.prefs.getIntPref(string);
  380.         } catch (e) {
  381.             result = def;
  382.         }
  383.         
  384.         return result;
  385.     },
  386.  
  387.  
  388.     getBoolPref: function(string, def) {
  389.         var result;
  390.         
  391.         try {
  392.             result = this.prefs.getBoolPref(string);
  393.         } catch (e) {
  394.             result = def;
  395.         }
  396.         
  397.         return result;
  398.     },
  399.  
  400.  
  401.     formatDate: function(d) {
  402.         return d.toLocaleDateString() + " " + d.toLocaleTimeString();
  403.     },
  404.  
  405.     // get fundamental settings
  406.  
  407.     get username() {
  408.         return this.getCharPref("username", "");
  409.     },
  410.  
  411.     get httpProtocol() {
  412.         return this.securityLevel == 1 ? "https://" : "http://";
  413.     },
  414.  
  415.     get sessionPin() {
  416.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  417.             getService(Ci.nsIFoxmarksService);
  418.  
  419.         return fms.getPin();
  420.     },
  421.  
  422.     set sessionPin(pw) {
  423.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  424.             getService(Ci.nsIFoxmarksService);
  425.  
  426.         fms.setPin(pw);
  427.     },
  428.     get sessionPassword() {
  429.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  430.             getService(Ci.nsIFoxmarksService);
  431.  
  432.         return fms.getPassword();
  433.     },
  434.  
  435.     set sessionPassword(pw) {
  436.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  437.             getService(Ci.nsIFoxmarksService);
  438.  
  439.         fms.setPassword(pw);
  440.     },
  441.     removePIN: function(){
  442.         var lm = Cc["@mozilla.org/login-manager;1"].
  443.             getService(Ci.nsILoginManager);
  444.         var nsli = new CCon("@mozilla.org/login-manager/loginInfo;1",
  445.             Ci.nsILoginInfo, "init");
  446.         var oldli = new nsli(this.host, null, SYNC_REALM_PIN, 
  447.             this.username, this.pinNoPrompt, "", "");
  448.  
  449.         lm.removeLogin(oldli);
  450.         this.sessionPin = "";
  451.     },
  452.  
  453.     set pin(pin) {
  454.         if (!this.rememberPin) {
  455.             this.sessionPin = pin;
  456.         } else {
  457.             if ("@mozilla.org/login-manager;1" in Cc) {
  458.                 // Can't set password without username.
  459.                 if (!this.username)
  460.                     return;
  461.                 var lm = Cc["@mozilla.org/login-manager;1"].
  462.                     getService(Ci.nsILoginManager);
  463.                 var nsli = new CCon("@mozilla.org/login-manager/loginInfo;1",
  464.                     Ci.nsILoginInfo, "init");
  465.                 var newli = new nsli(this.host, null, SYNC_REALM_PIN, 
  466.                     this.username, pin, "", "");
  467.                 var oldli = new nsli(this.host, null, SYNC_REALM_PIN, 
  468.                     this.username, this.pinNoPrompt, "", "");
  469.                 try {
  470.                     lm.modifyLogin(oldli, newli);
  471.                 } catch (e) {
  472.                     lm.addLogin(newli);
  473.                 }
  474.             }
  475.         }
  476.     },
  477.  
  478.     get pin() {
  479.  
  480.         var pw = this.pinNoPrompt;
  481.  
  482.         if (pw != null)
  483.             return pw;
  484.  
  485.         var pin = { value: "" };
  486.         var remember = { value: this.rememberPin };
  487.  
  488.         var sb = Bundle().GetStringFromName;
  489.         var rv = Cc["@mozilla.org/embedcomp/prompt-service;1"].
  490.              getService(Ci.nsIPromptService).
  491.              promptPassword(null, sb("appname.long"), 
  492.                  sb("prompt.pin"),
  493.                   pin,
  494.                  sb("prompt.rememberpin"),
  495.                  remember);
  496.  
  497.         if (!rv) {
  498.             throw 2;
  499.         }
  500.  
  501.         this.pin = pin.value;
  502.         this.rememberPin = remember.value;
  503.  
  504.         return pin.value;
  505.     },
  506.  
  507.     get pinNoPrompt() {
  508.         if (!this.rememberPin && this.sessionPin) {
  509.             return this.sessionPin;
  510.         }
  511.  
  512.         if (this.rememberPin) {
  513.             if ("@mozilla.org/login-manager;1" in Cc) {
  514.                 var lm = Cc["@mozilla.org/login-manager;1"].
  515.                     getService(Ci.nsILoginManager);
  516.                 var logins = lm.findLogins({}, this.host, null, SYNC_REALM_PIN);
  517.                 for (var i = 0; i < logins.length; ++i) {
  518.                     if (logins[i].username == this.username) {
  519.                         return logins[i].password;
  520.                     }
  521.                 }
  522.                 var oldhost = this.host == "sync.xmarks.com"
  523.                     ? "sync.foxmarks.com" : this.host;
  524.                 logins = lm.findLogins({}, oldhost, null, FOXMARKS_SYNC_REALM_PIN);
  525.                 for (var i = 0; i < logins.length; ++i) {
  526.                     if (logins[i].username == this.username) {
  527.                         return logins[i].password;
  528.                     }
  529.                 }
  530.             }
  531.         }
  532.         return null;    // couldn't fetch password
  533.     },
  534.  
  535.     get password() {
  536.  
  537.         var pw = this.passwordNoPrompt;
  538.  
  539.         if (pw != null)
  540.             return pw;
  541.  
  542.         var username = { value: this.username };
  543.         var password = { value: "" };
  544.         var remember = { value: this.rememberPassword };
  545.  
  546.         var sb = Bundle().GetStringFromName;
  547.         var rv = Cc["@mozilla.org/embedcomp/prompt-service;1"].
  548.              getService(Ci.nsIPromptService).
  549.              promptUsernameAndPassword(null, sb("appname.long"), 
  550.                  sb("prompt.usernamepassword"),
  551.                  username, password,
  552.                  sb("prompt.rememberpassword"),
  553.                  remember);
  554.  
  555.         if (!rv) {
  556.             throw 2;
  557.         }
  558.  
  559.         this.rememberPassword = remember.value;
  560.         this.username = username.value;
  561.         this.password = password.value;
  562.  
  563.         return password.value;
  564.     },
  565.  
  566.     get passwordNoPrompt() {
  567.         if (!this.rememberPassword && this.sessionPassword) {
  568.             return this.sessionPassword;
  569.         }
  570.  
  571.         if (this.rememberPassword) {
  572.             if ("@mozilla.org/passwordmanager;1" in Cc) {
  573.                 var host = {};
  574.                 var user = {};
  575.                 var pass = {}; 
  576.                 try {
  577.                     var pmi = Cc["@mozilla.org/passwordmanager;1"].
  578.                         createInstance(Ci.nsIPasswordManagerInternal);
  579.                     pmi.findPasswordEntry(this.host, this.username, 
  580.                         "", host, user, pass);
  581.                     if(pass.value){
  582.                         this.sessionPassword = pass.value;
  583.                     // else try foxmarks
  584.                     } else if(this.host == "sync.xmarks.com"){
  585.                         pmi.findPasswordEntry("sync.foxmarks.com", this.username, 
  586.                             "", host, user, pass);
  587.                     }
  588.                     return pass.value;
  589.                 } catch(e) { }
  590.             } else if ("@mozilla.org/login-manager;1" in Cc) {
  591.                 var lm = Cc["@mozilla.org/login-manager;1"].
  592.                     getService(Ci.nsILoginManager);
  593.                 var logins = lm.findLogins({}, this.host, null, SYNC_REALM);
  594.                 for (var i = 0; i < logins.length; ++i) {
  595.                     if (logins[i].username == this.username) {
  596.                         return logins[i].password;
  597.                     }
  598.                 }
  599.  
  600.                 // next try foxmarks realm
  601.                 var oldhost = this.host == "sync.xmarks.com" ? "sync.foxmarks.com" : this.host;
  602.                 logins = lm.findLogins({}, oldhost, null, FOXMARKS_SYNC_REALM);
  603.                 for (var i = 0; i < logins.length; ++i) {
  604.                     if (logins[i].username == this.username) {
  605.                         return logins[i].password;
  606.                     }
  607.                 }
  608.  
  609.                 logins = lm.findLogins({}, this.host, "", null);
  610.                 for (var i = 0; i < logins.length; ++i) {
  611.                     if (logins[i].username == this.username) {
  612.                         try {
  613.                             var password = logins[i].password;
  614.                             var nsli = new 
  615.                                 CCon("@mozilla.org/login-manager/loginInfo;1",
  616.                                 Ci.nsILoginInfo, "init");
  617.                             lm.removeLogin(logins[i]);
  618.                             var newli = new nsli(this.host, null, SYNC_REALM, 
  619.                                 this.username, password, "", "");
  620.                             lm.addLogin(newli);
  621.  
  622.                         } catch(e){
  623.  
  624.                         }
  625.  
  626.                         return password;
  627.                     }
  628.                 }
  629.             }
  630.         }
  631.         return null;    // couldn't fetch password
  632.     },
  633.  
  634.     _calcHash: function(host){
  635.         var fms = Cc["@foxcloud.com/extensions/foxmarks;1"].
  636.             getService(Ci.nsIFoxmarksService);
  637.  
  638.         return hex_md5((this.useOwnServer ? 
  639.                 this.url : host + this.username) + 
  640.             fms.getStorageEngine("bookmarks")).slice(16)
  641.             + ".";
  642.     },
  643.     get hash() {
  644.         return this._calcHash(this.host);
  645.     },
  646.             
  647.     get lastSynchDate() {
  648.         return this.getCharPref(this.hash + "lastSynchDate", "");
  649.     },
  650.  
  651.     get haveSynced() {
  652.         return this.lastSynchDate != "";
  653.     },
  654.  
  655.     getLastSyncDate: function(syncType){
  656.         if(syncType == "bookmarks")
  657.             return this.getCharPref(this.hash + "lastSynchDate", "");
  658.         else
  659.             return this.getCharPref(this.hash + syncType + "-lastSynchDate",
  660.                     "");
  661.     },
  662.     
  663.     getHaveSynced: function(syncType){
  664.         return this.getLastSyncDate(syncType) != "";
  665.  
  666.     },
  667.  
  668.     setLastSyncDate: function(syncType, string){
  669.         if(syncType == "bookmarks")
  670.             return this.prefs.setCharPref(this.hash + "lastSynchDate", string);
  671.         else
  672.             return this.prefs.setCharPref(this.hash + syncType + "-lastSynchDate",
  673.                     string);
  674.     },
  675.  
  676.     get minutesSinceLastSync() {
  677.         if (!this.haveSynced)
  678.           return 0;
  679.       
  680.         var syncMS = new Date(this.lastSynchDate).getTime();
  681.         var nowMS = Date.now();
  682.         return (nowMS - syncMS) / 60000;
  683.   
  684.     },
  685.   
  686.     get daysSinceLastUpdateNag() {
  687.         if (!this.lastNagDate)
  688.             return Infinity;
  689.         var updateMS = new Date(this.lastNagDate).getTime();
  690.         var nowMS = Date.now();
  691.         return (nowMS - updateMS) / (60000 * 60 * 24);
  692.     },
  693.   
  694.     get lastNagDate() {
  695.         return this.getCharPref("lastNagDate", null);
  696.     },
  697.     
  698.     set lastNagDate(string) {
  699.         this.prefs.setCharPref("lastNagDate", string);
  700.     },
  701.     
  702.     get lastSynchDisplayDate() {
  703.         if (!this.haveSynced) {
  704.             return Bundle().GetStringFromName("msg.neversynced");
  705.         } else {
  706.             return this.formatDate(new Date(this.lastSynchDate));
  707.         }
  708.     },
  709.  
  710.     setEtag: function(syncType, string){
  711.         if(syncType == "bookmarks"){
  712.             this.prefs.setCharPref(this.hash + "etag", string);
  713.         }
  714.         else {
  715.             this.prefs.setCharPref(this.hash + 
  716.                     "-" + syncType + "-etag", string);
  717.         }
  718.     },
  719.     getEtag: function(syncType){
  720.         if(syncType == "bookmarks"){
  721.             return this.getCharPref(this.hash + "etag", "");
  722.         }
  723.         else {
  724.             return this.getCharPref(this.hash + "-" + syncType + "-etag", "");
  725.         }
  726.     },
  727.     
  728.     
  729.     setToken: function(syncType, string){
  730.         if(syncType == "bookmarks"){
  731.             return this.prefs.setCharPref(this.hash + "token", string);
  732.         }
  733.         else {
  734.             return this.prefs.setCharPref(this.hash + "-" + syncType + "-token", string);
  735.         }
  736.  
  737.     },
  738.     getToken: function(syncType){
  739.         if(syncType == "bookmarks"){
  740.             return this.getCharPref(this.hash + "token", "");
  741.         }
  742.         else {
  743.             return this.getCharPref(this.hash + "-" + syncType + "-token", "");
  744.         }
  745.  
  746.     },
  747.     
  748.     get writeCount() {
  749.         return this.getIntPref("writeCount", 0);
  750.     },
  751.  
  752.     get lastError() {
  753.         return this.getIntPref("lastError", 0);
  754.     },
  755.     set lastError(err){
  756.         this.prefs.setIntPref("lastError", err);
  757.     },
  758.     get synchOnTimer() {
  759.         return this.getBoolPref("synchOnTimer", true);
  760.     },
  761.     get useBaselineCache() {
  762.         return this.getBoolPref("memory-useBaselineCache", true);
  763.     },
  764.     get forceGC() {
  765.         return this.getBoolPref("memory-forceGC", false);
  766.     },
  767.  
  768.     isSyncEnabled: function(syncType){
  769.         return this.getBoolPref("sync-"+syncType, syncType == "bookmarks");
  770.     },
  771.  
  772.     setSyncEnabled: function(syncType, val){
  773.         this.prefs.setBoolPref("sync-"+syncType, val);
  774.     },
  775.     
  776.     mustMerge: function(syncType){
  777.         return this.getBoolPref("mergereq-"+syncType, false);
  778.     },
  779.     setMustMerge: function(syncType, val){
  780.         this.prefs.setBoolPref("mergereq-"+syncType, val);
  781.     },
  782.     mustUpload: function(syncType){
  783.         return this.getBoolPref("uploadreq-"+syncType, false);
  784.     },
  785.     setMustUpload: function(syncType, val){
  786.         this.prefs.setBoolPref("uploadreq-"+syncType, val);
  787.     },
  788.     get autoSynchFreq() {
  789.         return this.getIntPref("autoSynchFreq", 60);
  790.     },
  791.     
  792.     get syncOnShutdown() {
  793.         return this.getIntPref("syncOnShutdown", true) != 0;
  794.     },
  795.  
  796.     get syncOnShutdownAsk() {
  797.         return this.getBoolPref("syncOnShutdownAsk", true);
  798.     },
  799.     
  800.     get debugUI() {
  801.         return this.getBoolPref("debugUI", false);
  802.     },
  803.     
  804.     get wizardPrefs() {
  805.         return this.getCharPref("wizardPrefURL", "/FX/wiz.json");
  806.     },
  807.     set wizardPrefs(val) {
  808.         this.prefs.setCharPref("wizardPrefURL", val);
  809.     },
  810.     get serpPrefix() {
  811.         return this.getCharPref("serpPrefix", "xmarksserp");
  812.     },
  813.     set serpPrefix(val) {
  814.         this.prefs.setCharPref("serpPrefix", val);
  815.     },
  816.     get wizardWarning() {
  817.         return this.getBoolPref("wizardDoWarning", true);
  818.     },
  819.     set wizardWarning(v){
  820.         this.prefs.setBoolPref("wizardDoWarning", v);
  821.     },
  822.     get wizardRetriesLeft(){
  823.         return this.getIntPref("wizardRetriesLeft", 5);
  824.     },
  825.  
  826.     set wizardRetriesLeft(v){
  827.         this.prefs.setIntPref("wizardRetriesLeft", v);
  828.     },
  829.  
  830.     get lastWizardBubble(){
  831.         return this.getCharPref("wizardLastBubble", "");
  832.     },
  833.  
  834.     set lastWizardBubble(v){
  835.         this.prefs.setCharPref("wizardLastBubble", v);
  836.     },
  837.     
  838.     get wizardMinTimeExpired(){
  839.         var nowMS = Date.now();
  840.         var lastMS = this.lastWizardBubble == "" ? 0 : new Date(this.lastWizardBubble).getTime();
  841.         return (nowMS - lastMS) >= (24 * 3600 * 1000);
  842.     },
  843.  
  844.     wizardResetMinTime: function(){
  845.         this.lastWizardBubble = this.NowAsGMT;
  846.     },
  847.  
  848.     get wizardSuppress() {
  849.         return this.getBoolPref("wizardNoShow", false);
  850.     },
  851.   
  852.     set wizardSuppress(bool) {
  853.        this.prefs.setBoolPref("wizardNoShow", bool);
  854.     },
  855.  
  856.     get disableIfMatchOnPut() {
  857.         return this.getBoolPref("disableIfMatchOnPut", false);
  858.     },
  859.  
  860.     set enableLogging(bool) {
  861.         this.prefs.setBoolPref("enableLogging", bool);
  862.     },
  863.     get enableLogging() {
  864.         return this.getBoolPref("enableLogging", true);
  865.     },
  866.  
  867.     get rememberPassword() {
  868.         return this.getBoolPref("rememberPassword", true);
  869.     },
  870.  
  871.     set rememberPassword(bool) {
  872.         this.prefs.setBoolPref("rememberPassword", bool);
  873.     },
  874.  
  875.  
  876.     get rememberPin() {
  877.         return this.getBoolPref("rememberPin", true);
  878.     },
  879.  
  880.     set rememberPin(bool) {
  881.         this.prefs.setBoolPref("rememberPin", bool);
  882.     },
  883.  
  884.     set username(string) {
  885.         string = string.replace(/^\s+|\s+$/g, '')
  886.         if (string != this.username) {
  887.             this.prefs.setCharPref("username", string);
  888.             this.ClearCredentials();
  889.         }
  890.     },
  891.     
  892.     set password(password) {
  893.         if (this.passwordNoPrompt != password) {
  894.             this.ClearCredentials();
  895.         }
  896.         if (!this.rememberPassword) {
  897.             this.sessionPassword = password;
  898.         } else {
  899.             if(!password)
  900.                 password = "";
  901.             if ("@mozilla.org/passwordmanager;1" in Cc) {
  902.                 // Can't set password without username.
  903.                 if (!this.username)
  904.                     return;
  905.                 var pm = Cc["@mozilla.org/passwordmanager;1"]
  906.                     .createInstance(Ci.nsIPasswordManager);
  907.                 try { 
  908.                     pm.removeUser(this.host, this.username);
  909.                 } catch(e) {}
  910.                 if(password.length > 0)
  911.                     pm.addUser(this.host, this.username, password);
  912.             } else if ("@mozilla.org/login-manager;1" in Cc) {
  913.                 // Can't set password without username.
  914.                 if (!this.username)
  915.                     return;
  916.                 var lm = Cc["@mozilla.org/login-manager;1"].
  917.                     getService(Ci.nsILoginManager);
  918.                 var nsli = new CCon("@mozilla.org/login-manager/loginInfo;1",
  919.                     Ci.nsILoginInfo, "init");
  920.                 var newli = new nsli(this.host, null, SYNC_REALM, 
  921.                     this.username, password, "", "");
  922.                 var oldli = new nsli(this.host, null, SYNC_REALM, 
  923.                     this.username, this.passwordNoPrompt, "", "");
  924.                 try {
  925.                     if(password.length == 0){
  926.                         lm.removeLogin(oldli);
  927.                     }
  928.                     else {
  929.                         lm.modifyLogin(oldli, newli);
  930.                     }
  931.                 } catch (e) {
  932.                     if(password.length > 0)
  933.                         lm.addLogin(newli);
  934.                 }
  935.             }
  936.         }
  937.     },
  938.     
  939.     ClearCredentials: function() {
  940.         var cm = Cc["@mozilla.org/cookiemanager;1"].
  941.             getService(Ci.nsICookieManager);
  942.         cm.remove(".staging.xmarks.com", "SYNCD_AUTH", "/", false);
  943.         cm.remove(".xmarks.com", "SYNCD_AUTH", "/", false);
  944.     },
  945.  
  946.     set lastSynchDate(string) {
  947.         this.prefs.setCharPref(this.hash + "lastSynchDate", string);
  948.     },
  949.  
  950.     set writeCount(integer) {
  951.         this.prefs.setIntPref("writeCount", integer);
  952.     },
  953.         
  954.     set autoSynchFreq(integer) {
  955.         this.prefs.setIntPref("autoSynchFreq", integer);
  956.     },
  957.     
  958.     set synchOnTimer(bool) {
  959.         this.prefs.setBoolPref("synchOnTimer", bool);
  960.     },
  961.     
  962.     set syncOnShutdown(integer) {
  963.         this.prefs.setIntPref("syncOnShutdown", integer);
  964.     },
  965.     
  966.     set syncOnShutdownAsk(bool) {
  967.         this.prefs.setBoolPref("syncOnShutdownAsk", bool);
  968.     },
  969.  
  970.     set debugUI(bool) {
  971.         this.prefs.setBoolPref("debugUI", bool);
  972.     },
  973.  
  974.     set serpEnabled(v){
  975.         this.prefs.setBoolPref("enableSERP", v);
  976.     },
  977.  
  978.     get serpEnabled(){
  979.         return this.getBoolPref("enableSERP", true);
  980.     },
  981.  
  982.     set simsiteEnabled(v){
  983.         this.prefs.setBoolPref("enableSimSite", v);
  984.     },
  985.  
  986.     get simsiteEnabled(){
  987.         return this.getBoolPref("enableSimSite", true);
  988.     },
  989.  
  990.     get serpRegex(){
  991.         return this.getCharPref("SERPRegEx", "(http:\/\/www\.google\..+\/.*[?&]q=([^&]+))|(http:\/\/[-a-zA-Z]+\.start3\.mozilla\.com\/search\?.*[?&]q=([^&]+))|(http:\/\/search\.yahoo\.com\/search?.*[?&]p=([^&]+))|(http:\/\/search\.(msn|live)\.com\/results\.aspx?.*[?&]q=([^&]+))");
  992.     },
  993.     set serpRegex(v){
  994.         this.prefs.setCharPref("SERPRegEx", v);
  995.     },
  996.     get serpMaxItems(){
  997.         return this.getIntPref("SERPMaxItems", 3);
  998.     },
  999.  
  1000.     set serpMaxItems(val) {
  1001.         this.prefs.setIntPref("SERPMaxItems", val);
  1002.     },
  1003.     set tagSuggestionsEnabled(v){
  1004.         this.prefs.setBoolPref("enableTagSuggestions", v);
  1005.     },
  1006.  
  1007.     get is_english(){
  1008.         var lang = this.lang;
  1009.         if(lang){
  1010.             return lang.split("-")[0] == 'en';
  1011.         }
  1012.         return true;
  1013.     },
  1014.     get lang(){
  1015.         var prefs = Components.classes["@mozilla.org/preferences-service;1"]
  1016.             .getService(Components.interfaces.nsIPrefBranch2);
  1017.         var lang = prefs.getComplexValue("intl.accept_languages",
  1018.                 Ci.nsIPrefLocalizedString).data;
  1019.  
  1020.         if(lang){
  1021.             var a = lang.split(",");
  1022.             if(a.length){
  1023.                 return a[0];
  1024.             }
  1025.         }
  1026.         return lang;
  1027.     },
  1028.     get tagSuggestionsEnabled() {
  1029.         var result;
  1030.         
  1031.         try {
  1032.             result = this.prefs.getBoolPref("enableTagSuggestions");
  1033.         } catch (e) {
  1034.             try {
  1035.                 var prefs = Components.classes["@mozilla.org/preferences-service;1"]
  1036.                                 .getService(Components.interfaces.nsIPrefBranch2);
  1037.                 var lang = prefs.getComplexValue("intl.accept_languages",
  1038.                     Ci.nsIPrefLocalizedString).data;
  1039.                 result = lang.substr(0, 2) == "en";
  1040.                 this.tagSuggestionsEnabled = result;
  1041.             } catch(f){
  1042.                 result = false;
  1043.             }
  1044.         }
  1045.         
  1046.         return result;
  1047.     },
  1048.     
  1049.     // get calculated settings
  1050.     get calcPath() {
  1051.         return this.path.replace("{username}", this.username);
  1052.     },
  1053.        
  1054.     get NowAsGMT() {
  1055.         var d = new Date();
  1056.         return d.toGMTString();
  1057.     },
  1058.     
  1059.  
  1060.     SyncComplete: function(syncType) {
  1061.         this.setLastSyncDate(syncType, this.NowAsGMT);
  1062.         // TODO - remove the last sync by type; it's really unnecssary and causes issues if bookmarks are being synced
  1063.         if(!this.isSyncEnabled("bookmarks")){
  1064.             this.setLastSyncDate("bookmarks", this.NowAsGMT);
  1065.         }
  1066.     },
  1067.  
  1068.     // Additions to support Sync2
  1069.     get useOwnServer() {
  1070.         return this.getBoolPref("useOwnServer", false);
  1071.     },
  1072.  
  1073.     set useOwnServer(bool) {
  1074.         this.prefs.setBoolPref("useOwnServer", bool);
  1075.     },
  1076.  
  1077.     set url(u) {
  1078.         this.prefs.setCharPref("url-bookmarks", u);
  1079.     },
  1080.  
  1081.     get url() {
  1082.         return this.getCharPref("url-bookmarks",
  1083.             this.getCharPref("url", ""));
  1084.     },
  1085.  
  1086.     set passwordurl(u) {
  1087.         this.prefs.setCharPref("url-passwords", u);
  1088.     },
  1089.  
  1090.     get passwordurl() {
  1091.         return this.getCharPref("url-passwords", "");
  1092.     },
  1093.  
  1094.     set hideStatusIcon(b) {
  1095.         this.prefs.setBoolPref("hideStatusIcon", b);
  1096.         var os = Cc["@mozilla.org/observer-service;1"].
  1097.             getService(Ci.nsIObserverService);
  1098.         os.notifyObservers(null, "foxmarks-statechange", 
  1099.             gSettings.hideStatusIcon ?  "hide" : "show")
  1100.     },
  1101.  
  1102.     get hideStatusIcon() {
  1103.         return this.getBoolPref("hideStatusIcon", false);
  1104.     },
  1105.  
  1106.     getUrlWithUsernameAndPassword: function(syncType){
  1107.         var url;
  1108.         if(syncType == "bookmarks")
  1109.             url = this.url;
  1110.         else
  1111.             url = this.getCharPref("url-" + syncType, "");
  1112.             
  1113.         var user = this.username;
  1114.         var pw = this.password;
  1115.         
  1116.         if (pw.length) {
  1117.             user += ":" + pw;
  1118.         }
  1119.  
  1120.         if (user.length) {
  1121.             user += "@";
  1122.         }
  1123.  
  1124.         return url.replace("://", "://" + user);
  1125.     },
  1126.  
  1127.     get majorVersion() {
  1128.         return this.getIntPref("majorVersion", 1);
  1129.     },
  1130.  
  1131.     set majorVersion(ver) {
  1132.         this.prefs.setIntPref("majorVersion", ver);
  1133.     },
  1134.  
  1135.     get currVersion(){
  1136.         return this.getCharPref("lastUpdateVersion", "");
  1137.     },
  1138.  
  1139.     set currVersion(ver){
  1140.         this.prefs.setCharPref("lastUpdateVersion", ver);
  1141.     },
  1142.  
  1143.     get host() {
  1144.         if (this.useOwnServer) {
  1145.             var exp = /(.*):\/\/([^\/]*)/;
  1146.             var result = this.url.match(exp);
  1147.             if (!result) {
  1148.                 return null;
  1149.             } else {
  1150.                 return result[1] + "://" + result[2];
  1151.             }
  1152.         } else {
  1153.             return this.getCharPref("host-bookmarks",
  1154.                        this.getCharPref("host", "sync.xmarks.com"));
  1155.         }
  1156.     },
  1157.  
  1158.     setDebugOption: function(opt, val){
  1159.         this.prefs.setBoolPref("debug-" + opt, val);
  1160.     },
  1161.     getDebugOption: function(opt){
  1162.         return this.getBoolPref("debug-" + opt, false);
  1163.     },
  1164.     getUnitTestOption: function(opt){
  1165.         return this.getIntPref("unittest-" + opt, 0);
  1166.     },
  1167.     getServerHost: function(syncType){
  1168.         if(syncType == "bookmarks" || this.useOwnServer)
  1169.             return this.host;
  1170.         else
  1171.             return this.getCharPref("host-" + syncType, "sync.xmarks.com");
  1172.     },
  1173.     
  1174.     get numTurboTags(){
  1175.         return this.getIntPref("turbotagctr", 0);
  1176.     },
  1177.     set numTurboTags(num){
  1178.         this.prefs.setIntPref("turbotagctr", num);
  1179.     },
  1180.  
  1181.     get apiHost() {
  1182.         return this.getCharPref("host-api", "api.xmarks.com");
  1183.     },
  1184.     set apiHost(val) {
  1185.         this.prefs.setCharPref("host-api", val);
  1186.     },
  1187.     get driftHost() {
  1188.         return this.getCharPref("host-drift", "www.xmarks.com");
  1189.     },
  1190.     set driftHost(val) {
  1191.         this.prefs.setCharPref("host-drift", val);
  1192.     },
  1193.     get staticHost() {
  1194.         return this.getCharPref("host-static", "static.xmarks.com");
  1195.     },
  1196.     set staticHost(val) {
  1197.         this.prefs.setCharPref("host-static", val);
  1198.     },
  1199.     get acctMgrHost() {
  1200.         return this.useOwnServer ? "" : 
  1201.             this.getCharPref("host-login",
  1202.                 this.getCharPref("acctMgrHost",
  1203.                     this.host.replace("sync", "login")
  1204.                 )
  1205.             );
  1206.     },
  1207.  
  1208.     get truncateLog(){
  1209.         return this.getBoolPref("truncateLog", true);
  1210.  
  1211.     },
  1212.     get webHost() {
  1213.         return this.useOwnServer ? "www.xmarks.com" : 
  1214.             this.getCharPref("host-www",
  1215.                 this.getCharPref("acctMgrHost",
  1216.                     this.host.replace("sync", "www")
  1217.                 )
  1218.             );
  1219.     },
  1220.     get wizardUrl() {
  1221.         return this.getCharPref("wizardUrl", "https://" + 
  1222.             this.acctMgrHost + "/wizard");
  1223.     },
  1224.  
  1225.     // -1: never synced
  1226.     //  0: likely synced in prior installation
  1227.     //  > 0: definitely synced
  1228.     get currentRevision() {
  1229.         return this.getIntPref(this.hash + "currentRevision", -1);
  1230.     },
  1231.  
  1232.     set currentRevision(cv) {
  1233.         if (cv != this.currentRevision) {
  1234.             this.prefs.setIntPref(this.hash + "currentRevision", cv);
  1235.             this.ps.savePrefFile(null);     // ensure it gets flushed
  1236.         }
  1237.     },
  1238.  
  1239.     GetSyncRevision: function(syncType) {
  1240.         if(syncType == "bookmarks")
  1241.             return this.getIntPref(this.hash + "currentRevision", -1);
  1242.         else    
  1243.             return this.getIntPref(this.hash + syncType + "-currentRevision", -1);
  1244.     },
  1245.  
  1246.     SetSyncRevision: function(syncType,cv) {
  1247.         if (cv != this.GetSyncRevision(syncType)) {
  1248.             if(syncType == "bookmarks")
  1249.                 this.prefs.setIntPref(this.hash + "currentRevision", cv);
  1250.             else
  1251.                 this.prefs.setIntPref(this.hash + syncType + "-currentRevision", cv);
  1252.             this.ps.savePrefFile(null);     // ensure it gets flushed
  1253.         }
  1254.     },
  1255.     get securityLevel() {
  1256.         // -1: use cleartext throughout
  1257.         //  0: use SSL for auth, cleartext otherwise (default)
  1258.         //  1: use SSL everywhere
  1259.         return this.getIntPref("securityLevel", 0);
  1260.     },
  1261.  
  1262.     set securityLevel(level) {
  1263.         this.prefs.setIntPref("securityLevel", level);
  1264.     },
  1265.  
  1266.     get disableIconSync() {
  1267.         return this.getBoolPref("disableIconSync", false);
  1268.     },
  1269.  
  1270.     get disableDirtyOnBatch() {
  1271.         return this.getBoolPref("disableDirtyOnBatch", false);
  1272.     },
  1273.  
  1274.     get machineId() {
  1275.         var id = this.getCharPref("machineId", null);
  1276.         if (!id) {
  1277.             id = Date.now().toString(36);
  1278.             this.prefs.setCharPref("machineId", id);
  1279.         }
  1280.         return id;
  1281.     },
  1282.  
  1283.     get serverVersion() {
  1284.         return this.getIntPref("serverVersion", 0);
  1285.     },
  1286.  
  1287.     set serverVersion(val) {
  1288.         this.prefs.setIntPref("serverVersion", val);
  1289.     },
  1290.     get viewId() {
  1291.         return this.getIntPref(this.hash + "viewId", 0);
  1292.     },
  1293.  
  1294.     set viewId(vid) {
  1295.         this.prefs.setIntPref(this.hash + "viewId", vid);
  1296.     },
  1297.  
  1298.     _stPref: function(undec, id, v){
  1299.         if(undec){
  1300.             return "UST-" + id + "-" + v;
  1301.         }
  1302.         return "ST-" + id + "-" + v;
  1303.     },
  1304.     getST: function(undec,id){
  1305.         var result = {};
  1306.         var val;
  1307.  
  1308.         val = this.getIntPref(this._stPref(undec,id, "d"), 0);
  1309.         if(val) result["d"] = val;
  1310.         val = this.getIntPref(this._stPref(undec,id, "dc"), 0);
  1311.         if(val) result["dc"] = val;
  1312.         val = this.getIntPref(this._stPref(undec,id, "u"), 0);
  1313.         if(val) result["u"] = val;
  1314.         val = this.getIntPref(this._stPref(undec,id, "uc"), 0);
  1315.         if(val) result["uc"] = val;
  1316.         val = this.getIntPref(this._stPref(undec,id, "na"), 0);
  1317.         if(val) result["na"] = val;
  1318.         val = this.getIntPref(this._stPref(undec,id, "h"), 0);
  1319.         if(val) result["h"] = val;
  1320.  
  1321.         return result;
  1322.     },
  1323.     incrST: function(id, key, undec){
  1324.         var name;
  1325.  
  1326.         name = this._stPref(undec,id, key);
  1327.         this.prefs.setIntPref(name, this.getIntPref(name, 0) + 1);
  1328.  
  1329.     },
  1330.     clearST: function(id){
  1331.         this.prefs.setIntPref(this._stPref(true, id, "d"),0);
  1332.         this.prefs.setIntPref(this._stPref(true, id, "dc"),0);
  1333.         this.prefs.setIntPref(this._stPref(true, id, "u"),0);
  1334.         this.prefs.setIntPref(this._stPref(true, id, "uc"),0);
  1335.         this.prefs.setIntPref(this._stPref(true, id, "na"),0);
  1336.         this.prefs.setIntPref(this._stPref(true, id, "h"),0);
  1337.         this.prefs.setIntPref(this._stPref(false, id, "d"),0);
  1338.         this.prefs.setIntPref(this._stPref(false, id, "dc"),0);
  1339.         this.prefs.setIntPref(this._stPref(false, id, "u"),0);
  1340.         this.prefs.setIntPref(this._stPref(false, id, "uc"),0);
  1341.         this.prefs.setIntPref(this._stPref(false, id, "na"),0);
  1342.         this.prefs.setIntPref(this._stPref(false, id, "h"),0);
  1343.     },
  1344.  
  1345.     get trSERP() {
  1346.         return this.getCharPref("trSERP", "");
  1347.     },
  1348.  
  1349.     set trSERP(val) {
  1350.         this.prefs.setCharPref("trSERP", val);
  1351.     },
  1352.     get bibBug() {
  1353.         return this.getCharPref("bibBug", "/FX/xmarks_bib.png");
  1354.     },
  1355.  
  1356.     set bibBug(val) {
  1357.         this.prefs.setCharPref("bibBug", val);
  1358.     },
  1359.  
  1360.     get viewName() {
  1361.         return this.getCharPref(this.hash + "viewName", this.viewId ?
  1362.             String(this.viewId) : 
  1363.             Bundle().GetStringFromName("profile.globalname"));
  1364.     },
  1365.  
  1366.     set viewName(name) {
  1367.         this.prefs.setCharPref(this.hash + "viewName", name);
  1368.     },
  1369.  
  1370.     get syncShortcutKey() {
  1371.         return this.getCharPref("shortcut.SyncNow", "");
  1372.     },
  1373.  
  1374.     get siteinfoDialogShortcutKey() {
  1375.         return this.getCharPref("shortcut.SiteInfo", "");
  1376.     },
  1377.     get openSettingsDialogShortcutKey() {
  1378.         return this.getCharPref("shortcut.OpenSettings", "");
  1379.     },
  1380.  
  1381.     correctHashes: function(){
  1382.         var oldhash = "";
  1383.         // if we are now using the default host, we must
  1384.         // have used sync.foxmarks.com before
  1385.         LogWrite("Upgrading to 3.0: correcting hashes");
  1386.         LogWrite("Current Host: " + this.host);
  1387.         if(this.host == "sync.xmarks.com"){
  1388.             oldhash = this._calcHash("sync.foxmarks.com");
  1389.  
  1390.             LogWrite("Hashes Need Correction");
  1391.             // change all the hosts
  1392.             this.prefs.setCharPref(this.hash + "lastSynchDate", 
  1393.                 this.getCharPref(oldhash + "lastSynchDate", ""));
  1394.             this.prefs.setCharPref(this.hash + "passwords-lastSynchDate", 
  1395.                 this.getCharPref(oldhash + "passwords-lastSynchDate", ""));
  1396.             this.prefs.setIntPref(this.hash + "currentRevision", 
  1397.                 this.getIntPref(oldhash + "currentRevision", -1));
  1398.             this.prefs.setIntPref(this.hash + "passwords-currentRevision", 
  1399.                 this.getIntPref(oldhash + "passwords-currentRevision", -1));
  1400.             this.prefs.setIntPref(this.hash + "viewId", 
  1401.                 this.getIntPref(oldhash + "viewId", 0));
  1402.             this.prefs.setCharPref(this.hash + "viewName", 
  1403.                 this.getCharPref(oldhash + "viewName", this.viewId ?
  1404.                     String(this.viewId) : 
  1405.                     Bundle().GetStringFromName("profile.globalname")
  1406.             ));
  1407.         } else {
  1408.             oldhash = this.hash;
  1409.         }
  1410.  
  1411.         // bookmark baseline 
  1412.         var dirname = Cc['@mozilla.org/file/directory_service;1']
  1413.             .getService(Ci.nsIProperties)
  1414.             .get('ProfD', Ci.nsIFile);
  1415.         var file = Cc['@mozilla.org/file/directory_service;1']
  1416.             .getService(Ci.nsIProperties)
  1417.             .get('ProfD', Ci.nsIFile);
  1418.         var fromname = "foxmarks-baseline-" + oldhash + "json";
  1419.         var toname = "xmarks-baseline-" + this.hash + "json";
  1420.  
  1421.         try {
  1422.             file.append(fromname);
  1423.             file.moveTo(dirname, toname);
  1424.         } catch(e){
  1425.             // don't do anything if file doesn't exist
  1426.         }
  1427.  
  1428.         // password baseline
  1429.         file = Cc['@mozilla.org/file/directory_service;1']
  1430.             .getService(Ci.nsIProperties)
  1431.             .get('ProfD', Ci.nsIFile);
  1432.         fromname = "foxmarks-password-baseline-" + oldhash + "json";
  1433.         toname = "xmarks-password-baseline-" + this.hash + "json";
  1434.  
  1435.         try {
  1436.             file.append(fromname);
  1437.             file.moveTo(dirname, toname);
  1438.         } catch(e){
  1439.             // don't do anything if file doesn't exist
  1440.         }
  1441.  
  1442.         this.ps.savePrefFile(null);     // ensure it gets flushed
  1443.     }
  1444. }
  1445.  
  1446. var gSettings = new FoxmarksSettings();
  1447.