Changeset 395

Show
Ignore:
Timestamp:
2007-06-08 00:23:28 (2 years ago)
Author:
MaierMan
Message:

merging with source:branches/maierman/manager-trees
patch available at http://code.downthemall.net/maierman/patches/dta-mt-trunk.diff

  • new download algorithm (one-file, recovering, failover)
  • new manager window architecture
  • verfication added (checksums)
  • metalink: added verficiation + file selection
  • link fingerprints added
Files:

Legend:

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

    r226 r395  
    11### package ### 
    22content dta     chrome/content/ 
     3content dta-help        chrome/help/ 
    34skin    dta     classic/1.0 chrome/skin/ 
    45locale  dta     en-US   chrome/locale/en-US/ 
  • trunk/chrome/content/about/about.xul

    r273 r395  
    4141 
    4242<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> 
    43 <?xml-stylesheet href="chrome://dta/skin/common/style.css" type="text/css"?> 
    4443<?xml-stylesheet href="style.css" type="text/css"?> 
    4544<?xml-stylesheet href="resource://gre/res/html.css" type="text/css"?> 
     
    108107                        You are welcome to redistribute it under certain conditions: 
    109108                </description> 
    110                 <label class="link" value="License" onclick="openTab('chrome://dta/content/gpl.txt');"/> 
     109                <label class="link" value="License (GPL)" onclick="openTab('http://www.gnu.org/licenses/gpl.txt');"/> 
    111110                <separator class="thin"/> 
    112111                <description> 
    113112                        DownThemAll! values your privacy.<html:br/> 
    114                         See our <html:span class="link" onclick="openHelp('About_Privacy','chrome://dta/locale/help/dtahelp.rdf');">Privacy notice</html:span>. 
     113                        See our <html:span class="link" onclick="openHelp('About_Privacy','chrome://dta-help/content/help.rdf');">Privacy notice</html:span>. 
    115114                </description> 
    116115 
  • trunk/chrome/content/about/style.css

    r36 r395  
    1 /* ***** BEGIN LICENSE BLOCK ***** 
    2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1 
    3  * 
    4  * The contents of this file are subject to the Mozilla Public License Version 
    5  * 1.1 (the "License"); you may not use this file except in compliance with 
    6  * the License. You may obtain a copy of the License at 
    7  * http://www.mozilla.org/MPL/ 
    8  * 
    9  * Software distributed under the License is distributed on an "AS IS" basis, 
    10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
    11  * for the specific language governing rights and limitations under the 
    12  * License. 
    13  * 
    14  * The Original Code is downTHEMall. 
    15  * 
    16  * The Initial Developer of the Original Code is Nils Maier 
    17  * Portions created by the Initial Developer are Copyright (C) 2007 
    18  * the Initial Developer. All Rights Reserved. 
    19  * 
    20  * Contributor(s): 
    21  *   Nils Maier <MaierMan@web.de> 
    22  * 
    23  * Alternatively, the contents of this file may be used under the terms of 
    24  * either the GNU General Public License Version 2 or later (the "GPL"), or 
    25  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 
    26  * in which case the provisions of the GPL or the LGPL are applicable instead 
    27  * of those above. If you wish to allow use of your version of this file only 
    28  * under the terms of either the GPL or the LGPL, and not to allow others to 
    29  * use your version of this file under the terms of the MPL, indicate your 
    30  * decision by deleting the provisions above and replace them with the notice 
    31  * and other provisions required by the GPL or the LGPL. If you do not delete 
    32  * the provisions above, a recipient may use your version of this file under 
    33  * the terms of any one of the MPL, the GPL or the LGPL. 
    34  * 
    35  * ***** END LICENSE BLOCK ***** */ 
     1@import 'chrome://dta/skin/common/style.css'; 
    362 
    37 .link { 
    38         color: blue; 
    39         text-decoration: underline; 
    40         cursor: pointer; 
    41 } 
    42 .link:hover { 
    43         color: red; 
    44 } 
    453groupbox { 
    464        background: white; 
  • trunk/chrome/content/common/bindings.css

    r296 r395  
    5454        -moz-image-region: rect(0px,72px,21px,48px) !important; 
    5555} 
     56 
     57richlistbox.metalinker .item { 
     58        -moz-binding: url(chrome://dta/content/common/bindings.xml#metalinker-item); 
     59} 
  • trunk/chrome/content/common/bindings.xml

    r294 r395  
    8080                <content> 
    8181                        <xul:vbox flex="1"> 
    82                         <xul:menulist anonid="list" editable="true" xbl:inherits="flex,tooltiptext,oninput=onchange,onselect=onchange"> 
     82                        <xul:menulist anonid="list" editable="true" xbl:inherits="readonly,disabled,flex,tooltiptext,oninput=onchange,onselect=onchange"> 
    8383                                <xul:menupopup anonid="popup" xbl:inherits="onselect=onchange,oncommand=onchange"/> 
    8484                        </xul:menulist> 
     
    106106                                                return eval(DTA_preferences.getMultiByteDTA(this._pref, rv)); 
    107107                                        } catch (ex) { 
    108                                                 alert(ex); 
    109108                                                return eval(rv); 
    110109                                        } 
     
    112111                        </property> 
    113112                        <property name="_max" onget="return DTA_preferences.getDTA('history', 5);"/> 
    114                         <property name="current" onget="return this._list.value"> 
     113                        <property name="inputField" onget="return this._list.inputField"/> 
     114                        <property name="value" onget="return this._list.value"> 
    115115                                <setter> 
    116116                                        val = String(val); 
    117                                         if (this.current == val) { 
     117                                        if (this.value == val) { 
    118118                                                return; 
    119119                                        } 
     
    139139                                        if (values.length) { 
    140140                                                this._list.selectedIndex = 0; 
    141                                                 this.current = values[0]; 
     141                                                this.value = values[0]; 
    142142                                        }                                
    143143                                        if (this.hasAttribute('readonly')) { 
     
    152152                        <method name="save"> 
    153153                                <body><![CDATA[ 
    154                                         var n = this.current
     154                                        var n = this.value
    155155                                        if ((!this.modified && this._list.selectedIndex == 0) || (n.length == 0 && !this.hasAttribute('allowempty'))) { 
    156156                                                return; 
     
    174174                </implementation> 
    175175        </binding> 
     176 
     177        <binding id="metalinker-item" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem"> 
     178                <content> 
     179                        <xul:hbox flex="1"> 
     180                                <xul:vbox> 
     181                                        <xul:image class="icon" xbl:inherits="src=iconURL"/> 
     182                                        <xul:spacer flex="1"/> 
     183                                </xul:vbox> 
     184                                <xul:vbox flex="1"> 
     185                                        <xul:checkbox anonid="check" xbl:inherits="label=identity,checked"/> 
     186                                        <xul:description flex="1" anonid="desc"/> 
     187                                        <xul:hbox> 
     188                                                <xul:description flex="1" class="url" crop="center" xbl:inherits="value=url"/> 
     189                                        </xul:hbox> 
     190                                </xul:vbox> 
     191                                <xul:vbox class="additional"> 
     192                                        <xul:description xbl:inherits="value=lang"/> 
     193                                        <xul:description xbl:inherits="value=sys"/> 
     194                                </xul:vbox> 
     195                        </xul:hbox> 
     196                </content> 
     197                 
     198                <implementation> 
     199                        <constructor><![CDATA[ 
     200                                var dl = this.download; 
     201                                this.setAttribute('checked', dl.selected); 
     202                                this.setAttribute('identity', dl.identity ? dl.identity : dl.url.usable.getUsableFileName()); 
     203                                this.setAttribute('iconURL', dl.logo ? dl.logo : getIcon(dl.url.usable, false, 32)); 
     204                                this.setAttribute('url', dl.url.usable); 
     205                                this.setAttribute('lang', dl.lang); 
     206                                this.setAttribute('sys', dl.sys); 
     207                                if (dl.description) { 
     208                                        this._desc.appendChild(document.createTextNode(dl.description)); 
     209                                } 
     210                        ]]></constructor> 
     211                        <property name="_checkbox" onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'check');"/> 
     212                        <property name="_desc" onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'desc');"/> 
     213                        <property name="checked" onget="return this._checkbox.checked;"/> 
     214                </implementation> 
     215    <handlers> 
     216      <handler event="click" button="0" phase="capturing"> 
     217      <![CDATA[ 
     218        event.preventDefault(); 
     219        event.stopPropagation(); 
     220        this._checkbox.checked = !this._checkbox.checked; 
     221      ]]> 
     222      </handler> 
     223    </handlers>          
     224        </binding>       
     225         
    176226</bindings> 
    177227                                 
  • trunk/chrome/content/common/internalFunctions.js

    r281 r395  
    4545const SYSTEMSLASH = (DTA_profileFile.get('dummy').path.indexOf('/') != -1) ? '/' : '\\'; 
    4646 
     47// shared state defines 
     48const QUEUED =    0; 
     49const PAUSED =    1<<1; 
     50const RUNNING =   1<<2; 
     51const FINISHING = 1<<3; 
     52const COMPLETE =  1<<4; 
     53const CANCELED =  1<<5; 
    4754/** 
    4855 * cast non-strings to string 
     
    6774} 
    6875 
    69 // From prototype.js :) 
    70 function objectExtend(destination, source) { 
    71   for (property in source) { 
    72     destination[property] = source[property]; 
    73   } 
    74   return destination; 
    75 } 
    76  
    7776/** 
    7877 * Get DOM Element(s) by Id. Missing ids are silently ignored! 
     
    8483                return document.getElementById(arguments[0]); 
    8584        } 
    86   var elements = []; 
    87   for (var i = 0, e = arguments.length; i < e; ++i) { 
    88     var id = arguments[i]; 
    89     var element = document.getElementById(id); 
     85       var elements = []; 
     86       for (var i = 0, e = arguments.length; i < e; ++i) { 
     87               var id = arguments[i]; 
     88               var element = document.getElementById(id); 
    9089                if (element) { 
    9190                        elements.push(element); 
     
    9493                        Debug.dump("requested a non-existing element: " + id); 
    9594                } 
    96   } 
    97   return elements; 
    98 
    99  
    100 function formatBytes(aNumber) { 
    101         aNumber = Number(aNumber); 
    102  
    103         if (aNumber < 1024)     { 
    104                 return aNumber.toFixed(0) + " b"; 
    105         } 
    106          
    107         var units = ['TB','GB','MB','KB']; 
    108         var unit; 
    109          
    110         while (aNumber > 875 && units.length) { 
    111                 aNumber /= 1024; 
    112                 unit = units.pop(); 
    113         } 
    114          
    115         return aNumber.toFixed(2) + " " + unit; 
    116  
    117 
    118  
    119 objectExtend(String.prototype,  
    120 {        
    121         trim : function() { 
    122                 return this.replace(/^[\s\t]+|[\s\t]+$/gi, ""); 
    123         }, 
    124         removeBadChars : function() { 
    125                 return this 
    126                         .replace(/[\?\:<>\*\|"]/g, "_") 
    127                         .replace(/%(?:25)?20/g, " "); 
    128         }, 
    129         addFinalSlash : function() { 
    130                 if (this.length == 0) return new String(SYSTEMSLASH); 
    131                  
    132                 if (this[this.length - 1] != SYSTEMSLASH) 
    133                         return this + SYSTEMSLASH; 
    134                 else 
     95        } 
     96        return elements; 
     97
     98 
     99function merge(me, that) { 
     100        for (let c in that) { 
     101                me[c] = that[c]; 
     102        } 
     103
     104 
     105        // not instanceof save, you know ;) 
     106function clone(obj) { 
     107        { 
     108                var rv = {}; 
     109                merge(rv, obj); 
     110                rv.prototype = this.prototype; 
     111    rv.constructor = this.constructor; 
     112                return rv; 
     113        } 
     114
     115merge( 
     116        String.prototype, 
     117        {  
     118                trim : function() { 
     119                        return this.replace(/^[\s\t]+|[\s\t]+$/gi, ""); 
     120                }, 
     121                removeBadChars : function() { 
     122                        return this 
     123                                .replace(/[\?\:<>\*\|"]/g, "_") 
     124                                .replace(/%(?:25)?20/g, " "); 
     125                }, 
     126                addFinalSlash : function() { 
     127                        if (this.length == 0) return new String(SYSTEMSLASH); 
     128                         
     129                        if (this[this.length - 1] != SYSTEMSLASH) 
     130                                return this + SYSTEMSLASH; 
     131                        else 
     132                                return this; 
     133                }, 
     134                removeFinalChar : function(c) { 
     135                        if (this.length == 0) { 
     136                                return this; 
     137                        } 
     138                        if (this[this.length - 1] == c) { 
     139                                return this.substring(0, this.length - 1); 
     140                        } 
    135141                        return this; 
    136         }, 
    137         removeFinalChar : function(c) { 
    138                 if (this.length == 0) { 
     142                }, 
     143                removeLeadingChar : function(c) { 
     144                        if (this.length == 0) { 
     145                                return this; 
     146                        } 
     147                        if (this[0] == c) { 
     148                                return this.slice(1); 
     149                        } 
    139150                        return this; 
    140                 } 
    141                 if (this[this.length - 1] == c) { 
    142                         return this.substring(0, this.length - 1); 
    143                 } 
    144                 return this; 
    145         }, 
    146         removeLeadingChar : function(c) { 
    147                 if (this.length == 0) { 
     151                }, 
     152                removeFinalSlash : function() { 
     153                        return this.removeFinalChar(SYSTEMSLASH); 
     154                }, 
     155                removeLeadingSlash : function() { 
     156                        return this.removeLeadingChar(SYSTEMSLASH); 
     157                }, 
     158                removeFinalBackSlash : function() { 
     159                        return this.removeFinalChar("/"); 
     160                }, 
     161                removeLeadingBackSlash : function() { 
     162                        return this.removeLeadingChar("/"); 
     163                }, 
     164                removeArguments : function() { 
     165                        return this.replace(/[\?#].*$/g, ""); 
     166                }, 
     167                getUsableFileName : function() { 
     168                        var t = this.trim().removeArguments().removeFinalBackSlash().split("/"); 
     169                        return t[t.length-1].removeBadChars().replace(/[\\/]/g, "").trim(); 
     170                }, 
     171                getExtension : function() { 
     172                        var name = this.getUsableFileName(); 
     173                        var c = name.lastIndexOf('.'); 
     174                        if (c == -1) { 
     175                                return null; 
     176                        } 
     177                        return name.slice(c+1); 
     178                }, 
     179                cropCenter : function(newLength) { 
     180                        if (this.length > newLength) { 
     181                                return this.substring(0, newLength / 2) + "..." + this.substring(this.length - newLength / 2, this.length); 
     182                        } 
    148183                        return this; 
    149184                } 
    150                 if (this[0] == c) { 
    151                         return this.slice(1); 
    152                 } 
    153                 return this; 
    154         }, 
    155         removeFinalSlash : function() { 
    156                 return this.removeFinalChar(SYSTEMSLASH); 
    157         }, 
    158         removeLeadingSlash : function() { 
    159                 return this.removeLeadingChar(SYSTEMSLASH); 
    160         }, 
    161         removeFinalBackSlash : function() { 
    162                 return this.removeFinalChar("/"); 
    163         }, 
    164         removeLeadingBackSlash : function() { 
    165                 return this.removeLeadingChar("/"); 
    166         }, 
    167         removeArguments : function() { 
    168                 return this.replace(/[\?#].*$/g, ""); 
    169         }, 
    170         getUsableFileName : function() { 
    171                 var t = this.trim().removeArguments().removeFinalBackSlash().split("/"); 
    172                 return t[t.length-1].removeBadChars().replace(/[\\/]/g, "").trim(); 
    173         }, 
    174         getExtension : function() { 
    175                 var name = this.getUsableFileName(); 
    176                 var c = name.lastIndexOf('.'); 
    177                 if (c == -1) { 
    178                         return null; 
    179                 } 
    180                 return name.slice(c+1); 
    181         }, 
    182         formatTimeDate : function() { 
    183                 return this.replace(/\b(\d)\b/g, "0$1"); 
    184         }, 
    185         cropCenter : function(newLength) { 
    186                 if (this.length > newLength) { 
    187                         return this.substring(0, newLength / 2) + "..." + this.substring(this.length - newLength / 2, this.length); 
    188                 } 
    189                 return this; 
    190         } 
    191 
     185        } 
    192186); 
    193187 
     
    208202                 
    209203                        // locate current directory 
    210                         var dest = this.isValidDir(predefined); 
     204                        var dest = this.validateDir(predefined); 
    211205                        if (dest) { 
    212206                                fp.displayDirectory = dest; 
     
    226220        }, 
    227221        /** 
    228          * Performs all the needed controls to see if the specified path is valid, is creable and writable and his drive has some free disk space.   
     222         * Performs all the needed controls to see if the specified path is valid, is creable and writable and his drive has some free disk space.      
    229223         * @param path The path to test 
    230224         * @return a nsILocalFile to the specified path if it's valid, false if it wasn't 
    231225         */ 
    232         isValidDir: function(path) { 
    233                 if (!path || !String(path).trim().length) { 
    234                         return false; 
    235                 } 
    236                 var directory = Components.classes["@mozilla.org/file/local;1"]. 
    237                 createInstance(Components.interfaces.nsILocalFile); 
    238                 try { 
    239                         directory.initWithPath(path); 
    240                         // look for the first directory that exists. 
    241                         var parent = directory.clone(); 
    242                         while (parent && !parent.exists()) { 
    243                                 parent = parent.parent; 
    244                         } 
    245                         if (parent) { 
    246                                 // from nsIFile 
    247                                 parent = parent.QueryInterface(Components.interfaces.nsILocalFile); 
    248                                 // we look for a directory that is writeable and has some diskspace 
    249                                 return parent.isDirectory() && parent.isWritable() && parent.diskSpaceAvailable ? directory : false; 
    250                         } 
    251                 } catch(ex) { 
    252                         Debug.dump('Utils.isValidDir()', ex); 
     226        validateDir: function(path) { 
     227                var directory = null; 
     228                if (!(path instanceof Components.interfaces.nsILocalFile)) { 
     229                        if (!path || !String(path).trim().length) { 
     230                                return false; 
     231                        } 
     232                        var directory = Components.classes["@mozilla.org/file/local;1"]. 
     233                        createInstance(Components.interfaces.nsILocalFile); 
     234                        try { 
     235                                directory.initWithPath(path); 
     236                        } 
     237                        catch (ex) { 
     238                                // 
     239                        } 
     240                } 
     241                else { 
     242                        directory = path.clone(); 
     243                } 
     244                if (directory) { 
     245                        try { 
     246                                // look for the first directory that exists. 
     247                                var parent = directory.clone(); 
     248                                while (parent && !parent.exists()) { 
     249                                        parent = parent.parent; 
     250                                } 
     251                                if (parent) { 
     252                                        // from nsIFile 
     253                                        parent = parent.QueryInterface(Components.interfaces.nsILocalFile); 
     254                                        // we look for a directory that is writeable and has some diskspace 
     255                                        return parent.isDirectory() && parent.isWritable() && parent.diskSpaceAvailable ? directory : false; 
     256                                } 
     257                        } 
     258                        catch(ex) { 
     259                                Debug.dump('Utils.validateDir()', ex); 
     260                        } 
    253261                } 
    254262                return false; 
     
    287295                } 
    288296                var rv = Date.parse(str); 
    289                 if (isNaN(rv)) { 
     297                if (!isFinite(rv)) { 
    290298                        throw new Error("invalid date"); 
    291299                } 
    292300                return rv; 
     301        }, 
     302 
     303        /** 
     304         * returns a formated representation of a (file) size 
     305         * @param aNumber The number to format 
     306         * @author Nils 
     307         */ 
     308        formatBytes: function U_formatBytes(aNumber) { 
     309                aNumber = Number(aNumber); 
     310         
     311                if (aNumber < 1024) { 
     312                        return aNumber.toFixed(0) + " b"; 
     313                } 
     314                 
     315                var units = ['TB','GB','MB','KB']; 
     316                var unit; 
     317                 
     318                while (aNumber > 875 && units.length) { 
     319                        aNumber /= 1024; 
     320                        unit = units.pop(); 
     321                } 
     322                 
     323                return aNumber.toFixed(2) + " " + unit; 
     324        }, 
     325         
     326        /** 
     327         * returns a pretty number containing at least specified number of digits 
     328         * @param aNumber the number to format 
     329         * @param aDigists Optional. Number of digits the result must at least have 
     330         * @author Nils 
     331         */ 
     332        formatNumber: function U_formatNumber(rv, digits) { 
     333                rv = _atos(rv); 
     334                if (typeof(digits) != 'number') { 
     335                        digits = 3; 
     336                } 
     337                while (rv.length < digits) { 
     338                        rv = '0' + rv; 
     339                } 
     340                return rv; 
     341        }, 
     342        /** 
     343         * formats a time-delta. At least minutes and seconds are given back 
     344         */ 
     345        formatTimeDelta: function U_formatTimeDelta(aDelta) { 
     346                var h = Math.floor(aDelta / 3600); 
     347                var m = Math.floor((aDelta % 3600) / 60); 
     348                var s = Math.floor(aDelta % 60); 
     349                if (h) { 
     350                        return this.formatNumber(h, 2) + ":" + this.formatNumber(m, 2) + ":" + this.formatNumber(s, 2); 
     351                } 
     352                return this.formatNumber(m, 2) + ":" + this.formatNumber(s, 2); 
    293353        } 
    294354}; 
     
    365425                        || iid.equals(Components.interfaces.nsIWeakReference) 
    366426                        || iid.equals(Components.interfaces.nsiObserver) 
    367                 )     
     427                )
    368428                        return this; 
    369429                } 
     
    407467                        } 
    408468                } 
    409                 throw new Components.Exception('BUNDLE STRING NOT FOUND'); 
     469                throw new Components.Exception('BUNDLE STRING NOT FOUND (' + id + ')'); 
    410470        }, 
    411471        getFormattedString: function(id, params) { 
     
    418478                        } 
    419479                } 
    420                 throw new Components.Exception('BUNDLE STRING NOT FOUND');              
     480                throw new Components.Exception('BUNDLE STRING NOT FOUND (' + id + ')');          
    421481        } 
    422482}; 
     
    476536        }, 
    477537        _nixLaunch: function(file) { 
    478                 this._proto.loadUrl(this._io.newFileURI(file));         
     538                this._proto.loadUrl(this._io.newFileURI(file));  
    479539        }, 
    480540        /** 
     
    536596        } 
    537597        else { 
    538                 step = stop - start > 0 ? 1 : -1;       
    539         } 
    540         if (isNaN(start) || isNaN(stop) || isNaN(step) || step == 0) { 
     598                step = stop - start > 0 ? 1 : -1;  
     599        } 
     600        if (!isFinite(start) || !isFinite(stop) || !isFinite(step) || step == 0) { 
    541601                throw Components.results.NS_ERROR_INVALID_ARG; 
    542602        } 
  • trunk/chrome/content/common/overlayFunctions.js

    r334 r395  
    7070        var instantApply = DTA_preferences.get("browser.preferences.instantApply", false); 
    7171        window.openDialog( 
    72                 'chrome://dta/content/preferences/newPref.xul', 
     72                'chrome://dta/content/preferences/prefs.xul', 
    7373                'dtaPrefs', 
    7474                'chrome,titlebar,toolbar,resizable,centerscreen'+ (instantApply ? ',dialog=no' : '') 
     
    179179        _consoleService : null, 
    180180        _logPointer : null, 
    181         _loaded : false, 
    182         _load : function() { 
     181        load : function() { 
    183182                this._dumpEnabled = DTA_preferences.getDTA("logging", false); 
     183                if (!this._dumpEnabled) { 
     184                        this.dump = this._dumpStub; 
     185                        return; 
     186                } 
     187                this.dump = this._dump; 
    184