Changeset 7

Show
Ignore:
Timestamp:
2007-01-04 16:39:03 (2 years ago)
Author:
MaierMan
Message:

--

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/chrome.manifest

    r4 r7  
    33skin    dta     classic/1.0 chrome/skin/classic/ 
    44locale  dta     en-US   chrome/locale/en-US/ 
    5 locale  dta     de-DE   chrome/locale/de-DE/ 
    6 locale  dta     el-GR   chrome/locale/el-GR/ 
    7 locale  dta     es-ES   chrome/locale/es-ES/ 
    8 locale  dta     fr-FR   chrome/locale/fr-FR/ 
    9 locale  dta     it-IT   chrome/locale/it-IT/ 
    10 locale  dta     ko-KR   chrome/locale/ko-KR/ 
    11 locale  dta     nl-NL   chrome/locale/nl-NL/ 
    12 locale  dta     pl-PL   chrome/locale/pl-PL/ 
    13 locale  dta     pt-BR   chrome/locale/pt-BR/ 
    14 locale  dta     ru-RU   chrome/locale/ru-RU/ 
    15 locale  dta     sk-SK   chrome/locale/sk-SK/ 
    16 locale  dta     bg-BG   chrome/locale/bg-BG/ 
    17 locale  dta     zh-CN   chrome/locale/zh-CN/ 
    18 locale  dta     he-IL   chrome/locale/he-IL/ 
    19 locale  dta     sv-SE   chrome/locale/sv-SE/ 
    20 locale  dta     cy-GB   chrome/locale/cy-GB/ 
    215 
    226content dta-pref-style  chrome/content/opzioni/style/   platform 
  • trunk/chrome/content/dta/down.js

    r6 r7  
    9292} 
    9393 
    94 // --------* Lista dei download *-------- 
     94function URLManager(urls) 
     95
     96        this._urls = []; 
     97        this._idx = 0; 
     98         
     99        if (urls instanceof Array) { 
     100                this.initByArray(urls); 
     101        } 
     102        else if (urls instanceof Node) { 
     103                        this.initByNode(urls); 
     104        } 
     105        else if (urls) { 
     106                throw "Feeding the URLManager with some bad stuff is usually a bad idea!"; 
     107        } 
     108
     109URLManager.prototype = { 
     110        _sort: function(a,b) { 
     111                const rv = a.preference - b.preference; 
     112                return rv ? rv : (a.url < b.url ? -1 : 1); 
     113        }, 
     114         
     115        initByNode: function um_initByNode(node) { 
     116                var nodes = node.getElementsByTagName('url'); 
     117                for (var i = 0; i < nodes.length; ++i) 
     118                { 
     119                        var n = nodes[i]; 
     120                        this.add(new DTA_URL( 
     121                                n.getAttribute('uri'), 
     122                                n.getAttribute('charset'), 
     123                                n.getAttribute('usable'), 
     124                                n.getAttribute('preference') 
     125                        )); 
     126                } 
     127                this._urls.sort(this._sort); 
     128                this._usable = this._urls[0].usable; 
     129        }, 
     130        initByArray: function um_initByArray(urls) { 
     131                for (var i = 0; i < urls.length; ++i) { 
     132                        this.add(urls[i]); 
     133                } 
     134                this._urls.sort(this._sort); 
     135                this._usable = this._urls[0].usable;             
     136        }, 
     137        add: function um_add(url) { 
     138                if (!url instanceof DTA_URL) { 
     139                        throw (url + " is not an DTA_URL"); 
     140                } 
     141                if (!this._urls.some(function(ref) { return ref.url == url.url; })) { 
     142                        this._urls.push(url); 
     143                } 
     144        }, 
     145        getURL: function um_getURL(idx) { 
     146                if (typeof(idx) != 'number') 
     147                { 
     148                        this._idx--; 
     149                        if (this._idx < 0) { 
     150                                this._idx = this._urls.length - 1; 
     151                        } 
     152                        idx = this._idx; 
     153                } 
     154                return this._urls[idx]; 
     155        }, 
     156        get url() { 
     157                return this._urls[0].url; 
     158        }, 
     159        get usable() { 
     160                return this._urls[0].usable; 
     161        }, 
     162        get charset() { 
     163                return this._urls[0].charset; 
     164        }, 
     165        replace: function um_replace(url, newUrl) { 
     166                this._urls.forEach(function(u,i,a){ if (u.url == url) u = newURL; }); 
     167        }, 
     168        save: function um_save(node) { 
     169                for (var i = 0; i < this._urls.length; ++i) 
     170                { 
     171                        var url = this._urls[i]; 
     172                        var n = node.ownerDocument.createElement("url"); 
     173                        n.setAttribute('uri', url.url); 
     174                        n.setAttribute('charset', url.charset); 
     175                        n.setAttribute('usable', url.usable); 
     176                        n.setAttribute('preference', url.preference); 
     177                        node.appendChild(n); 
     178                } 
     179        } 
     180}; 
     181 
     182const headerCmpKeys = { 
     183        'etag': true, // must not be modified from 200 to 206: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.7 
     184        //'content-length': false, 
     185        'content-type': true, 
     186        'last-modified': true, // may get omitted later, but should not change 
     187        'content-encoding': true // must not change, or download will become corrupt. 
     188}; 
     189 
     190function Visitor() { 
     191        // sanity check 
     192        if (arguments.length != 1 || !('attributes' in arguments[0])) return; 
     193 
     194        var nodes = arguments[0].getElementsByTagName('header'); 
     195        if (!nodes.length) { 
     196                throw "no headers"; 
     197        } 
     198        try     { 
     199                for (var i = 0; i < nodes.length; ++i) { 
     200                        var name = nodes[i].getAttribute('name'); 
     201                        if (!name || !(name in headerCmpKeys)) 
     202                        { 
     203                                continue; 
     204                        } 
     205                        this[name] = nodes[i].getAttribute('value'); 
     206                } 
     207        } catch (e) { 
     208                Debug.dump("hrhv::ctor", e); 
     209        } 
     210
     211 
     212Visitor.prototype = { 
     213        type : null, 
     214        overrideCharset: null, 
     215        encoding : null, 
     216        fileName : null, 
     217        dontacceptrange : false, 
     218        contentlength : 0, 
     219         
     220        QueryInterface: function(aIID) { 
     221                if ( 
     222                        aIID.equals(Components.interfaces.nsISupports) 
     223                        || aIID.equals(Components.interfaces.nsIHttpHeaderVisitor) 
     224                ) { 
     225                        return this; 
     226                } 
     227                throw Components.results.NS_ERROR_NO_INTERFACE; 
     228        }, 
     229        visitHeader : function(aHeader, aValue) {try { 
     230         
     231                const header = aHeader.toLowerCase(); 
     232                switch (header) { 
     233                        case 'content-type': 
     234                        { 
     235                                this.type = aValue; 
     236                                var ch = aValue.match(/charset=['"]?([\w\d_-]+)/i); 
     237                                if (ch && ch[1].length) { 
     238                                        DTA_debug.dump("visitHeader: found override to " + ch[1]); 
     239                                        this.overrideCharset = ch[1]; 
     240                                } 
     241                        } 
     242                        break; 
     243 
     244                        case 'content-encoding': 
     245                                this.encoding = aValue; 
     246                        break; 
     247 
     248                        case 'accept-ranges': 
     249                                this.dontacceptrange = (aValue.toLowerCase().indexOf('none') >= 0); 
     250                                Debug.dump("acceptrange = " + aValue.toLowerCase()); 
     251                        break; 
     252 
     253                        case 'content-length': 
     254                                this.contentlength = Number(aValue); 
     255                        break; 
     256 
     257                        case 'content-range': 
     258                                var dim = aValue.substring(aValue.lastIndexOf('/') + 1, aValue.length); 
     259                                if (dim.length>0 && dim.lastIndexOf('*')==-1) 
     260                                        this.contentlength = Number(dim); 
     261                        break; 
     262                } 
     263 
     264                if (header in headerCmpKeys) 
     265                        this[header] = aValue; 
     266                 
     267                if ((header == 'content-type' || header == 'content-disposition') && this.fileName == null) { 
     268                        // we have to handle headers like "content-disposition: inline; filename='dummy.txt'; title='dummy.txt';" 
     269                        var value = aValue.match(/file(name)?=(["']?)([^\2;]+)\2(;.+)?/i); 
     270                        if (!value) { 
     271                                // workaround for bug #13959 
     272                                // attachments on some vbulletin forums send nasty headers like "content-disposition: inline; filename*=utf-8''file.ext"  
     273                                value = aValue.match(/file(name)?\*=(.*)''(.+)/i); 
     274                                this.overrideCharset = 'utf-8'; 
     275                        } 
     276                        if (value) { 
     277                                this.fileName = value[3].getUsableFileName(); 
     278                        } 
     279                } 
     280        } catch (ex) { 
     281                Debug.dump("hrhv::visitHeader:", ex); 
     282        }                
     283        }, 
     284        compare : function vi_compare(v)        { 
     285                if (!(v instanceof Visitor)) { 
     286                        return; 
     287                } 
     288 
     289                for (x in headerCmpKeys) { 
     290                        // we don't have this header 
     291                        if (!(x in this)) { 
     292                                continue; 
     293                        } 
     294                        // v does not have this header 
     295                        else if (!(x in v)) { 
     296                                // allowed to be missing? 
     297                                if (headerCmpKeys[x]) { 
     298                                        continue; 
     299                                } 
     300                                Debug.dump(x + " missing"); 
     301                                throw (x + " is missing"); 
     302                        } 
     303                        // header is there, but differs 
     304                        else if (this[x] != v[x]) { 
     305                                Debug.dump(x + " nm: [" + this[x] + "] [" + v[x] + "]"); 
     306                                throw ("Header " + x + "doesn't match"); 
     307                        } 
     308                } 
     309        }, 
     310        save : function vi_save(node) { 
     311                // salva su file le informazioni sugli headers 
     312                for (x in headerCmpKeys) { 
     313                        if (!(x in this)) { 
     314                                continue; 
     315                        } 
     316                        var head = node.ownerDocument.createElement('header'); 
     317                        head.setAttribute('name', x); 
     318                        head.setAttribute('value', this[x]); 
     319                        node.appendChild(head); 
     320                } 
     321        } 
     322}; 
     323 
     324function VisitorManager() { 
     325        this._visitors = {}; 
     326
     327VisitorManager.prototype = { 
     328 
     329        load: function vm_init(node) { 
     330                var nodes = node.getElementsByTagName('visitor'); 
     331                for (var i = 0; i < nodes.length; ++i) { 
     332                        try { 
     333                                var visitor = new Visitor(nodes[i]); 
     334                                this._visitors[nodes[i].getAttribute('url')] = visitor;                          
     335                        } catch (ex) { 
     336                                Debug.dump("failed to read one visitor", ex); 
     337                        } 
     338                } 
     339        }, 
     340        save: function vm_save(node) { 
     341                for (x in this._visitors) { 
     342                        var v = node.ownerDocument.createElement('visitor'); 
     343                        v.setAttribute('url', x); 
     344                        this._visitors[x].save(v); 
     345                        node.appendChild(v); 
     346                } 
     347        }, 
     348        visit: function vm_visit(chan) { 
     349                var url = chan.URI.spec; 
     350                 
     351                var visitor = new Visitor(); 
     352                chan.visitResponseHeaders(visitor); 
     353                if (url in this._visitors) 
     354                { 
     355                                this._visitors[url].compare(visitor); 
     356                } 
     357                return (this._visitors[url] = visitor); 
     358        } 
     359}; 
     360 
    95361var chunkElement = function(start, end, d) { 
    96362        Debug.dump('ChunkElement: ' + start + "/" + end); 
     
    142408} 
    143409 
    144 function downloadElement(link, dir, num, desc, mask, refPage) { 
    145  
     410function downloadElement(lnk, dir, num, desc, mask, refPage) { 
     411 
     412        this.visitors = new VisitorManager(); 
     413         
    146414        dir = dir.addFinalSlash(); 
    147415         
    148         if (typeof link == 'string') { 
    149                 this.link = new DTA_URL(link); 
     416        if (typeof lnk == 'string') { 
     417                this.urlManager = new URLManager([new DTA_URL(lnk)]); 
     418        } else if (lnk instanceof URLManager) { 
     419                this.urlManager = lnk; 
    150420        } else { 
    151                 this.link = link
     421                this.urlManager = new URLManager([lnk])
    152422        } 
    153423 
    154424        this.dirSave = dir; 
    155425        this.originalDirSave = dir; 
    156         this.destinationName = this.fileName = this.link.usable.getUsableFileName(); 
     426        this.destinationName = this.fileName = this.urlManager.usable.getUsableFileName(); 
    157427        this.mask = mask; 
    158428        this.numIstance = num; 
     
    166436downloadElement.prototype = { 
    167437        contentType : "", 
    168         visitor : null, 
     438        visitors : null, 
    169439        totalSize : 0, 
    170440        partialSize : 0, 
     
    181451        isPaused : false, 
    182452        isCompleted : false, 
    183         isResumable : false, 
     453        isResumable: false, 
    184454        isRunning : false, 
    185455        isStarted : false, 
     
    203473        reDownload : function() { 
    204474                // replace names 
    205                  
    206                 this.destinationName = this.fileName = this.link.usable.getUsableFilenName(); 
     475                Debug.dump(this.urlManager.usable); 
     476                this.destinationName = this.fileName = this.urlManager.usable.getUsableFileName(); 
    207477                this.alreadyMaskedName = false; 
    208478                this.alreadyMaskedDir = false; 
     
    216486                this.declaratedChunks = 0; 
    217487                this.chunks = new Array(); 
    218                 this.visitor = null
     488                this.visitors = new VisitorManager()
    219489                this.getHeader(); 
    220490        }, 
    221491         
    222492        getHeader : function() { 
    223                 Debug.dump(this.link.url + " (" + this.refPage.spec +"): getHeader()"); 
     493                Debug.dump(this.urlManager.url + " (" + this.refPage.spec +"): getHeader()"); 
    224494                Prefs.refresh(); 
    225495                this.maxChunks = Prefs.maxChunks; 
     
    320590        }, 
    321591         
    322         moveCompleted : function(fileManager) {try{ 
    323  
    324                 if (this.join && !this.join.imJoining) this.join.closeStream(); 
    325                 if (this.isCanceled) return; 
     592        moveCompleted : function(fileManager) { 
     593 
     594                if (this.join) { 
     595                        this.join.closeStream(); 
     596                } 
     597                if (this.isCanceled) { 
     598                        return; 
     599                } 
     600                Debug.dump(this.isMetalink); 
    326601                 
    327602                // increment completedDownloads counter 
    328603                this.isCompleted = true; 
    329604                Stats.completedDownloads++;      
    330                  
    331                 var destination = cc["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); 
    332                 destination.initWithPath(this.dirSave); 
    333                 Debug.dump(this.fileName + ": Move " + fileManager.path + " to " + this.dirSave + this.destinationName); 
    334605 
    335606                try { 
    336                          
    337                         if (!destination.exists())  
     607                        var destination = cc["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); 
     608                        destination.initWithPath(this.dirSave); 
     609                        Debug.dump(this.fileName + ": Move " + fileManager.path + " to " + this.dirSave + this.destinationName); 
     610                         
     611                        if (!destination.exists()) { 
    338612                                destination.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0766); 
    339          
     613                       } 
    340614                        this.checkFilenameConflict(); 
    341615                        var destinationName = (this.compression)?("[comp]"+this.destinationName):this.destinationName; 
     
    344618                        fileManager.moveTo(destination, destinationName); 
    345619                         
    346                 } catch(e) { 
     620                } catch(ex) { 
    347621                        failDownload(this, strbundle.getString("accesserror"), strbundle.getString("permissions") + " " + strbundle.getString("destpath") + strbundle.getString("checkperm"), strbundle.getString("accesserror")); 
    348                         Debug.dump("download::moveCompleted: Could not move file or create directory: ", e); 
     622                        Debug.dump("download::moveCompleted: Could not move file or create directory: ", ex); 
    349623                        return; 
    350624                } 
    351                  
    352  
    353625                this.finishDownload(); 
    354                  
    355         } catch(e) {Debug.dump("download::moveCompleted: ", e)} 
    356         }, 
    357          
     626                if ('isMetalink' in this) { 
     627                        this.handleMetalink(); 
     628                }                
     629        }, 
     630        handleMetalink: function dl_handleMetaLink() { 
     631                try { 
     632                        for (var i = 0; i < downloadList.length; ++i) 
     633                        { 
     634                                if (downloadList[i] == this) { 
     635                                        removeElement(i); 
     636                                        break; 
     637                                } 
     638                        } 
     639                        var fileManager = new FileFactory(this.dirSave); 
     640                        fileManager.append(this.destinationName); 
     641                         
     642                        var fiStream = cc['@mozilla.org/network/file-input-stream;1'].createInstance(Components.interfaces.nsIFileInputStream); 
     643                        fiStream.init(fileManager, 1, 0, false); 
     644                        var domParser = new DOMParser(); 
     645                        var doc = domParser.parseFromStream(fiStream, null, fileManager.fileSize, "application/xml"); 
     646                        var root = doc.documentElement; 
     647                        fiStream.close(); 
     648                         
     649                        try { 
     650                                fileManager.remove(false); 
     651                        } catch (ex) { 
     652                                Debug.dump("failed to remove metalink file!", ex); 
     653                        } 
     654 
     655                        var downloads = []; 
     656                        var files = root.getElementsByTagName('file'); 
     657                        for (var i = 0; i < files.length; ++i) { 
     658                                var file = files[i]; 
     659                                var urls = []; 
     660                                var urlNodes = file.getElementsByTagName('url'); 
     661                                for (var j = 0; j < urlNodes.length; ++j) { 
     662                                        var url = urlNodes[j]; 
     663                                        if (['http', 'https'].indexOf(url.getAttribute('type')) != -1) { 
     664                                                urls.push(new DTA_URL(url.textContent, doc.characterSet)); 
     665                                        } 
     666                                } 
     667                                if (!urls.length) { 
     668                                        continue; 
     669                                } 
     670                                var desc = root.getElementsByTagName('description'); 
     671                                if (desc.length) { 
     672                                        desc = desc[0].textContent; 
     673                                } 
     674                                else { 
     675                                        desc = ''; 
     676                                } 
     677                                downloads.push({ 
     678                                        'url': new URLManager(urls), 
     679                                        'refPage': this.refPage.spec, 
     680                                        'numIstance': 0, 
     681                                        'mask': this.mask, 
     682                                        'dirSave': this.originalDirSave, 
     683                                        'description': desc, 
     684                                        'ultDescription': '' 
     685                                }); 
     686                        } 
     687                        if (downloads.length) 
     688                        { 
     689                                startnewDownloads(true, downloads); 
     690                        } 
     691                } catch (ex) { 
     692                        Debug.dump("hml exception", ex); 
     693                } 
     694        },       
    358695        finishDownload : function() { 
    359696 
     
    432769 
    433770                var uri = cc['@mozilla.org/network/standard-url;1'].createInstance(Components.interfaces.nsIURI); 
    434                 uri.spec = this.link.usable; 
     771                uri.spec = this.urlManager.usable; 
    435772 
    436773                // normalize slashes 
     
    470807                                var tempname = this.fileName.substring(0, this.fileName.lastIndexOf(".")); 
    471808                                var tempext = this.fileName.getExtension(); 
    472                                  
    473                                 /* 
    474                                         // if extension reflects MIME type... 
    475                                         if ( 
    476                                                 (new RegExp(mimeServ.getTypeFromExtension(tempext), "g")).test(contentType)  
    477                                                 ||  
    478                                                 (new RegExp(mimeServ.getTypeFromURI(uri), "g")).test(contentType) 
    479                                                 ) { 
    480                                                 // ..we use it 
    481                                                 name = tempname; 
    482                                                 ext = tempext; 
    483                                         } else { 
    484                                                 // ..else we add mime.primaryExtension to existing extension 
    485                                                 var info = mimeServ.getFromTypeAndExtension(contentType, null); 
    486                                                 name = tempname; 
    487                                                 ext = tempext + "." + info.primaryExtension; 
    488                                         } 
    489                                 */ 
    490809                                 
    491810                                // ..we use it 
     
    570889                var maxUrlSize = 70; // set the max size limit of a URL string, after which the string will be trimmed 
    571890 
    572                 var shortUrl = (this.link.usable).cropCenter(maxUrlSize); 
     891                var shortUrl = (this.urlManager.usable).cropCenter(maxUrlSize); 
    573892                var s = -1; 
    574893                if (!this.isCompleted && this.isRunning) { 
     
    582901                                if (p != -1) { 
    583902                                        s = askForRenaming( 
    584                                                 strbundle.getString("samedestination", [shortUrl, this.destinationName, inProgressList[p].d.link.url]) + " " + strbundle.getString("whatdoyou"), 
     903                                                strbundle.getString("samedestination", [shortUrl, this.destinationName, inProgressList[p].d.urlManager.url]) + " " + strbundle.getString("whatdoyou"), 
    585904                                                {caption:strbundle.getFormattedString("reninto", [newDest]), value:0}, {caption:strbundle.getString("skipfirst"), value:2}, {caption:strbundle.getString("cancelsecond"), value:3} 
    586905                                        ); 
     
    628947                if (!this.isCanceled) { 
    629948                        Debug.dump(this.fileName + ": cancelDownload()"); 
    630                         if (this.isFirst) Check.setFirstInQueue(); 
     949                         
     950                        this.visitors = new VisitorManager(); 
     951                         
     952                        if (this.isFirst) { 
     953                                Check.setFirstInQueue(); 
     954                        } 
    631955                        this.isCanceled = true; 
    632956                         
    633                         if (message == "" || !message) 
     957                        if (message == "" || !message) { 
    634958                                message = strbundle.getString("canceled"); 
    635  
     959                        } 
    636960                        this.setTreeCell("status", message); 
    637961                        this.setTreeProgress("canceled"); 
     
    660984                        popup(); 
    661985                } 
    662         } catch(e) { 
    663                 Debug.dump("cancelDownload():", e); 
     986        } catch(ex) { 
     987                Debug.dump("cancelDownload():", ex); 
    664988        } 
    665989        }, 
     
    13561680        } 
    13571681} 
    1358  
    1359 const headerCmpKeys = { 
    1360         //'etag': true, // must not be modified from 200 to 206: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.7 
    1361         'last-modified': true, // may get omitted later, but should not change 
    1362         'content-encoding': true // must not change, or download will become corrupt. 
    1363 }; 
    1364  
    1365 var HTTPResponseHeaderVisitor = function() { 
    1366         // sanity check 
    1367         if (arguments.length != 1 || !('attributes' in arguments[0])) return; 
    1368  
    1369         var headers = arguments[0]; 
    1370         // carica da file le informazioni sugli headers 
    1371         try     { 
    1372                 for (x in headerCmpKeys)        { 
    1373                         // step over all unset stuff 
    1374                         if (!headers.hasAttribute('header-' + x)) 
    1375                                 continue; 
    1376                         this[x] = headers.getAttribute('header-' + x); 
    1377                 } 
    1378         } catch (e) { 
    1379                 Debug.dump("hrhv::ctor", e); 
    1380         } 
    1381 } 
    1382  
    1383 HTTPResponseHeaderVisitor.prototype = { 
    1384         type : null, 
    1385         overrideCharset: null, 
    1386         encoding : null, 
    1387         fileName : null, 
    1388         dontacceptrange : false, 
    1389         contentlength : 0, 
    1390          
    1391         QueryInterface: function(aIID) { 
    1392                 if ( 
    1393                         aIID.equals(Components.interfaces.nsISupports) 
    1394                         || aIID.equals(Components.interfaces.nsIHttpHeaderVisitor) 
    1395                 ) { 
    1396                         return this; 
    1397                 } 
    1398                 throw Components.results.NS_ERROR_NO_INTERFACE; 
    1399         }, 
    1400         visitHeader : function(aHeader, aValue) {try { 
    1401          
    1402                 const header = aHeader.toLowerCase(); 
    1403                 switch (header) { 
    1404                         case 'content-type': 
    1405                         { 
    1406                                 this.type = aValue; 
    1407                                 var ch = aValue.match(/charset=['"]?([\w\d_-]+)/i); 
    1408                                 if (ch.length == 2 && ch[1].length) { 
    1409                                         DTA_debug.dump("visitHeader: found override to " + ch[1]); 
    1410                                         this.overrideCharset = ch[1]; 
    1411                                 } 
    1412                         } 
    1413                         break; 
    1414  
    1415                         case 'content-encoding': 
    1416                                 this.encoding = aValue; 
    1417                         break; 
    1418  
    1419                         case 'accept-ranges': 
    1420                                 this.dontacceptrange = (aValue.toLowerCase().indexOf('none') >= 0); 
    1421                                 Debug.dump("acceptrange = " + aValue.toLowerCase()); 
    1422                         break; 
    1423  
    1424                         case 'content-length': 
    1425                                 this.contentlength = Number(aValue); 
    1426                         break; 
    1427  
    1428                         case 'content-range': 
    1429                                 var dim = aValue.substring(aValue.lastIndexOf('/') + 1, aValue.length); 
    1430                                 if (dim.length>0 && dim.lastIndexOf('*')==-1) 
    1431                                         this.contentlength = Number(dim); 
    1432                         break; 
    1433                 } 
    1434  
    1435                 if (header in headerCmpKeys) 
    1436                         this[header] = aValue; 
    1437                  
    1438                 if ((header == 'content-type' || header == 'content-disposition') && this.fileName == null) { 
    1439                         // we have to handle headers like "content-disposition: inline; filename='dummy.txt'; title='dummy.txt';" 
    1440                         var value = aValue.match(/file(name)?=(["']?)([^\2;]+)\2(;.+)?/i); 
    1441                         if (!value) { 
    1442                                 // workaround for bug #13959 
    1443                                 // attachments on some vbulletin forums send nasty headers like "content-disposition: inline; filename*=utf-8''file.ext"  
    1444                                 value = aValue.match(/file(name)?\*=(.*)''(.+)/i); 
    1445                                 this.overrideCharset = 'utf-8'; 
    1446                         } 
    1447                         if (value) { 
    1448                                 this.fileName = value[3].getUsableFileName(); 
    1449                         } 
    1450                 } 
    1451         } catch (ex) { 
    1452                 Debug.dump("hrhv::visitHeader:", ex); 
    1453         }                
    1454         }, 
    1455         compare : function(vi)  { 
    1456                 try     { 
    1457                         v = vi.QueryInterface(Components.interfaces.nsIHttpHeaderVisitor); 
    1458                 }       catch (ex) { 
    1459                         return false; 
    1460                 } 
    1461                  
    1462                 for (x in headerCmpKeys) { 
    1463                         // se non abbiamo l'informazione pace 
    1464                         if (!(x in this)) { 
    1465                                 continue; 
    1466                         // se ce l'abbiamo ma non c'e' nel nuovo chunk, e non si puo' 
    1467                         } else if (!(x in v)) { 
    1468                                 // if MAY be missing 
    1469                                 if (headerCmpKeys[x]) { 
    1470                                         continue; 
    1471                                 } 
    1472                                 Debug.dump(x + " non presente!"); 
    1473                                 return false; 
    1474                         // se ce l'abbiamo in entrambi ma differiscono 
    1475                         } else if (this[x] != v[x]) { 
    1476                                 Debug.dump(x + ": prima:" + v[x] + " ora: " + this[x]); 
    1477                                 return false; 
    1478                         } 
    1479                 } 
    1480                 return true; 
    1481         }, 
    1482         save : function(node) { 
    1483                 // salva su file le informazioni sugli headers 
    1484                 for (x in headerCmpKeys) { 
    1485                         if (!(x in this)) { 
    1486                                 continue; 
    1487                         } 
    1488                         node.setAttribute('header-' + x, this[x]); 
    1489                 } 
    1490                 node.setAttribute('hasHeaders', true); 
    1491         } 
    1492 }; 
    14931682 
    14941683// --------* Progress Listener per il singolo download *-------- 
     
    17071896         
    17081897                Debug.dump(d.fileName + ": Download is completed!"); 
     1898                 
    17091899                // multipart downloads have moveCompleted call after the last joining process 
    17101900                if (d.chunks.length == 1) 
     
    17311921                                d.compression = false; 
    17321922                                d.declaratedChunks = 0; 
    1733                                 d.visitor = null
     1923                                d.visitors = new VisitorManager()
    17341924                        } 
    17351925                        Check.checkClose(); 
     
    18572047                                d.setTreeCell("dir", d.dirSave); 
    18582048                                return; 
    1859                         } else { 
    1860  
    1861                                 // every chunk has to check response status senseness 
    1862                                 if (chan.responseStatus == 401 && "user" in d && d.user!="" && "pass" in d && d.pass!="") { 
    1863                                         Debug.dump(d.fileName + ": Trying to redownload file with user and pass.."); 
    1864                                         d.hasToBeRedownloaded = true; 
    1865                                         d.redownloadIsResumable = null; 
    1866                                         this.isHeaderHack = false; 
    1867                                         c.end = d.totalSize - 1; 
    1868                                         d.setPaused(); 
    1869                                         return; 
    1870                                 } else if (chan.responseStatus >= 400) { 
    1871                                         // se si tratta di errore >= 400 blocchiamo e basta 
    1872                                         failDownload( 
    1873                                         d, 
    1874                                         strbundle.getFormattedString("error", [chan.responseStatus]), 
    1875                                         strbundle.getFormattedString("failed", [((d.fileName.length>50)?(d.fileName.substring(0, 50)+"..."):d.fileName)]) + " " + strbundle.getFormattedString("sra", [chan.responseStatus]) + ": " + chan.responseStatusText, 
    1876                                         strbundle.getFormattedString("error", [chan.responseStatus]) 
    1877                                         ); 
    1878                                         return; 
    1879                                 } else if (chan.responseStatus != 206 && c.end != 0) { 
    1880                                         // se stiamo richiedendo un range e non ci viene dato codice 206, ci buttiamo nei chunk singoli 
    1881                                         Debug.dump(d.fileName + ": Server returned a " + chan.responseStatus + " response instead of 206... Normal mode"); 
    1882                                         d.hasToBeRedownloaded = true; 
    1883                                         d.redownloadIsResumable = false; 
    1884                                         d.setPaused(); 
    1885                                         return; 
    1886                                 } 
    1887  
    1888                                 // every chunk has to check response headers senseness 
    1889                                 var visitor = new HTTPResponseHeaderVisitor(); 
    1890                                 chan.visitResponseHeaders(visitor); 
    1891  
    1892                                 // save visitor to compare later 
    1893                                 if (d.visitor == null) { 
    1894                                         d.visitor = visitor; 
    1895                                 } 
    1896                                 // if we can compare response headers 
    1897                                 else if (!d.visitor.compare(visitor)) { 
    1898                                         Debug.dump(d.fileName + ": Header senseness test failed.. Let's start redownloading it"); 
    1899                                         // restart download from the beginning 
    1900                                         d.hasToBeRedownloaded = true; 
    1901                                         // To prevent sites with malformed e-tag, d.redownloadIsResumable = false 
    1902                                         d.redownloadIsResumable = false; 
    1903                                         d.setPaused(); 
    1904                                         return; 
    1905                                 } 
    1906  
    1907