home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / AIMP2 / aimp_2.61.583.exe / $TEMP / YandexPackSetup.msi / fil8804DAAB017ADF30C02527628F44E55F < prev    next >
Text File  |  2010-07-12  |  22KB  |  765 lines

  1. var gYaBookmarks = {
  2.   _init: function() {
  3.     OBSERVER_SERVICE.addObserver(this, "quit-application-granted", false);
  4.     OBSERVER_SERVICE.addObserver(this, "Ya-Refresh-Login-Status", false);
  5.   },
  6.  
  7.   _uninit: function() {
  8.     OBSERVER_SERVICE.removeObserver(this, "Ya-Refresh-Login-Status");
  9.     OBSERVER_SERVICE.removeObserver(this, "quit-application-granted");
  10.   },
  11.  
  12.   observe: function(aSubject, aTopic, aData) {
  13.     switch (aTopic) {
  14.       case "Ya-Refresh-Login-Status":
  15.         this.refreshBookmarksDOMMenu();
  16.         break;
  17.  
  18.       case "quit-application-granted":
  19.         this._uninit();
  20.         break;
  21.     }
  22.   },
  23.  
  24.   refreshBookmarksDOMMenu: function() {
  25.     this.bookmarksCache.clear();
  26.  
  27.     gYaSearchService.bookmarksDOMMenu = false;
  28.     OBSERVER_SERVICE.notifyObservers(null, "Ya-Refresh-Data", "bookmarks");
  29.   },
  30.  
  31.   __isRegRequired: false,
  32.  
  33.   get isRegRequired() {
  34.     return !!this.__isRegRequired;
  35.   },
  36.  
  37.   set isRegRequired(val) {
  38.     if (this.__isRegRequired !== null)
  39.       this.__isRegRequired = val;
  40.  
  41.     return this.__isRegRequired;
  42.   },
  43.  
  44.   getServerResponse: function(aResponseString) {
  45.     var result = {
  46.       xml: gYaSearchService.safeE4Xml(gYaSearchService.safeUnicode(aResponseString), null, ["page", "yaru"]),
  47.       error: 0
  48.     };
  49.  
  50.     if (!result.xml || result.xml.xscript_invoke_failed.length()) {
  51.       result.error = "service";
  52.     } else if (result.xml.err.length()) {
  53.       var err = result.xml.err[0];
  54.  
  55.       if ("spam" === err.@code.toString()) {
  56.         result.error = "spam";
  57.       } else {
  58.         switch (err.toString()) {
  59.           case "Exception: input":
  60.             result.error = "input";
  61.             break;
  62.  
  63.           case "Exception: auth_required":
  64.             result.error = "auth_required";
  65.             break;
  66.  
  67.           case "Exception: reg_required":
  68.             result.error = "reg_required";
  69.             this.isRegRequired = true;
  70.             break;
  71.  
  72.           case "Exception: wow":
  73.             if (!result.xml.has_not_journal.length())
  74.               result.error = "wow_error";
  75.             break;
  76.  
  77.           case "Exception: service":
  78.           default:
  79.             result.error = "service";
  80.             break;
  81.         }
  82.       }
  83.     }
  84.  
  85.     return result;
  86.   },
  87.  
  88.   get bookmarksXML() {
  89.     return gYaSearchService.bookmarksRawXml.bookmarks;
  90.   },
  91.  
  92.   _getHostForBookmarkedCheck: function(aURI) {
  93.     var res = "";
  94.     try {
  95.       if ("scheme" in aURI && /ftp|https?/.test(aURI.scheme))
  96.         res = [aURI.scheme, "://", (aURI.scheme == "file" ? "/" : ""), aURI.hostPort].join("");
  97.     } catch(e) {}
  98.     return res;
  99.   },
  100.  
  101.   _getUrlSpecForBookmarkedCheck: function(aURI) {
  102.     var res = "";
  103.     try {
  104.       if ("scheme" in aURI && /ftp|https?/.test(aURI.scheme))
  105.         res = [this._getHostForBookmarkedCheck(aURI), aURI.path].join("").replace(/(\/|#.+)+$/, "");
  106.     } catch(e) {}
  107.     return res;
  108.   },
  109.  
  110.   bookmarksCache: {
  111.     _maxLength: 100,
  112.     _bookmarksData: [],
  113.  
  114.     _notifyObservers: function(aBookmarkURL) {
  115.       OBSERVER_SERVICE.notifyObservers(null, "Ya-Refresh-Data", "bookmarks-url-status");
  116.     },
  117.  
  118.     add: function(aBookmarkData, aNotifyObservers) {
  119.       var url = aBookmarkData.url;
  120.  
  121.       var exists = this._bookmarksData.some(function(bmData) { return url === bmData.url; });
  122.  
  123.       if (!exists) {
  124.         this._bookmarksData.splice(this._maxLength);
  125.         this._bookmarksData.unshift(aBookmarkData);
  126.  
  127.         if (aNotifyObservers)
  128.           this._notifyObservers();
  129.       }
  130.     },
  131.  
  132.     remove: function(aBookmarkURL, aNotifyObservers) {
  133.       this._bookmarksData = [bmData for each (bmData in this._bookmarksData) if (aBookmarkURL !== bmData.url)];
  134.       if (aNotifyObservers)
  135.         this._notifyObservers();
  136.     },
  137.  
  138.     clear: function() {
  139.       this._bookmarksData = [];
  140.       this._notifyObservers();
  141.     },
  142.  
  143.     getData: function(aBookmarkURL) {
  144.       var bmData = this._bookmarksData.filter(function(bmData) { return aBookmarkURL === bmData.url; });
  145.       return bmData.length ? bmData[0] : null;
  146.     }
  147.   },
  148.  
  149.   isBookmarkedURIinCache: function(aURI) {
  150.     var url = this._getUrlSpecForBookmarkedCheck(aURI);
  151.     if (!url)
  152.       return false;
  153.  
  154.     var res = this.bookmarksCache.getData(url);
  155.  
  156.     return res ? res.bookmarked : null;
  157.   },
  158.  
  159.   isBookmarkedURI: function(aURI) {
  160.     var res = false;
  161.  
  162.     var id = null,
  163.         folderId = null;
  164.  
  165.     var url = this._getUrlSpecForBookmarkedCheck(aURI);
  166.  
  167.     if (url) {
  168.       if (this._addBookmarkQueue.hasBookmarkForURL(url)) {
  169.         res = "adding";
  170.       } else if (this.bookmarksXML) {
  171.         var regexpUrl = new RegExp(url.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1')
  172.                                       .replace(/(https?\\:\\\/\\\/)(www\\.)?/, '$1(www\\.)?'));
  173.  
  174.           var bookmarkedLink = false;
  175.           for each (var link in this.bookmarksXML..link.(regexpUrl.test(@url))) {
  176.             var endOfUrl = link.@url.split(regexpUrl).pop();
  177.             if (endOfUrl && !(/^\/$/.test(endOfUrl) || /^\/?#/.test(endOfUrl)))
  178.               continue;
  179.  
  180.             bookmarkedLink = link;
  181.             break;
  182.           }
  183.  
  184.           if (bookmarkedLink) {
  185.             res = "url";
  186.             id = bookmarkedLink.@id.toString();
  187.             folderId = 0;
  188.           }
  189.       }
  190.     }
  191.  
  192.     res = { url: url,
  193.             id: id,
  194.             folderId: folderId,
  195.             bookmarked: res }
  196.  
  197.     this.bookmarksCache.add(res);
  198.  
  199.     return res;
  200.   },
  201.  
  202.   getBrowserPageData: function(aBrowser) {
  203.     var res = {url: "", name: "", descr: ""};
  204.  
  205.     var url = this._getUrlSpecForBookmarkedCheck(aBrowser.currentURI);
  206.  
  207.     if (!/^about:/.test(url)) {
  208.       res.url = url;
  209.       res.name = aBrowser.contentTitle;
  210.  
  211.       var metaNodes = aBrowser.contentDocument.defaultView.document.getElementsByTagName("meta");
  212.       for (var i = 0, len = metaNodes.length; i < len; i++) {
  213.         var metaName = (metaNodes[i].name || "").toLowerCase();
  214.         if (metaName == "description" && metaNodes[i].content) {
  215.           res.descr = metaNodes[i].content;
  216.           break;
  217.         }
  218.       }
  219.     }
  220.  
  221.     return res;
  222.   },
  223.  
  224.   _addBookmarkQueue: {
  225.     _elements: [],
  226.     _elementsAfterError: [],
  227.  
  228.     get size() {
  229.       return this._elements.length;
  230.     },
  231.  
  232.     get isEmpty() {
  233.       return !this.size;
  234.     },
  235.  
  236.     get isBusy() {
  237.       return this._isBusy;
  238.     },
  239.  
  240.     hasBookmarkForURL: function(aURL) {
  241.       for each (var bookmarkData in this._elements.concat(this._elementsAfterError))
  242.         if (bookmarkData.url == aURL)
  243.           return true;
  244.  
  245.       return false;
  246.     },
  247.  
  248.     clear: function() {
  249.       this._elements = [];
  250.       this._elementsAfterError = [];
  251.       this._isBusy = false;
  252.     },
  253.  
  254.     push: function(aBookmarkData) {
  255.       if (this.hasBookmarkForURL(aBookmarkData.url))
  256.         return false;
  257.  
  258.       this._elements.push(aBookmarkData);
  259.  
  260.       gYaBookmarks.bookmarksCache.remove(aBookmarkData.url, true);
  261.  
  262.       this._checkNeedProccess();
  263.  
  264.       return true;
  265.     },
  266.  
  267.     shift: function() {
  268.       return this._elements.shift();
  269.     },
  270.  
  271.     get topElement() {
  272.       return this._elements[0];
  273.     },
  274.  
  275.     _checkNeedProccess: function() {
  276.       if (this.isBusy)
  277.         return false;
  278.  
  279.       if (this.isEmpty) {
  280.         var elementsAfterError = this._elementsAfterError;
  281.  
  282.         this.clear();
  283.  
  284.         gYaBookmarks.bookmarksCache.clear(true);
  285.  
  286.         if (elementsAfterError.length) {
  287.           if (elementsAfterError.length == 1) {
  288.             gYaBookmarks.showError(elementsAfterError[0].error, "add");
  289.           }
  290.           else {
  291.             var failedBookmarksTitles = "";
  292.             for each (bookmarkData in elementsAfterError) {
  293.               var str = bookmarkData.name.length? bookmarkData.name : bookmarkData.url;
  294.               if (str.length > 50)
  295.                 str = str.substr(0, 50) + "...";
  296.               failedBookmarksTitles += (str + "\n");
  297.             }
  298.             var readableReason = gYaBookmarks.getString("Reason_" + elementsAfterError[elementsAfterError.length - 1].error);
  299.             gYaSearchService.promptService.alert(
  300.               null,
  301.               gYaBookmarks.getString("Error_bgfailed_Title"),
  302.               gYaBookmarks.getFormattedString("Error_bgfailed_Message", [failedBookmarksTitles, readableReason]));
  303.           }
  304.         }
  305.  
  306.         return false;
  307.       }
  308.  
  309.       this._isBusy = true;
  310.  
  311.       this.topElement.callback = this._proccessCallback.bind(this);
  312.       gYaSearchService.bookmarksInsertNewItem(this.topElement);
  313.  
  314.       return true;
  315.     },
  316.     
  317.     _criticalErrors: ["auth_required", "reg_required", "spam"],
  318.     
  319.     _errorIsCritical: function(err) {
  320.       return !(this._criticalErrors.indexOf(err) == -1);
  321.     },
  322.  
  323.     _proccessCallback: function(aData) {
  324.       this._isBusy = false;
  325.       var currentElement = this.shift();
  326.  
  327.       if ("string" == typeof aData) {
  328.         currentElement.callback = null;
  329.         currentElement.error = aData;
  330.         
  331.         this._elementsAfterError.push(currentElement);
  332.         
  333.         if (this._errorIsCritical(aData)) {
  334.           this._elementsAfterError = this._elementsAfterError.concat(this._elements);
  335.           this._elements = [];
  336.         }
  337.       }
  338.       
  339.       this._checkNeedProccess();
  340.     }
  341.   },
  342.  
  343.   getStringBundle: function() {
  344.     if (!this.stringBundle) {
  345.       var strBundleService = Cc["@mozilla.org/intl/stringbundle;1"].createInstance(Ci.nsIStringBundleService);
  346.       this.stringBundle = strBundleService.createBundle("chrome://yasearch/locale/bookmarks/bookmarks.properties");
  347.     }
  348.     return this.stringBundle;
  349.   },
  350.  
  351.   getString: function(aName) {
  352.     return this.getStringBundle().GetStringFromName(aName);
  353.   },
  354.  
  355.   getFormattedString: function(aName, aStrArray) {
  356.     return this.getStringBundle().formatStringFromName(aName, aStrArray, aStrArray.length);
  357.   },
  358.  
  359.   showError: function(aErrorType, aBookmarkingMode) {
  360.     if (aErrorType === "reg_required")
  361.       return this.showRegRequiredDialog();
  362.  
  363.     var t1 = [this.getString("Action_" + aBookmarkingMode + "_InTitle")];
  364.     var t2 = [this.getString("Action_" + aBookmarkingMode + "_InMessage")];
  365.  
  366.     if (aErrorType === "input") {
  367.       t2.unshift(t1);
  368.     }
  369.  
  370.     var errorType = "Error_" + aErrorType + "_";
  371.  
  372.     gYaSearchService.promptService.alert(null,
  373.         this.getFormattedString(errorType + "Title", t1),
  374.         this.getFormattedString(errorType + "Message", t2)
  375.     );
  376.   },
  377.  
  378.   showRegRequiredDialog: function() {
  379.     const winType = "Yasearch:BookmarksRegRequiredDialog";
  380.  
  381.     var regRequiredWindow = gYaSearchService.getWindow(winType);
  382.     if (regRequiredWindow)
  383.       regRequiredWindow.focus();
  384.     else
  385.       gYaSearchService.windowWatcher.openWindow(
  386.         null,
  387.         CHROME_CONTENT + "bookmarks/regrequiredDialog.xul",
  388.         winType,
  389.         "chrome,resizable=no,dependent=yes,centerscreen",
  390.         null);
  391.   },
  392.  
  393.   addBookmarkInBackground: function(aBrowser) {
  394.     var bookmarkData = gYaBookmarks.getBrowserPageData(aBrowser);
  395.     if (!bookmarkData.url || gYaBookmarks.isBookmarkedURI(bookmarkData.url).bookmarked)
  396.       return false;
  397.  
  398.     bookmarkData.tags = "";
  399.     bookmarkData.folder = 0;
  400.  
  401.     this._addBookmarkQueue.push(bookmarkData);
  402.   },
  403.  
  404.   formatTagsString: function(aString, aReturnArray) {
  405.     var tagsHash = {}, tagsArray = aString.toString().split(",");
  406.  
  407.     for (var i = tagsArray.length; i-- > 0;) {
  408.       var tag = tagsArray[i].replace(/[^\x20-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]/g, "")
  409.                              .replace(/^\s+/, "")
  410.                              .replace(/\s+$/, "")
  411.                              .replace(/\s+/g, " ");
  412.  
  413.       if (tag != "" && !tagsHash[tag])
  414.         tagsHash[tag] = true;
  415.     }
  416.  
  417.     tagsArray = [];
  418.  
  419.     for (var tag in tagsHash)
  420.       tagsArray.push(tag);
  421.  
  422.     tagsArray.reverse();
  423.  
  424.     return aReturnArray ? tagsArray : tagsArray.join(", ");
  425.   },
  426.  
  427.   getTagsListArray: function(aLimitNmb) {
  428.     var tagsHash = {};
  429.  
  430.     var linkXMLElements = this.bookmarksXML..link;
  431.  
  432.     for (var i=0, len = linkXMLElements.length(); i < len; i++) {
  433.       var linkTags = linkXMLElements[i].@tags.toString();
  434.  
  435.       if (linkTags) {
  436.         var tagsArray = this.formatTagsString(linkTags, true);
  437.         for each (var tag in tagsArray) {
  438.           tagsHash[tag] ?
  439.               (tagsHash[tag].count++) :
  440.               (tagsHash[tag] = {value: tag, count: 1});
  441.         }
  442.       }
  443.     }
  444.  
  445.     var tagsArray = [];
  446.  
  447.     for each (var tag in tagsHash)
  448.       tagsArray.push(tag);
  449.  
  450.     tagsHash = null;
  451.  
  452.     tagsArray = this.sortTagsArrayByCount(tagsArray);
  453.  
  454.     if (aLimitNmb)
  455.       tagsArray = tagsArray.slice(0, aLimitNmb);
  456.  
  457.     return tagsArray;
  458.   },
  459.  
  460.   sortTagsArrayByCount: function(aTagsArray) {
  461.     aTagsArray.sort(function(a,b) {
  462.       return (a.count > b.count) ? -1 : (a.count < b.count) ? 1 :
  463.                   ((a.value > b.value) ? -1 : (a.value < b.value) ? 1 : 0);
  464.     });
  465.  
  466.     return aTagsArray;
  467.   },
  468.  
  469.   sortTagsArrayByName: function(aTagsArray) {
  470.     aTagsArray.sort(function(a,b) {
  471.       var aLower = a.toLowerCase(), bLower = b.toLowerCase();
  472.  
  473.       return (aLower < bLower) ? -1 : (aLower > bLower) ? 1 :
  474.                 ((a < b) ? -1 : (a > b) ? 1 : 0);
  475.     });
  476.  
  477.     return aTagsArray;
  478.   },
  479.  
  480.   getDataForTagsContainer: function(aLimitNmb) {
  481.     var resArray = [], tagsArray = this.getTagsListArray(aLimitNmb);
  482.  
  483.     for each (var tagObject in tagsArray)
  484.       resArray.push(tagObject.value);
  485.  
  486.     return resArray;
  487.   },
  488.  
  489.   showTags: function(aInput, aLimitNmb, aLimitNmbToShow) {
  490.     var tagsArray = this.formatTagsString(aInput.value, true);
  491.     var tagsData = this.getDataForTagsContainer(aLimitNmb);
  492.  
  493.     var res = {};
  494.  
  495.     for each (var tag in tagsData) {
  496.       res[tag] = {value: tag};
  497.       for each (var value in tagsArray) {
  498.         if (value == tag)
  499.           res[tag].disabled = true;
  500.       }
  501.     }
  502.  
  503.     var resLimited;
  504.  
  505.     if (aLimitNmbToShow && tagsData.length) {
  506.       resLimited = {};
  507.  
  508.       tagsData = this.sortTagsArrayByName(tagsData.slice(0, aLimitNmbToShow));
  509.  
  510.       for each (var tag in tagsData)
  511.         resLimited[tag] = {value: tag};
  512.     }
  513.  
  514.     aInput.showTags(res, resLimited);
  515.   },
  516.  
  517.   handleTextChange: function(aInput) {
  518.     var value = aInput.value;
  519.     if (value === aInput.lastTextValue) return;
  520.  
  521.     var tagsArray = this.formatTagsString(value, true);
  522.  
  523.     if (aInput.tagMaxLength) {
  524.       for each (var tag in tagsArray) {
  525.           if (tag.length > aInput.tagMaxLength) {
  526.             aInput.value = aInput.lastTextValue;
  527.           aInput.selectTextRange(aInput.lastCursorPosition, aInput.lastCursorPosition);
  528.           aInput.showMaxLengthTooltip();
  529.           return;
  530.           }
  531.       }
  532.     }
  533.  
  534.     for each (var tagList in aInput.tagsList) {
  535.       var exist = false;
  536.  
  537.       for (var i=0, len = tagsArray.length; i < len; i++) {
  538.         if (tagsArray[i] === tagList.value) {
  539.           if (tagList.element && tagList.element.getAttribute("disabled") != "true")
  540.             tagList.element.setAttribute("disabled", "true");
  541.  
  542.           exist = tagsArray.splice(i,1);
  543.  
  544.           break;
  545.         }
  546.       }
  547.  
  548.       if (!exist && tagList.element && tagList.element.getAttribute("disabled") == "true")
  549.         tagList.element.setAttribute("disabled", "false");
  550.     }
  551.  
  552.     aInput.lastTextValue = value;
  553.     aInput.lastCursorPosition = aInput.selectionStart;
  554.   },
  555.  
  556.   handleTextInput: function(aInput) {
  557.     if (!aInput.tagsList)
  558.       return;
  559.  
  560.     var value = aInput.value;
  561.     var selStart = aInput.selectionStart, selEnd = aInput.selectionEnd;
  562.  
  563.     if (selEnd !== value.length)
  564.       return;
  565.  
  566.     var textBefore = value.substr(0, selStart);
  567.     textBefore = textBefore.substr(textBefore.lastIndexOf(",") + 1).replace(/^( *)/, "");
  568.  
  569.     if (textBefore == "")
  570.       return;
  571.  
  572.     var re = new RegExp("^" + textBefore);
  573.  
  574.     for each (var tag in aInput.tagsList) {
  575.       var tagValue = tag.value;
  576.       if (re.test(tagValue) && !(new RegExp("(^|,) *" + tagValue + " *($|,)","i").test(value))) {
  577.         var textComplete = tagValue.substr(textBefore.length);
  578.         var resultValue = value.substr(0, selEnd) + textComplete;
  579.  
  580.         if (aInput.trySetNewValue(resultValue)) {
  581.           aInput.selectTextRange(selStart, resultValue.length);
  582.           aInput.lastTextComplete = textComplete;
  583.           return;
  584.         }
  585.       }
  586.     }
  587.   },
  588.  
  589.   refreshYaRuUserData: function(aCallback) {
  590.     gYaSearchService.xmlHttpRequest("http://zakladki.yandex.ru/bar/getcommunities.xml?" + getNCRndStr(),
  591.                              { callbackFunc: this.refreshYaRuUserDataCallback.bind(this, aCallback) });
  592.   },
  593.  
  594.   refreshYaRuUserDataCallback: function(aReq, aCallback) {
  595.     var res;
  596.  
  597.     if (gYaSearchService.isReqError(aReq)) {
  598.       res = "lost_connection";
  599.     } else if (!gYaSearchService.isLogin) {
  600.       res = "auth_required";
  601.     } else {
  602.       var yaruResponse = this.getServerResponse(aReq.target.responseText);
  603.       if (yaruResponse.error) {
  604.         res = yaruResponse.error;
  605.       } else {
  606.         if (yaruResponse.xml && yaruResponse.xml.communities) {
  607.           var communities = yaruResponse.xml.communities.community;
  608.           var communitiesArray = [];
  609.  
  610.           for (var i=0, len = communities.length(); i < len; i++) {
  611.             var label = communities[i].title.toString();
  612.             var value = communities[i].feed_id.toString();
  613.  
  614.             if (label && value)
  615.               communitiesArray.push(communities[i]);
  616.           }
  617.  
  618.           communitiesArray.sort(function(a,b) {
  619.             var labelA = a.title.toString(), labelB = b.title.toString();
  620.             var labelALower = labelA.toLowerCase(), labelBLower = labelB.toLowerCase();
  621.  
  622.             return (labelALower < labelBLower) ? -1 : (labelALower > labelBLower) ? 1 :
  623.                                       ((labelA < labelB) ? -1 : (labelA > labelB) ? 1 : 0);
  624.           });
  625.  
  626.           var _communities = new XML('<communities/>');
  627.           for each (var community in communitiesArray)
  628.             _communities.community += community;
  629.  
  630.           yaruResponse.xml.communities = _communities;
  631.         }
  632.  
  633.         res = yaruResponse.xml;
  634.       }
  635.     }
  636.  
  637.     if (aCallback)
  638.       aCallback(res);
  639.   },
  640.  
  641.   refreshYaRuUserFriendsData: function(aCallback) {
  642.     gYaSearchService.xmlHttpRequest("http://zakladki.yandex.ru/bar/getfriendlast.xml?" + getNCRndStr(),
  643.                              { callbackFunc: this.refreshYaRuUserFriendsDataCallback.bind(this, aCallback) });
  644.   },
  645.  
  646.   refreshYaRuUserFriendsDataCallback: function(aReq, aCallback) {
  647.     var res;
  648.  
  649.     if (gYaSearchService.isReqError(aReq)) {
  650.       res = "lost_connection";
  651.     } else if (!gYaSearchService.isLogin) {
  652.       res = "auth_required";
  653.     } else {
  654.       var yaruResponse = this.getServerResponse(aReq.target.responseText);
  655.       if (yaruResponse.error) {
  656.         res = yaruResponse.error;
  657.       } else {
  658.         res = yaruResponse.xml;
  659.       }
  660.     }
  661.  
  662.     if (typeof res !== "xml") {
  663.       var errorXml = <yaru/>;
  664.       errorXml.@yasearch_error = res;
  665.       res = errorXml;
  666.     }
  667.  
  668.     res.@yasearch_login = gYaSearchService.username;
  669.     res = gYaSearchService.getDOMDocContent2("bookmarks/xsl-yaru-friends-links.xsl",
  670.                                              gYaSearchService.domParser.parseFromString(res.toSource(), "text/xml"));
  671.  
  672.     if (aCallback)
  673.       aCallback(res);
  674.   },
  675.  
  676.   yaruPrefs: {
  677.     MAX_ADD_HELP_SHOWED: 9,
  678.  
  679.     prefBranchName: "yasearch.general.ui.bookmarks.prefs.",
  680.  
  681.     onHelpShowed: function(aHidePermanently) {
  682.       this.set("yaruAddHelpShowed",
  683.                 aHidePermanently || (gYaSearchService.getIntPref(this.prefBranchName + "yaruAddHelpShowed") + 1));
  684.     },
  685.  
  686.     get: function(aPrefName) {
  687.       var fullPrefName = this.prefBranchName + aPrefName;
  688.  
  689.       var res = null;
  690.  
  691.       switch (aPrefName) {
  692.         case "yaruBlockExpanded":
  693.         case "yaruLiveWindowDisabled":
  694.         case "yaruExportChecked":
  695.           res = gYaSearchService.getBoolPref(fullPrefName);
  696.           break;
  697.  
  698.         case "yaruPublicVal":
  699.           res = gYaSearchService.getIntPref(fullPrefName);
  700.           break;
  701.  
  702.         case "yaruAddHelpShowed":
  703.           res = gYaSearchService.getIntPref(fullPrefName) >= this.MAX_ADD_HELP_SHOWED;
  704.           break;
  705.  
  706.         default:
  707.           return null;
  708.       }
  709.  
  710.       return res;
  711.     },
  712.  
  713.     set: function(aPrefName, aPrefValue) {
  714.       var fullPrefName = this.prefBranchName + aPrefName;
  715.  
  716.       var res = null;
  717.  
  718.       switch (aPrefName) {
  719.         case "yaruBlockExpanded":
  720.         case "yaruLiveWindowDisabled":
  721.         case "yaruExportChecked":
  722.           res = gYaSearchService.setBoolPref(fullPrefName, aPrefValue);
  723.           break;
  724.  
  725.         case "yaruPublicVal":
  726.           res = gYaSearchService.setIntPref(fullPrefName, aPrefValue);
  727.           break;
  728.  
  729.         case "yaruAddHelpShowed":
  730.           if ("number" !== typeof aPrefValue)
  731.             aPrefValue = aPrefValue ? this.MAX_ADD_HELP_SHOWED : 0;
  732.  
  733.           res = gYaSearchService.setIntPref(fullPrefName, Math.min(this.MAX_ADD_HELP_SHOWED, aPrefValue));
  734.           break;
  735.  
  736.         default:
  737.           return null;
  738.       }
  739.  
  740.       return res;
  741.     }
  742.   },
  743.  
  744.   _lastUsedFolderPrefName: "yasearch.general.ui.bookmarks.lastfolder",
  745.  
  746.   get lastUsedFolder() {
  747.     var [lastFolderId, lastFolderTimestamp] =
  748.         gYaSearchService.getCharPref(this._lastUsedFolderPrefName).split(";");
  749.  
  750.     lastFolderId = gYaSearchService.parseIntFromStr(lastFolderId);
  751.     lastFolderTimestamp = gYaSearchService.parseIntFromStr(lastFolderTimestamp);
  752.     
  753.     return (lastFolderId && (Date.now() - lastFolderTimestamp) < (DAY_SECS / 24)) ? // 1 hour
  754.             Math.max(0, lastFolderId) : 0;
  755.   },
  756.  
  757.   set lastUsedFolder(val) {
  758.     gYaSearchService.setCharPref(this._lastUsedFolderPrefName,
  759.         [Math.max(0, gYaSearchService.parseIntFromStr(val)), Date.now()].join(";"));
  760.  
  761.     return this.lastUsedFolder;
  762.   }
  763. }
  764.  
  765. gYaBookmarks._init();