home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2005 August / PCpro_2005_08.ISO / files / firefox / ScrapBook.xpi / chrome / scrapbook.jar / content / scrapcapture.js < prev    next >
Encoding:
JavaScript  |  2005-06-04  |  23.0 KB  |  765 lines

  1. /**************************************************
  2. // scrapcapture.js
  3. // Implementation file for overlay.xul, capture.xul
  4. // 
  5. // Description: 
  6. // Author: Gomita
  7. // Contributors: 
  8. // 
  9. // Version: 
  10. // License: see LICENSE.txt
  11. **************************************************/
  12.  
  13.  
  14.  
  15. var SBcapture = {
  16.  
  17.  
  18.     item         : null,
  19.     contentDir   : null,
  20.     httpTask     : {},
  21.     file2URL     : {},
  22.     linked       : {},
  23.     refURLObj    : null,
  24.     favicon      : null,
  25.     frameList    : null,
  26.     frameNumber  : 0,
  27.     selection    : null,
  28.     linkURLs     : [],
  29.  
  30.  
  31.     getFrameList : function(aWindow)
  32.     {
  33.         for ( var f=0; f<aWindow.frames.length; f++ )
  34.         {
  35.             this.frameList.push(aWindow.frames[f]);
  36.             this.getFrameList(aWindow.frames[f]);
  37.         }
  38.     },
  39.  
  40.     init : function()
  41.     {
  42.         this.favicon = null;
  43.         this.httpTask[this.item.id] = 0;
  44.         this.file2URL = { 'index.html' : true, 'index.css' : true, 'index.dat' : true };
  45.         this.linked   = { img : false, snd : false, mov : false, arc : false, all : false, seq : false };
  46.         this.linkURLs = [];
  47.         this.frameList   = [];
  48.         this.frameNumber = 0;
  49.     },
  50.  
  51.     doCaptureDocument : function(ROOT_WINDOW, SELECTION_ONLY, DETAIL_DIALOG, RESOURCE_NAME, RESOURCE_INDEX)
  52.     {
  53.         SBRDF.init();
  54.  
  55.         this.item = new ScrapBookItem(SBRDF.identify(SBcommon.getTimeStamp()));
  56.         this.item.chars  = ROOT_WINDOW.document.characterSet;
  57.         this.item.source = ROOT_WINDOW.location.href;
  58.         this.init();
  59.         try {
  60.             this.item.icon = document.getElementById("content").selectedTab.getAttribute("image");
  61.         } catch(ex) {
  62.         }
  63.  
  64.         this.getFrameList(ROOT_WINDOW);
  65.  
  66.         var titleList = ROOT_WINDOW.document.title ? [ROOT_WINDOW.document.title] : [this.item.source];
  67.         if ( SELECTION_ONLY )
  68.         {
  69.             this.selection = ROOT_WINDOW.getSelection();
  70.             var lines = this.selection.toString().split("\n");
  71.             for ( var i = 0; i < lines.length; i++ )
  72.             {
  73.                 lines[i] = lines[i].replace(/\r|\n|\t/g, "");
  74.                 if ( lines[i].length > 0 ) titleList.push(lines[i].substring(0,72));
  75.                 if ( titleList.length > 4 ) break;
  76.             }
  77.             this.item.title = ( titleList.length > 0 ) ? titleList[1] : titleList[0];
  78.         }
  79.         else
  80.         {
  81.             this.selection = null;
  82.             this.item.title = titleList[0];
  83.         }
  84.  
  85.         if ( DETAIL_DIALOG )
  86.         {
  87.             var ret = this.showDetailDialog(titleList, RESOURCE_NAME);
  88.             if ( ret.change ) { RESOURCE_NAME = ret.resName; RESOURCE_INDEX = 0; }
  89.             if ( ret.cancel ) { return; }
  90.         }
  91.  
  92.         this.contentDir = SBcommon.getContentDir(this.item.id);
  93.  
  94.         this.saveDocument(ROOT_WINDOW.document, "index");
  95.  
  96.         if ( this.item.icon && this.item.type != "image" && this.item.type != "file" )
  97.         {
  98.             var iconFileName = this.download(this.item.icon);
  99.             this.favicon = iconFileName;
  100.         }
  101.  
  102.         if ( this.httpTask[this.item.id] == 0 ) this.notifyOnComplete(this.item.id, this.item.icon, this.item.title);
  103.  
  104.         this.addResource(RESOURCE_NAME, RESOURCE_INDEX);
  105.  
  106.         if ( this.linked.seq && this.linkURLs.length > 0 )
  107.         {
  108.             var newID = SBRDF.identify(SBcommon.getTimeStamp());
  109.             var newItem = new ScrapBookItem(newID);
  110.             newItem.title = this.item.title;
  111.             newItem.type = "folder";
  112.             var newRes = SBRDF.addItem(newItem, RESOURCE_NAME, RESOURCE_INDEX > 0 ? RESOURCE_INDEX + 1 : RESOURCE_INDEX);
  113.             SBRDF.createEmptySeq(newRes.Value);
  114.             try {
  115.                 (window.opener ? window.opener : window).top.document.getElementById("sidebar").contentWindow.SB_rebuildAllTree();
  116.             } catch(ex) {
  117.             }
  118.             window.openDialog(
  119.                 "chrome://scrapbook/content/capture.xul", "", "chrome,centerscreen,all,dialog=no",
  120.                 this.linkURLs, this.refURLObj.spec, false, true, newRes.Value, 0
  121.             );
  122.         }
  123.  
  124.         return true;
  125.     },
  126.  
  127.  
  128.     doCaptureLinkedDocument : function(ROOT_WINDOW, FILE_KEY)
  129.     {
  130.         this.item.chars = ROOT_WINDOW.document.characterSet;
  131.         this.init();
  132.         this.getFrameList(ROOT_WINDOW);
  133.         this.saveDocument(ROOT_WINDOW.document, FILE_KEY);
  134.         return true;
  135.     },
  136.  
  137.  
  138.     doCaptureFile : function(TARGET_URL, CAPTURE_TYPE, REFER_URL, DETAIL_DIALOG, RESOURCE_NAME, RESOURCE_INDEX)
  139.     {
  140.         SBRDF.init();
  141.  
  142.         this.item = new ScrapBookItem(SBRDF.identify(SBcommon.getTimeStamp()));
  143.         this.item.title  = SBcommon.getFileName(TARGET_URL);
  144.         this.item.icon   = "moz-icon://" + this.item.title + "?size=16";
  145.         this.item.source = TARGET_URL;
  146.         this.item.type   = CAPTURE_TYPE;
  147.         this.init();
  148.         if ( DETAIL_DIALOG )
  149.         {
  150.             var ret = this.showDetailDialog([this.item.title], RESOURCE_NAME);
  151.             if ( ret.change ) { RESOURCE_NAME = ret.resName; RESOURCE_INDEX = 0; }
  152.             if ( ret.cancel ) { return; }
  153.         }
  154.         this.contentDir = SBcommon.getContentDir(this.item.id);
  155.         this.refURLObj  = SBcommon.convertURLToObject(REFER_URL);
  156.         this.saveFile(TARGET_URL, "index", CAPTURE_TYPE);
  157.         this.addResource(RESOURCE_NAME, RESOURCE_INDEX);
  158.         return true;
  159.     },
  160.  
  161.  
  162.     showDetailDialog : function(aTitleList, aResName)
  163.     {
  164.         var ret = {
  165.             titleList : aTitleList,
  166.             resName   : aResName,
  167.             cancel    : false,
  168.             change    : false
  169.         };
  170.         window.openDialog('chrome://scrapbook/content/detail.xul' + (window.opener ? "?capture" : ""), "", "chrome,modal,centerscreen,resizable", ret);
  171.         return ret;
  172.     },
  173.  
  174.  
  175.     saveDocument : function(aDocument, aFileKey)
  176.     {
  177.         if ( !aDocument.body || !aDocument.contentType.match(/text|html|xml/i) )
  178.         {
  179.             var captureType = (aDocument.contentType.substring(0,5) == "image") ? "image" : "file";
  180.             if ( this.frameNumber == 0 ) this.item.type = captureType;
  181.             var newLeafName = this.saveFile(aDocument.location.href, aFileKey, captureType);
  182.             return newLeafName;
  183.         }
  184.  
  185.         this.refURLObj = SBcommon.convertURLToObject(aDocument.location.href);
  186.  
  187.         dump("ScrapBook::saveDocument\t" + this.item.id + " [" + this.frameNumber + "] " + aFileKey + " " + aDocument.location.href + "\n");
  188.  
  189.         if ( this.selection )
  190.         {
  191.             var myRange = this.selection.getRangeAt(0);
  192.             var myDocFrag = myRange.cloneContents();
  193.             var curNode = myRange.commonAncestorContainer;
  194.             if ( curNode.nodeName == "#text" ) curNode = curNode.parentNode;
  195.         }
  196.  
  197.         var tmpNodeList = [];
  198.         if ( this.selection )
  199.         {
  200.             do {
  201.                 tmpNodeList.unshift(curNode.cloneNode(false));
  202.                 curNode = curNode.parentNode;
  203.             }
  204.             while ( curNode.nodeName.toUpperCase() != "HTML" );
  205.         }
  206.         else
  207.         {
  208.             tmpNodeList.unshift(aDocument.body.cloneNode(true));
  209.         }
  210.  
  211.         var rootNode = aDocument.getElementsByTagName("html")[0].cloneNode(false);
  212.  
  213.         try {
  214.             var headNode = aDocument.getElementsByTagName("head")[0].cloneNode(true);
  215.             rootNode.appendChild(headNode);
  216.             rootNode.appendChild(document.createTextNode("\n"));
  217.         } catch(ex) {
  218.         }
  219.  
  220.         rootNode.appendChild(tmpNodeList[0]);
  221.         rootNode.appendChild(document.createTextNode("\n"));
  222.         for ( var n = 0; n < tmpNodeList.length-1; n++ )
  223.         {
  224.             tmpNodeList[n].appendChild(document.createTextNode("\n"));
  225.             tmpNodeList[n].appendChild(tmpNodeList[n+1]);
  226.             tmpNodeList[n].appendChild(document.createTextNode("\n"));
  227.         }
  228.  
  229.         if ( this.selection )
  230.         {
  231.             this.addCommentTag(tmpNodeList[tmpNodeList.length-1], "DOCUMENT_FRAGMENT");
  232.             tmpNodeList[tmpNodeList.length-1].appendChild(myDocFrag);
  233.             this.addCommentTag(tmpNodeList[tmpNodeList.length-1], "/DOCUMENT_FRAGMENT");
  234.         }
  235.  
  236.  
  237.         this.processDOMRecursively(rootNode);
  238.  
  239.  
  240.         var myCSS = "";
  241.         var myStyleSheets = aDocument.styleSheets;
  242.         for ( var i=0; i<myStyleSheets.length; i++ )
  243.         {
  244.             myCSS += this.processCSSRecursively(myStyleSheets[i]);
  245.         }
  246.  
  247.         if ( myCSS )
  248.         {
  249.             var newLinkNode = document.createElement("link");
  250.             newLinkNode.setAttribute("media", "all");
  251.             newLinkNode.setAttribute("href", aFileKey + ".css");
  252.             newLinkNode.setAttribute("type", "text/css");
  253.             newLinkNode.setAttribute("rel", "stylesheet");
  254.             rootNode.firstChild.appendChild(document.createTextNode("\n"));
  255.             rootNode.firstChild.appendChild(newLinkNode);
  256.             rootNode.firstChild.appendChild(document.createTextNode("\n"));
  257.         }
  258.  
  259.  
  260.         if ( SBcommon.getBoolPref("scrapbook.capture.utf8encode", true) )
  261.         {
  262.             this.item.chars = "UTF-8";
  263.             var newMetaNode = document.createElement("meta");
  264.             newMetaNode.setAttribute("content", aDocument.contentType + "; charset=" + this.item.chars);
  265.             newMetaNode.setAttribute("http-equiv", "Content-Type");
  266.             rootNode.firstChild.insertBefore(newMetaNode, rootNode.firstChild.firstChild);
  267.             rootNode.firstChild.insertBefore(document.createTextNode("\n"), rootNode.firstChild.firstChild);
  268.         }
  269.  
  270.  
  271.         var myHTML;
  272.         myHTML = this.surroundByTags(rootNode, rootNode.innerHTML);
  273.         myHTML = this.doctypeToString(aDocument.doctype) + myHTML;
  274.         myHTML = myHTML.replace(/\x00/g, " ");
  275.  
  276.         var myHTMLFile = this.contentDir.clone();
  277.         myHTMLFile.append(aFileKey + ".html");
  278.         SBcommon.writeFile(myHTMLFile, myHTML, this.item.chars);
  279.  
  280.         if ( myCSS )
  281.         {
  282.             var myCSSFile = this.contentDir.clone();
  283.             myCSSFile.append(aFileKey + ".css");
  284.             SBcommon.writeFile(myCSSFile, myCSS, this.item.chars);
  285.         }
  286.  
  287.         return myHTMLFile.leafName;
  288.     },
  289.  
  290.  
  291.     saveFile : function(aFileURL, aFileKey, aCaptureType)
  292.     {
  293.         if ( !aFileKey ) aFileKey = "file" + Math.random().toString();
  294.  
  295.         if ( !this.refURLObj ) this.refURLObj = SBcommon.convertURLToObject(aFileURL);
  296.  
  297.         dump("ScrapBook::saveFile\t" + this.item.id + " [" + this.frameNumber + "] " + aFileKey + " (" + aCaptureType + ") " + aFileURL + "\n");
  298.  
  299.         if ( this.frameNumber == 0 )
  300.         {
  301.             this.item.icon  = "moz-icon://" + SBcommon.getFileName(aFileURL) + "?size=16";
  302.             this.item.type  = aCaptureType;
  303.             this.item.chars = "";
  304.         }
  305.  
  306.         var newFileName = this.download(aFileURL);
  307.  
  308.         if ( aCaptureType == "image" ) {
  309.             var myHTML = '<html><body><img src="' + newFileName + '"></body></html>';
  310.         } else {
  311.             var myHTML = '<html><head><meta http-equiv="refresh" content="0;URL=./' + newFileName + '"></head><body></body></html>';
  312.         }
  313.         var myHTMLFile = this.contentDir.clone();
  314.         myHTMLFile.append(aFileKey + ".html");
  315.         SBcommon.writeFile(myHTMLFile, myHTML, "UTF-8");
  316.  
  317.         return myHTMLFile.leafName;
  318.     },
  319.  
  320.  
  321.     addResource : function(aResName, aResIndex)
  322.     {
  323.         var myRes = SBRDF.addItem(this.item, aResName, aResIndex);
  324.         try {
  325.             (window.opener ? window.opener : window).top.document.getElementById("sidebar").contentWindow.SB_rebuildAllTree();
  326.         } catch(ex) {
  327.         }
  328.         if ( this.favicon )
  329.         {
  330.             var faviconURL = SBservice.IO.newFileURI(this.contentDir).spec + this.favicon;
  331.             (window.opener ? window.opener : window).setTimeout(function() { SBRDF.updateItem(myRes, "icon", faviconURL); SBRDF.flush(); }, 500);
  332.             this.item.icon = this.favicon;
  333.         }
  334.         SBcommon.writeIndexDat(this.item);
  335.     },
  336.  
  337.  
  338.  
  339.     surroundByTags : function(aNode, aContent)
  340.     {
  341.         var tag = "<" + aNode.nodeName.toLowerCase();
  342.         for ( var i=0; i<aNode.attributes.length; i++ )
  343.         {
  344.             tag += ' ' + aNode.attributes[i].name + '="' + aNode.attributes[i].value + '"';
  345.         }
  346.         tag += ">\n";
  347.         return tag + aContent + "</" + aNode.nodeName.toLowerCase() + ">\n";
  348.     },
  349.  
  350.  
  351.     addCommentTag : function(targetNode, aComment)
  352.     {
  353.         targetNode.appendChild(document.createTextNode("\n"));
  354.         targetNode.appendChild(document.createComment(aComment));
  355.         targetNode.appendChild(document.createTextNode("\n"));
  356.     },
  357.  
  358.  
  359.     removeNodeFromParent : function(aNode)
  360.     {
  361.         var newNode = document.createTextNode("");
  362.         aNode.parentNode.replaceChild(newNode, aNode);
  363.         aNode = newNode;
  364.         return aNode;
  365.     },
  366.  
  367.  
  368.     doctypeToString : function(aDoctype)
  369.     {
  370.         if ( !aDoctype ) return "";
  371.         var ret = "<!DOCTYPE " + aDoctype.name;
  372.         if ( aDoctype.publicId ) ret += ' PUBLIC "' + aDoctype.publicId + '"';
  373.         if ( aDoctype.systemId ) ret += ' "'        + aDoctype.systemId + '"';
  374.         ret += ">\n";
  375.         return ret;
  376.     },
  377.  
  378.  
  379.  
  380.     processDOMRecursively : function(rootNode)
  381.     {
  382.         for ( var curNode = rootNode.firstChild; curNode != null; curNode = curNode.nextSibling )
  383.         {
  384.             if ( curNode.nodeName == "#text" || curNode.nodeName == "#comment" ) continue;
  385.             curNode = this.inspectNode(curNode);
  386.             this.processDOMRecursively(curNode);
  387.         }
  388.     },
  389.  
  390.  
  391.     inspectNode : function(aNode)
  392.     {
  393.         switch ( aNode.nodeName.toLowerCase() )
  394.         {
  395.             case "img" : 
  396.             case "embed" : 
  397.                 if ( aNode.hasAttribute("onclick") ) aNode = this.convertJavaScriptLink(aNode, "onclick");
  398.                 var aFileName = this.download(aNode.src);
  399.                 if (aFileName) aNode.setAttribute("src", aFileName);
  400.                 break;
  401.  
  402.             case "object" : 
  403.                 var aFileName = this.download(aNode.data);
  404.                 if (aFileName) aNode.setAttribute("data", aFileName);
  405.                 break;
  406.  
  407.             case "body" : 
  408.             case "table" : 
  409.             case "td" : 
  410.                 var aFileName = this.download(aNode.getAttribute("background"));
  411.                 if (aFileName) aNode.setAttribute("background", aFileName);
  412.                 break;
  413.  
  414.             case "input" : 
  415.                 if ( aNode.type.toLowerCase() == "image" ) {
  416.                     var aFileName = this.download(aNode.src);
  417.                     if (aFileName) aNode.setAttribute("src", aFileName);
  418.                 }
  419.                 break;
  420.  
  421.             case "link" : 
  422.                 if ( aNode.rel.toLowerCase() == "stylesheet" ) {
  423.                     aNode = this.removeNodeFromParent(aNode);
  424.                     return aNode;
  425.                 } else if ( aNode.rel.toLowerCase() == "shortcut icon" || aNode.rel.toLowerCase() == "icon" ) {
  426.                     var aFileName = this.download(aNode.href);
  427.                     if (aFileName) aNode.setAttribute("href", aFileName);
  428.                     if ( this.frameNumber == 0 && !this.favicon ) this.favicon = aFileName;
  429.                 } else {
  430.                     aNode.setAttribute("href", aNode.href);
  431.                 }
  432.                 break;
  433.  
  434.             case "base" : 
  435.             case "style" : 
  436.                 aNode = this.removeNodeFromParent(aNode);
  437.                 return aNode;
  438.                 break;
  439.  
  440.             case "script" : 
  441.             case "noscript" : 
  442.                 if ( SBcommon.getBoolPref("scrapbook.capture.removescript", true) )
  443.                 {
  444.                     aNode = this.removeNodeFromParent(aNode);
  445.                     return aNode;
  446.                 }
  447.                 else
  448.                 {
  449.                     if ( aNode.hasAttribute("src") ) {
  450.                         var aFileName = this.download(aNode.src);
  451.                         if (aFileName) aNode.setAttribute("src", aFileName);
  452.                     }
  453.                 }
  454.                 break;
  455.  
  456.             case "a" : 
  457.             case "area" : 
  458.                 if ( aNode.hasAttribute("onclick") ) aNode = this.convertJavaScriptLink(aNode, "onclick");
  459.                 if ( !aNode.hasAttribute("href") ) return aNode;
  460.                 if ( aNode.href.match(/^javascript:/i) ) aNode = this.convertJavaScriptLink(aNode, "href");
  461.                 if ( !this.selection && aNode.getAttribute("href").charAt(0) == "#" ) return aNode;
  462.                 var ext = SBcommon.splitFileName(SBcommon.getFileName(aNode.href))[1];
  463.                 var flag = false;
  464.                 switch ( ext.toLowerCase() )
  465.                 {
  466.                     case "jpg" : case "jpeg" : case "png" : case "gif" : flag = this.linked.img; break;
  467.                     case "mp3" : case "wav"  : case "ram" : case "wma" : flag = this.linked.snd; break;
  468.                     case "mpg" : case "mpeg" : case "avi" : 
  469.                     case "ram" : case "rm"   : case "mov" : case "wmv" : flag = this.linked.mov; break;
  470.                     case "zip" : case "lzh"  : case "rar" :    case "xpi" : flag = this.linked.arc; break;
  471.                     default :
  472.                         if ( ext && this.linked.custom )
  473.                         {
  474.                             if ( (", " + this.linked.custom + ", ").indexOf(", " + ext + ", ") != -1 ) flag = true;
  475.                         }
  476.                         if ( !flag && this.linked.seq ) this.linkURLs.push(aNode.href);
  477.                 }
  478.                 if ( flag ) {
  479.                     var aFileName = this.download(aNode.href);
  480.                     if (aFileName) aNode.setAttribute("href", aFileName);
  481.                 } else {
  482.                     aNode.setAttribute("href", aNode.href);
  483.                 }
  484.                 break;
  485.  
  486.             case "form" : 
  487.                 aNode.setAttribute("action", SBcommon.resolveURL(this.refURLObj.spec, aNode.action));
  488.                 break;
  489.  
  490.             case "meta" : 
  491.                 if ( SBcommon.getBoolPref("scrapbook.capture.utf8encode", true) )
  492.                 {
  493.                     if ( aNode.hasAttribute("http-equiv") && aNode.hasAttribute("content") &&
  494.                          aNode.getAttribute("http-equiv").toLowerCase() == "content-type" && 
  495.                          aNode.getAttribute("content").match(/charset\=/i) )
  496.                     {
  497.                         aNode = this.removeNodeFromParent(aNode);
  498.                         return aNode;
  499.                     }
  500.                 }
  501.                 break;
  502.  
  503.             case "frame"  : 
  504.             case "iframe" : 
  505.                 if ( this.selection ) {
  506.                     aNode.setAttribute("src", aNode.src);
  507.                     break;
  508.                 }
  509.                 try {
  510.                     var newFileName = this.saveDocument(this.frameList[this.frameNumber++].document, "index" + this.frameNumber);
  511.                     aNode.setAttribute("src", newFileName);
  512.                 } catch(ex) {
  513.                     alert("ScrapBook ERROR: Failed to get document in a frame.");
  514.                 }
  515.                 break;
  516.  
  517.         }
  518.  
  519.         var newCSStext = this.inspectCSSText(aNode.style.cssText, this.refURLObj.spec);
  520.         if ( newCSStext ) aNode.setAttribute("style", newCSStext);
  521.  
  522.         if ( SBcommon.getBoolPref("scrapbook.capture.removescript", true) )
  523.         {
  524.             aNode.removeAttribute("onmouseover");
  525.             aNode.removeAttribute("onmouseout");
  526.             aNode.removeAttribute("onload");
  527.         }
  528.  
  529.         return aNode;
  530.     },
  531.  
  532.  
  533.     processCSSRecursively : function(aCSS)
  534.     {
  535.         var content = "";
  536.  
  537.         if ( aCSS.disabled ) return "";
  538.         var medium = aCSS.media.mediaText;
  539.         if ( !medium.match("screen|all", "i") && medium != "" )
  540.         {
  541.             return "";
  542.         }
  543.  
  544.         var flag = false;
  545.         for ( var i=0; i<aCSS.cssRules.length; i++ )
  546.         {
  547.             if ( aCSS.cssRules[i].type == 1 || aCSS.cssRules[i].type == 4 )
  548.             {
  549.                 if ( !flag ) { content += "\n/* ::::: " + aCSS.href + " ::::: */\n\n"; flag = true; }
  550.                 content += this.inspectCSSText(aCSS.cssRules[i].cssText, aCSS.href) + "\n";
  551.             }
  552.             else if ( aCSS.cssRules[i].type == 3 )
  553.             {
  554.                 content += this.processCSSRecursively(aCSS.cssRules[i].styleSheet);
  555.             }
  556.         }
  557.         return content;
  558.     },
  559.  
  560.  
  561.     inspectCSSText : function(aCSStext, aCSShref)
  562.     {
  563.         if ( !aCSStext ) return;
  564.         var RE = new RegExp(/ url\(([^\'\)]+)\)/);
  565.         var i = 0;
  566.         while ( aCSStext.match(RE) )
  567.         {
  568.             if ( ++i > 10 ) break;
  569.             var imgURL  = SBcommon.resolveURL(aCSShref, RegExp.$1);
  570.             var imgFile = this.download(imgURL);
  571.             aCSStext = aCSStext.replace(RE, " url('" + imgFile + "')");
  572.         }
  573.         aCSStext = aCSStext.replace(/([^\{\}])(\r|\n)/g, "$1\\A");
  574.         RE = new RegExp(/ content: [\"\'](.*?)[\"\']; /);
  575.         if ( aCSStext.match(RE) )
  576.         {
  577.             var innerQuote = RegExp.$1;
  578.             innerQuote = innerQuote.replace(/\"/g, '\\"');
  579.             innerQuote = innerQuote.replace(/\\[\"\'] attr\(([^\)]+)\) \\[\"\']/g, '" attr($1) "');
  580.             aCSStext = aCSStext.replace(RE, ' content: "' + innerQuote + '"; ');
  581.         }
  582.         aCSStext = aCSStext.replace(/ quotes: [^;]+; /g, " ");
  583.         if ( aCSStext.match(/ background: /i) )
  584.         {
  585.             aCSStext = aCSStext.replace(/ -moz-background-[^:]+: initial;/g, "");
  586.             aCSStext = aCSStext.replace(/ scroll 0%/, "");
  587.             aCSStext = aCSStext.replace(/ no-repeat scroll 0px;/g, " no-repeat 0px 0px;");
  588.         }
  589.         return aCSStext;
  590.     },
  591.  
  592.  
  593.     download : function(aURLSpec)
  594.     {
  595.         if ( !aURLSpec ) return;
  596.  
  597.         aURLSpec = SBcommon.resolveURL(this.refURLObj.spec, aURLSpec);
  598.  
  599.         try {
  600.             var aURL = Components.classes['@mozilla.org/network/standard-url;1'].createInstance(Components.interfaces.nsIURL);
  601.             aURL.spec = aURLSpec;
  602.         } catch(ex) {
  603.             alert("ScrapBook ERROR: Failed to download: " + aURLSpec);
  604.             return;
  605.         }
  606.         var newFileName = aURL.fileName;
  607.  
  608.         if ( !newFileName ) newFileName = "untitled";
  609.         newFileName = SBcommon.validateFileName(newFileName);
  610.  
  611.         if ( this.file2URL[newFileName] == undefined )
  612.         {
  613.         }
  614.         else if ( this.file2URL[newFileName] != aURLSpec )
  615.         {
  616.             var seq = 1;
  617.             var fileLR = SBcommon.splitFileName(newFileName);
  618.             if ( !fileLR[1] ) fileLR[1] = "dat";
  619.             while ( this.file2URL[ fileLR[0] + "_" + SBcommon.leftZeroPad3(seq) + "." + fileLR[1] ] != undefined ) { seq++; }
  620.             newFileName = fileLR[0] + "_" + SBcommon.leftZeroPad3(seq) + "." + fileLR[1];
  621.         }
  622.         else
  623.         {
  624.             return newFileName;
  625.         }
  626.  
  627.         if ( aURL.schemeIs("http") || aURL.schemeIs("https") || aURL.schemeIs("ftp") )
  628.         {
  629.             var targetFile = this.contentDir.clone();
  630.             targetFile.append(newFileName);
  631.             try {
  632.                 var WBP = Components.classes['@mozilla.org/embedding/browser/nsWebBrowserPersist;1'].createInstance(Components.interfaces.nsIWebBrowserPersist);
  633.                 WBP.persistFlags |= WBP.PERSIST_FLAGS_FROM_CACHE;
  634.                 WBP.saveURI(aURL, null, this.refURLObj, null, null, targetFile);
  635.                 this.httpTask[this.item.id]++;
  636.                 WBP.progressListener = new SBdownloadListener(this.item, newFileName);
  637.                 this.file2URL[newFileName] = aURLSpec;
  638.                 return newFileName;
  639.             }
  640.             catch(ex) {
  641.                 dump("*** SCRAPBOOK_PERSIST_FAILURE: " + aURLSpec + "\n" + ex + "\n");
  642.                 this.httpTask[this.item.id]--;
  643.                 return "";
  644.             }
  645.         }
  646.         else if ( aURL.schemeIs("file") )
  647.         {
  648.             var targetDir = this.contentDir.clone();
  649.             try {
  650.                 var orgFile = SBcommon.convertURLToFile(aURLSpec);
  651.                 if ( !orgFile.isFile() ) return;
  652.                 orgFile.copyTo(targetDir, newFileName);
  653.                 this.file2URL[newFileName] = aURLSpec;
  654.                 return newFileName;
  655.             }
  656.             catch(ex) {
  657.                 dump("*** SCRAPBOOK_COPY_FAILURE: " + aURLSpec + "\n" + ex + "\n");
  658.                 return "";
  659.             }
  660.         }
  661.     },
  662.  
  663.  
  664.     convertJavaScriptLink : function(aNode, aAttr)
  665.     {
  666.         var val = aNode.getAttribute(aAttr);
  667.         if ( !val.match(/\(\'([^\']+)\'/) ) return aNode;
  668.         val = RegExp.$1;
  669.         if ( val.indexOf("/") == -1 && val.indexOf(".") == -1 ) return aNode;
  670.         val = SBcommon.resolveURL(this.refURLObj.spec, val);
  671.         if ( aNode.nodeName.toLowerCase() == "img" )
  672.         {
  673.             if ( aNode.parentNode.nodeName.toLowerCase() == "a" ) {
  674.                 aNode.parentNode.setAttribute("href", val);
  675.                 aNode.removeAttribute("onclick");
  676.             } else {
  677.                 val = "window.open('" + val + "');";
  678.                 aNode.setAttribute(aAttr, val);
  679.             }
  680.         }
  681.         else
  682.         {
  683.             aNode.setAttribute("href", val);
  684.             aNode.removeAttribute("onclick");
  685.         }
  686.         return aNode;
  687.     },
  688.  
  689.  
  690.     notifyOnComplete : function(aID, aIcon, aTitle)
  691.     {
  692.         if ( SBcommon.getBoolPref("scrapbook.capture.notify", false) )
  693.         {
  694.             window.openDialog(
  695.                 "chrome://scrapbook/content/notify.xul", "", "alwaysRaised,dependent,titlebar=no",
  696.                 aID, aIcon, ( aTitle.length > 40 ) ? aTitle.substring(0,40) + "..." : aTitle
  697.             );
  698.         }
  699.     }
  700.  
  701.  
  702. };
  703.  
  704.  
  705.  
  706. function SBdownloadListener(aSBitem, aFileName)
  707. {
  708.     this.item     = { id : aSBitem.id, icon : aSBitem.icon, title : aSBitem.title };
  709.     this.fileName = aFileName;
  710.     this.callback = SBdownloadListenerCallback;
  711. }
  712.  
  713. SBdownloadListener.prototype = {
  714.  
  715.     onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
  716.     {
  717.         if ( aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP )
  718.         {
  719.             if ( --SBcapture.httpTask[this.item.id] == 0 ) {
  720.                 this.callback.onCompleteAllDownloads(this.item);
  721.             } else {
  722.                 this.callback.onCompleteDownload(this.item);
  723.             }
  724.         }
  725.     },
  726.     onProgressChange : function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
  727.     {
  728.         if ( aCurTotalProgress == aMaxTotalProgress ) return;
  729.         var progress = (aMaxSelfProgress > 0) ? Math.round(aCurSelfProgress / aMaxSelfProgress * 100) + "%" : aCurSelfProgress + "Bytes";
  730.         this.callback.onProgressDownload(this.item, this.fileName, progress);
  731.     },
  732.     onStatusChange   : function() {},
  733.     onLocationChange : function() {},
  734.     onSecurityChange : function() {},
  735. };
  736.  
  737.  
  738. var SBdownloadListenerCallback = {
  739.  
  740.     onCompleteDownload : function(aItem)
  741.     {
  742.         try {
  743.             top.window.document.getElementById("sidebar").contentWindow.SBstatus.httpBusy(SBcapture.httpTask[aItem.id], aItem.title);
  744.         } catch(ex) {
  745.         }
  746.     },
  747.     onCompleteAllDownloads : function(aItem)
  748.     {
  749.         try {
  750.             top.window.document.getElementById("sidebar").contentWindow.SBstatus.httpComplete(aItem.title);
  751.         } catch(ex) {
  752.         }
  753.         SBcapture.notifyOnComplete(aItem.id, aItem.icon, aItem.title);
  754.     },
  755.     onProgressDownload : function(aItem, aFileName, aProgress)
  756.     {
  757.         try {
  758.             top.window.document.getElementById("sidebar").contentWindow.SBstatus.httpBusy(SBcapture.httpTask[aItem.id], aProgress + " : " + aFileName);
  759.         } catch(ex) {
  760.         }
  761.     },
  762. };
  763.  
  764.  
  765.