Show
Ignore:
Timestamp:
06/29/09 18:05:30 (4 years ago)
Author:
cassiano
Message:

Merged revisions 4909,4930-4932,4934-4935 via svnmerge from
http://svn.umitproject.org/svnroot/umit/trunk

................

r4909 | nopper | 2009-06-22 11:55:24 -0300 (Mon, 22 Jun 2009) | 21 lines


Merged revisions 4781-4783,4908 via svnmerge from
http://svn.umitproject.org/svnroot/umit/branch/UmitPlugins


........

r4781 | nopper | 2009-05-08 21:26:32 +0200 (ven, 08 mag 2009) | 1 line


Switching to new schema see UmitPlugins.xsd in PM branch. Switched also from xml.minidom to sax to speed up things.

........

r4782 | nopper | 2009-05-09 16:11:38 +0200 (sab, 09 mag 2009) | 1 line


Switched update process to new xml schema file.

........

r4783 | nopper | 2009-05-09 17:02:06 +0200 (sab, 09 mag 2009) | 1 line


Updating documentation to the new schema

........

r4908 | nopper | 2009-06-22 16:43:59 +0200 (lun, 22 giu 2009) | 1 line


Fixing a typo

........

................

r4930 | luis | 2009-06-27 11:33:59 -0300 (Sat, 27 Jun 2009) | 1 line


Fixing #334 - import error when umit is installed from package

................

r4931 | luis | 2009-06-27 22:38:54 -0300 (Sat, 27 Jun 2009) | 1 line


Fixed #331 - Permission denied writing umit config file

................

r4932 | luis | 2009-06-27 23:09:05 -0300 (Sat, 27 Jun 2009) | 1 line


Typo in Flow Analyzer plugin

................

r4934 | luis | 2009-06-27 23:30:31 -0300 (Sat, 27 Jun 2009) | 3 lines


Initialized merge tracking via "svnmerge" with revisions "1-4699" from
http://svn.umitproject.org/svnroot/umit/branch/radialnet

................

r4935 | ignotus | 2009-06-27 23:54:28 -0300 (Sat, 27 Jun 2009) | 3 lines


Fix accents problem in header.

................

Location:
branch/QuickScan
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • branch/QuickScan

    • Property svnmerge-integrated changed from /trunk:1-4792 to /trunk:1-4937
  • branch/QuickScan/umit/plugin/Update.py

    r4240 r4946  
    2222try: 
    2323    from hashlib import md5 
     24    from hashlib import sha1 as sha 
    2425except ImportError: 
    2526    from md5 import md5 
     27    from sha import sha 
    2628 
    2729from threading import RLock 
    2830from tempfile import mkstemp 
     31from StringIO import StringIO 
    2932from xml.dom.minidom import parseString 
    3033 
     
    4750FILE_CHECKING = 7 
    4851 
    49 class UpdateObject(object): 
     52from xml.sax import handler, make_parser 
     53 
     54class Update(object): 
     55    def __init__(self, version, description, url, integrity): 
     56        self.version, self.description, self.url, self.integrity = \ 
     57            version, description, url, integrity 
     58 
     59class UpdateObject(handler.ContentHandler): 
    5060    def __init__(self, obj): 
     61        self.data = '' 
     62        self.parse_phase = 0 
     63        self.updates = [] 
     64 
     65        self.version = '' 
     66        self.description = '' 
     67        self.url = [] 
     68        self.integrity = {} 
     69 
    5170        self.buffer = [] 
    52          
     71 
    5372        self.status = STATUS_IDLE 
    54          
     73 
    5574        self.label = None 
    5675        self.fract = None 
    57          
    58         self.url = None 
    59         self.version = None 
    60         self.hash = None 
    61          
     76 
    6277        self.object = obj 
    63          
     78 
    6479        self.fd = None 
    65          
     80 
    6681        self.size = None 
    6782        self.total = None 
    6883 
     84        self.last_update_idx = 0 
     85        self.selected_update_idx = -1 
     86 
    6987        # Simple lock for sync 
    7088        self.lock = RLock() 
    7189 
    7290    def parse_latest_file(self): 
    73         """ 
    74         @return url, version or None, None on error 
    75         """ 
    76  
    77         try: 
    78             doc = parseString("".join(self.buffer)) 
    79              
    80             if doc.documentElement.tagName != 'UmitPluginUpdate': 
    81                 raise Exception("Not valid xml file.") 
    82  
    83             url, version, hash = None, None, None 
    84  
    85             for node in doc.documentElement.childNodes: 
    86                 if node.nodeName == 'update-uri': 
    87                     url = node.firstChild.data 
    88                 if node.nodeName == 'version': 
    89                     version = node.firstChild.data 
    90                 if node.nodeName == 'md5': 
    91                     hash = node.firstChild.data 
    92  
    93             return url, version, hash 
    94         except Exception, exc: 
    95             log.warning("__parse_xml: %s" % exc) 
    96             return None, None, None 
    97  
     91        parser = make_parser() 
     92        parser.setContentHandler(self) 
     93        parser.parse(StringIO("".join(self.buffer))) 
     94 
     95    def startElement(self, name, attrs): 
     96        if name == 'UmitPluginUpdate' and self.parse_phase == 0: 
     97            self.parse_phase = 1 
     98        elif name == 'update' and self.parse_phase == 1: 
     99            self.parse_phase = 2 
     100        elif name in ('version', 'description', 'url') and \ 
     101             self.parse_phase == 2: 
     102 
     103            self.parse_phase = 3 
     104        elif name == 'integrity' and self.parse_phase == 2 and \ 
     105             'type' in attrs.keys() and 'value' in attrs.keys(): 
     106 
     107            self.integrity[attrs.get('type')] =  attrs.get('value') 
     108        else: 
     109            self.data = '' 
     110 
     111    def characters(self, ch): 
     112        if self.parse_phase == 3: 
     113            self.data += ch 
     114 
     115    def endElement(self, name): 
     116        if name in ('version', 'description', 'url'): 
     117            val = getattr(self, name, None) 
     118 
     119            if isinstance(val, basestring): 
     120                setattr(self, name, self.data) 
     121            elif isinstance(val, list): 
     122                val.append(self.data) 
     123 
     124        elif name == 'update': 
     125            if self.version and self.url: 
     126                self.updates.append(Update(self.version, self.description, 
     127                                     self.url, self.integrity)) 
     128 
     129            self.version = '' 
     130            self.description = '' 
     131            self.url = [] 
     132            self.integrity = {} 
     133            self.parse_phase = 1 
     134            self.data = '' 
     135        else: 
     136            self.parse_phase -= 1 
     137            self.data = '' 
    98138 
    99139class UpdateEngine(object): 
     
    107147        self.static_lst = None 
    108148        self.updating = False 
    109      
     149 
    110150    def stop(self): 
    111151        "Mark as stopped" 
     
    127167 
    128168            self.__process_next() 
    129          
     169 
    130170        self.updating = True 
    131      
     171 
    132172    def start_download(self): 
    133173        """ 
     
    145185 
    146186            self.__process_next_download() 
    147              
     187 
    148188        self.updating = True 
    149      
     189 
    150190    def __process_next_download(self): 
    151191        """ 
     
    155195        if not self.update_lst: 
    156196            return 
    157          
     197 
    158198        obj = self.update_lst.pop(0) 
    159          
     199 
    160200        try: 
    161201            user_dir = os.path.join(Path.config_dir) 
    162202            filename = os.path.basename(obj.object.reader.get_path()) 
    163              
     203 
    164204            obj.fd = open(mkstemp(".part", filename, \ 
    165205                         os.path.join(user_dir, "plugins-download"))[1], "wb+") 
    166                           
    167             Network.get_url(obj.url, self.__process_plugin, obj) 
     206 
     207            Network.get_url( 
     208                # Maybe too long string? :P 
     209                obj.updates[obj.selected_update_idx].url[obj.last_update_idx], 
     210                self.__process_plugin, obj 
     211            ) 
    168212        except Exception, err: 
    169213            obj.status = FILE_ERROR 
    170214            obj.label = err 
    171215            obj.fract = None 
    172              
     216 
    173217            self.__process_next_download() 
    174      
     218 
     219    def __remove_file(self, obj): 
     220        try: 
     221            obj.fd.close() 
     222            os.remove(obj.fd.name) 
     223        except: 
     224            log.error('Error while removing temp %s file' % obj.fd.name) 
     225 
    175226    def __process_plugin(self, file, data, exc, obj): 
    176227        """ 
     
    182233 
    183234            try: 
    184                 obj.status = FILE_ERROR 
    185                 obj.label = exc.reason 
    186                 obj.fract = 1 
    187                  
     235                if obj.last_update_idx + 1 < \ 
     236                   len(obj.updates[obj.selected_update_idx].url): 
     237 
     238                    obj.last_update_idx += 1 
     239 
     240                    obj.status = FILE_GETTING 
     241                    obj.label = _('Cycling to next update url. Waiting...') 
     242                else: 
     243                    obj.status = FILE_ERROR 
     244                    obj.label = _('Download failed: %s') % str(exc.reason) 
     245                    obj.fract = 1 
     246 
     247                self.__remove_file(obj) 
     248 
    188249                self.__process_next_download() 
    189250                return 
    190251            finally: 
    191252                obj.lock.release() 
    192          
     253 
    193254        elif isinstance(exc, StopNetException): 
    194             if obj.hash: 
     255            #TODO: CHECK THIS 
     256            if obj.updates[obj.selected_update_idx].integrity: 
    195257 
    196258                data = "" 
     
    200262                    obj.label = _('Checking validity ...') 
    201263                    obj.status = FILE_CHECKING 
    202                  
     264 
    203265                    obj.fd.flush() 
    204266                    obj.fd.seek(0) 
     
    207269                finally: 
    208270                    obj.lock.release() 
    209                  
     271 
    210272                # Not locked it could freeze the ui 
    211                 hasher = md5(data) 
    212                  
     273                md5_hash = sha_hash = None 
     274                sums = obj.updates[obj.selected_update_idx].integrity 
     275 
     276                if 'md5' in sums: 
     277                    md5_hash = md5(data) 
     278                if 'sha1' in sums: 
     279                    sha_hash = sha(data) 
     280 
    213281                obj.lock.acquire() 
    214282 
    215283                try: 
    216                     if hasher.hexdigest() == obj.hash: 
     284                    if (md5_hash and md5_hash.hexdigest() == sums['md5']) or \ 
     285                       (sha_hash and sha_hash.hexdigest() == sums['sha1']): 
     286 
    217287                        obj.label = _('Updated. Restart to take effect') 
    218288                        obj.status = FILE_GETTED 
     
    231301                finally: 
    232302                    obj.lock.release() 
    233              
     303 
    234304            obj.lock.acquire() 
    235305 
     
    239309            finally: 
    240310                obj.lock.release() 
    241              
     311 
    242312            try: 
    243313                if obj.status == FILE_ERROR: 
     
    249319                # TODO: add more sensed control? 
    250320                pass 
    251              
     321 
    252322            self.__process_next() 
    253          
     323 
    254324        elif isinstance(exc, StartNetException): 
    255325            obj.lock.acquire() 
     
    262332                except: 
    263333                    pass 
    264              
     334 
    265335                obj.label = _('Downloading ...') 
    266336            finally: 
     
    272342                obj.fract = float(obj.size) / float(obj.total) 
    273343            obj.fd.write(data) 
    274      
     344 
    275345    def __process_next(self): 
    276346        """ 
     
    280350        if not self.update_lst: 
    281351            return 
    282          
     352 
    283353        obj = self.update_lst.pop(0) 
    284         Network.get_url("%s/latest.xml" % obj.object.reader.update, \ 
     354        obj.label = _('Downloading update information...') 
     355 
     356        Network.get_url("%s/latest.xml" % \ 
     357                        obj.object.reader.update[obj.last_update_idx], \ 
    285358                        self.__process_manifest, obj) 
    286359 
     
    295368 
    296369            try: 
    297                 obj.status = LATEST_ERROR 
    298                 obj.label = _('Cannot find newer version (%s)') % exc.reason 
    299                  
     370                if obj.last_update_idx + 1 < len(obj.object.reader.update): 
     371                    obj.last_update_idx += 1 
     372 
     373                    obj.status = LATEST_GETTING 
     374                    obj.label = _('Cycling to next update url. Waiting...') 
     375 
     376                    self.update_lst.append(obj) 
     377                elif isinstance(exc, ErrorNetException): 
     378                    obj.status = LATEST_ERROR 
     379                    obj.label = _('Cannot find newer version (%s)') % exc.reason 
     380 
    300381                self.__process_next() 
    301382                return 
    302383            finally: 
    303384                obj.lock.release() 
    304          
     385 
    305386        elif isinstance(exc, StopNetException): 
    306             url, version, hash = obj.parse_latest_file() 
    307  
    308             new_v = Version(version) 
    309             cur_v = Version(obj.object.reader.version) 
    310  
     387            try: 
     388                obj.parse_latest_file() 
     389            except Exception, exc: 
     390 
     391                if obj.last_update_idx + 1 < len(obj.object.reader.update): 
     392                    obj.last_update_idx += 1 
     393 
     394                    obj.status = LATEST_GETTING 
     395                    obj.label = _('Cycling to next update url. Waiting...') 
     396 
     397                    self.update_lst.append(obj) 
     398                else: 
     399                    obj.status = LATEST_ERROR 
     400                    obj.label = _('Cannot find newer version (%s)') % str(exc) 
     401 
     402                self.__process_next() 
     403                return 
     404 
     405            version = None 
    311406            type = -1 # -1 no action / 0 update / 1 downgrade 
    312407 
    313             if new_v > cur_v: 
    314                 type = 0 
    315             elif cur_v < new_v: 
    316                 type = 1 
     408            # If we have only 1 update.. 
     409            if len(obj.updates) == 1: 
     410                version = obj.updates[0].version 
     411 
     412                new_v = Version(version) 
     413                cur_v = Version(obj.object.reader.version) 
     414 
     415                if new_v > cur_v: 
     416                    type = 0 
     417                elif cur_v < new_v: 
     418                    type = 1 
    317419 
    318420            obj.lock.acquire() 
    319421 
    320422            try: 
    321                 if url and version and type >= 0: 
     423                if obj.updates: 
    322424 
    323425                    # We check if the path is the plugins in config_dir 
     
    330432                        obj.status = LATEST_ERROR 
    331433 
    332                         if not type: 
    333                             obj.label = _('Version %s avaiable but need manual update.') % version 
    334                         else: 
    335                             obj.label = _('Version %s avaiable but need manual downgrade.') % version 
     434                        if type == -1: 
     435                            obj.label = _('Various versions available but require manual intervention.') 
     436                        elif type == 0: 
     437                            obj.label = _('Version %s available but need manual update.') % version 
     438                        elif type == 1: 
     439                            obj.label = _('Version %s available but need manual downgrade.') % version 
    336440                    else: 
    337441                        obj.status = LATEST_GETTED 
    338                         obj.label = _('Version %s avaiable.') % version 
    339                      
    340                     obj.version = version 
    341                     obj.url = url 
    342                     obj.hash = hash 
     442                        if type == -1: 
     443                            obj.label = _('Various versions available') 
     444                        else: 
     445                            obj.label = _('Version %s available.') % version 
     446 
    343447                else: 
    344448                    obj.status = LATEST_ERROR 
     
    355459        elif not exc: 
    356460            obj.buffer.append(data) 
    357      
     461 
    358462    def get_list(self): 
    359463        "Getter for list" 
    360464        return self.static_lst 
    361      
     465 
    362466    def set_list(self, value): 
    363467        "Setter for list" 
    364468        lst = [] 
    365          
     469 
    366470        for iter in value: 
    367471            if isinstance(iter, UpdateObject): 
     
    369473            else: 
    370474                lst.append(UpdateObject(iter)) 
    371                  
     475 
    372476        self.update_lst = lst 
    373477        self.static_lst = tuple(self.update_lst) 
    374          
     478 
    375479    list = property(get_list, set_list) 
     480 
     481if __name__ == "__main__": 
     482    parser = make_parser() 
     483    loader = UpdateObject(1) 
     484    parser.setContentHandler(loader) 
     485    parser.parse(open('test.xml')) 
     486    print loader.updates