Changeset 4909

Show
Ignore:
Timestamp:
06/22/09 14:55:24 (4 years ago)
Author:
nopper
Message:

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

........

Location:
trunk
Files:
22 modified

Legend:

Unmodified
Added
Removed
  • trunk

    • Property svnmerge-integrated changed from /branch/InterfaceEditor:1-4362 /branch/NetworkInventory:1-3849,3851-3864,3876-3919,3921-3948,3953-3955,3957-4289 /branch/UmitPlugins:1-2993,2997-2998,3008,3010-3011,3013-3015,3029-3031,3034-3073,3077-3086,3088,3091-3092,3098-3100,3105-3108,3110,3112,3120-3125,3128,3130-3131,3133,3135-3141,3143-3151,3153-3232,3234-3789,3792-4383,4385-4387,4389-4423,4425-4443,4445-4745 to /branch/InterfaceEditor:1-4362 /branch/NetworkInventory:1-3849,3851-3864,3876-3919,3921-3948,3953-3955,3957-4289 /branch/UmitPlugins:1-2993,2997-2998,3008,3010-3011,3013-3015,3029-3031,3034-3073,3077-3086,3088,3091-3092,3098-3100,3105-3108,3110,3112,3120-3125,3128,3130-3131,3133,3135-3141,3143-3151,3153-3232,3234-3789,3792-4383,4385-4387,4389-4423,4425-4443,4445-4908
  • trunk/higwidgets/higrichlists.py

    r4243 r4909  
    9090 
    9191        return True 
    92      
     92 
    9393    def do_realize(self): 
    9494        gtk.EventBox.do_realize(self) 
     
    9999           (evt.type == gtk.gdk._2BUTTON_PRESS) and \ 
    100100           (self.tree.change_selection(self)): 
    101              
     101 
    102102            self.active = True 
    103103            self.emit('clicked') 
     
    162162        self.enabled = self._reader.enabled 
    163163        self.connect('activate', self.__on_activate) 
    164          
     164 
    165165        self.show_all() 
    166166 
    167167        self.progressbar.hide() 
    168168        self.box_act.hide() 
    169         self.include_button.hide() 
     169        self.versions_button.hide() 
    170170 
    171171    def __create_widgets(self): 
     
    174174        self.label = gtk.Label('') 
    175175        self.label.set_ellipsize(pango.ELLIPSIZE_END) 
    176          
    177         self.include_button = gtk.CheckButton(_('Include update')) 
     176 
     177        self.versions_model = gtk.ListStore(str, str) 
     178        self.versions_button = gtk.ComboBox(self.versions_model) 
     179 
     180        rend = gtk.CellRendererPixbuf() 
     181        self.versions_button.pack_start(rend, False) 
     182        self.versions_button.add_attribute(rend, 'stock-id', 0) 
     183 
     184        rend = gtk.CellRendererText() 
     185        self.versions_button.pack_end(rend) 
     186        self.versions_button.add_attribute(rend, 'text', 1) 
    178187 
    179188        self.img_play = gtk.image_new_from_stock(gtk.STOCK_MEDIA_PLAY, \ 
     
    197206 
    198207        vbox = gtk.VBox(False, 2) 
    199          
     208 
    200209        mhbox = gtk.HBox(False, 2) 
    201210        self.label.set_alignment(0, 0.5) 
    202          
     211 
    203212        mhbox.pack_start(self.label) 
    204         mhbox.pack_start(self.include_button, False, False) 
    205          
     213 
     214        minibox = gtk.VBox() 
     215        minibox.pack_start(self.versions_button, False, False, 0) 
     216 
     217        mhbox.pack_start(minibox, False, False) 
     218 
    206219        vbox.pack_start(mhbox) 
    207220        vbox.pack_start(self.progressbar, False, False, 0) 
     
    285298    def get_message(self): 
    286299        return self._message 
    287      
     300 
    288301    def set_message(self, value): 
    289302        """ 
    290303        If not defined don't update 
    291304        """ 
    292          
     305 
    293306        if value is not None: 
    294307            self._message = value 
    295              
     308 
    296309            # Used to update the label 
    297310            self.enabled = self.enabled 
     
    314327            self.progressbar.set_text('%d %%' % int(val * 100)) 
    315328            self.progressbar.show() 
    316      
     329 
    317330    def get_include(self): 
    318331        if self._show_include: 
    319             return self.include_button.get_active() 
     332            id = self.versions_button.get_active() -1 
     333 
     334            if id >= 0: 
     335                return True 
    320336        else: 
    321337            return False 
    322      
     338 
    323339    def set_include(self, value): 
    324340        self._show_include = value 
    325          
     341 
    326342        if value: 
    327             self.include_button.show() 
    328         else: 
    329             self.include_button.hide() 
     343            self.versions_button.show() 
     344        else: 
     345            self.versions_button.hide() 
    330346 
    331347    def get_activatable(self): 
     
    365381 
    366382        gtk.ScrolledWindow.__init__(self) 
    367          
     383 
    368384        self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) 
    369385        self.set_shadow_type(gtk.SHADOW_ETCHED_IN) 
     
    413429 
    414430        self.vbox.foreach(remove, self.vbox) 
    415      
     431 
    416432    def get_rows(self): 
    417433        return len(self.vbox) 
  • trunk/share/doc/umit/src/plugins_dev.rst

    r4746 r4909  
    4646The entire plugin system is based on the ``Manifest.xml`` file previously introduceed. This file is responsible to provide information to the Plugin Engine. These information are provided trough an xml file. 
    4747 
    48 You could add you custom elements to the xml file but someone are reserved by UMIT Plugin system: 
    49  
    50    +--------------------+-------------------------------------------------------+ 
    51    | Element            |                                                       | 
    52    +====================+=======================================================+ 
    53    | ``<needs>``        | A list (``VersionString``) of needed virtual plugins  | 
    54    |                    | that must be already loaded to enable the target      | 
    55    |                    | plugin.                                               | 
    56    +--------------------+-------------------------------------------------------+ 
    57    | ``<conflicts>``    | A list (``VersionString``) of conflicting virtual     | 
    58    |                    | plugins that must be **NOT** present to load the      | 
    59    |                    | target plugin.                                        | 
    60    +--------------------+-------------------------------------------------------+ 
    61    | ``<provides>``     | A list (``VersionString``) of exported virtual names  | 
    62    |                    | that the target plugin provides to the others.        | 
    63    +--------------------+-------------------------------------------------------+ 
    64    | ``<start-file>``   | A string pointing to the main file in ``bin/``        | 
    65    |                    | directory.                                            | 
    66    +--------------------+-------------------------------------------------------+ 
    67    | ``<url>``          |A string (URL) pointing to the target plugins homepage.| 
    68    +--------------------+-------------------------------------------------------+ 
    69    | ``<author>``       | A string representing the name of the plugin's author.| 
    70    +--------------------+-------------------------------------------------------+ 
    71    | ``<license>``      | A string representing the license used for the plugin.| 
    72    +--------------------+-------------------------------------------------------+ 
    73    | ``<name>``         | A *non-operator* ``VersionString`` describing the     | 
    74    |                    | plugin.                                               | 
    75    +--------------------+-------------------------------------------------------+ 
    76    | ``<update>``       | A string (URL) pointing to the target plugins update  | 
    77    |                    | directory.                                            | 
    78    +--------------------+-------------------------------------------------------+ 
    79    | ``<description>``  | A string containing a description of the plugin.      | 
    80    +--------------------+-------------------------------------------------------+ 
    81    | ``<version>``      | A string represetnting the plugin version.            | 
    82    +--------------------+-------------------------------------------------------+ 
    83    | ``<contributors>`` | A list of plugin's contributors.                      | 
    84    +--------------------+-------------------------------------------------------+ 
    85    | ``<translators>``  | A list of plugin's translators.                       | 
    86    +--------------------+-------------------------------------------------------+ 
    87    | ``<artists>``      | A list of plugin's artists.                           | 
    88    +--------------------+-------------------------------------------------------+ 
     48You could add you custom elements to the xml file but someone are reserved by UMIT Plugin system (Elements marked with * could compare several times in the Manifest file): 
     49 
     50   +---------------------+---------------------------------------------------------------------+ 
     51   | /UmitPlugin         | Description                                                         | 
     52   +=====================+=====================================================================+ 
     53   | ``<name>``          | A string representing the plugin name.                              | 
     54   +---------------------+---------------------------------------------------------------------+ 
     55   | ``<version>``       | A string represetnting the plugin version.                          | 
     56   +---------------------+---------------------------------------------------------------------+ 
     57   | ``<description>``   | A string containing a description of the plugin.                    | 
     58   +---------------------+---------------------------------------------------------------------+ 
     59   | ``<url>``           | A URI string pointing to the target plugins homepage.               | 
     60   +---------------------+---------------------------------------------------------------------+ 
     61   | ``<runtime>``       | Required.                                                           | 
     62   +---------------------+---------------------------------------------------------------------+ 
     63   | ``<deptree>``       | Optional.                                                           | 
     64   +---------------------+---------------------------------------------------------------------+ 
     65   | ``<credits>``       | Required.                                                           | 
     66   +---------------------+---------------------------------------------------------------------+ 
     67 
     68``<runtime>`` description: 
     69 
     70   +---------------------+---------------------------------------------------------------------+ 
     71   | /UmitPlugin/runtime | Description                                                         | 
     72   +=====================+=====================================================================+ 
     73   | ``<start_file>``    | A string pointing to the main file in ``bin/`` directory.           | 
     74   +---------------------+---------------------------------------------------------------------+ 
     75   | ``<update>`` *      | A URI string pointing to the target plugins update remote location. | 
     76   |                     | In a manifest you could provide multiple ``<update>`` elements for  | 
     77   |                     | mirroring reasons. Optional.                                        | 
     78   +---------------------+---------------------------------------------------------------------+ 
     79 
     80``<deptree>`` description (all elements are optional here): 
     81 
     82   +---------------------+---------------------------------------------------------------------+ 
     83   | /UmitPlugin/deptree | Description                                                         | 
     84   +=====================+=====================================================================+ 
     85   | ``<provide>`` *     | A ``VersionString`` that describes what the target plugin provides  | 
     86   |                     | to the others. Example ``=ftplib-1.0`` or ``=trayicon-2.0``.        | 
     87   +---------------------+---------------------------------------------------------------------+ 
     88   | ``<need>`` *        | A ``VersionString`` of a needed virtual plugin that must be loaded  | 
     89   |                     | in order to enable the target plugin.                               | 
     90   +---------------------+---------------------------------------------------------------------+ 
     91   | ``<conflict>`` *    | A ``VersionString`` of a conflicting virtual plugin that must be    | 
     92   |                     | **NOT** loaded in order to enable the target plugin.                | 
     93   +---------------------+---------------------------------------------------------------------+ 
     94 
     95``credits`` description: 
     96 
     97   +---------------------+---------------------------------------------------------------------+ 
     98   | /UmitPlugin/credits | Description                                                         | 
     99   +=====================+=====================================================================+ 
     100   | ``<license>`` *     | A string representing the license used for the plugin.              | 
     101   +---------------------+---------------------------------------------------------------------+ 
     102   | ``<copyright>`` *   | A string representing the copyright information for plugin.         | 
     103   +---------------------+---------------------------------------------------------------------+ 
     104   | ``<author>`` *      | A string representing a plugin's author.                            | 
     105   +---------------------+---------------------------------------------------------------------+ 
     106   | ``<contributor>`` * | A string representing a plugin's contributor. Optional.             | 
     107   +---------------------+---------------------------------------------------------------------+ 
     108   | ``<translator>`` *  | A string representing a plugin's translator. Optional.              | 
     109   +---------------------+---------------------------------------------------------------------+ 
     110   | ``<artist>`` *      | A string representing a plugin's artist. Optional.                  | 
     111   +---------------------+---------------------------------------------------------------------+ 
     112 
     113 
     114UmitPlugin element could have also an attribute called type to indicate if the plugin is a UI addition or just a library. You could have respectively ``<UmitPlugin .. type="ui">`` or ``<UmitPlugin .. type="lib">``. 
    89115 
    90116Following an example of a Manifest.xml:: 
    91117 
    92     <?xml version="1.0" ?> 
    93     <UmitPlugin> 
    94       <url>http://www.umitproject.org</url> 
    95       <conflicts></conflicts> 
    96       <provides>&gt;=SystemInfo-1.0</provides> 
    97       <needs></needs><type></type> 
    98       <start_file>main</start_file> 
     118    <?xml version="1.0" encoding="utf-8"?> 
     119    <UmitPlugin xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.umitproject.org" xsi:schemaLocation="http://www.umitproject.org UmitPlugins.xsd" type="ui"> 
    99120      <name>SystemInfo</name> 
    100121      <version>0.1</version> 
    101122      <description>A plugin that provides info about the system</description> 
    102       <author>Francesco Piccinno</author> 
    103       <license>GPL</license> 
    104       <update>http://localhost/~stack/plugins/systeminfo</update> 
     123      <url>http://blog.archpwn.org</url> 
     124      <runtime> 
     125        <start_file>main</start_file> 
     126        <update>http://localhost/mia/</update> 
     127        <update>http://localhost/</update> 
     128      </runtime> 
     129      <deptree> 
     130        <provide>&gt;=SystemInfo-1.0</provide> 
     131      </deptree> 
     132      <credits> 
     133        <license>GPL</license> 
     134        <copyright>(C) 2009 Adriano Monteiro Marques</copyright> 
     135        <author>Francesco Piccinno</author> 
     136      </credits> 
    105137    </UmitPlugin> 
    106138 
     
    108140^^^^^^^^^^^^^^ 
    109141 
    110 Elements like ``<needs>`` , ``<conflicts>`` , ``<provides>`` and ``<name>`` are ``VersionString`` elements. 
     142Elements like ``<need>`` , ``<conflict>`` , ``<provide>`` are ``VersionString`` elements. 
    111143 
    112144EBNF/regex form for op and *non-operator* ``VersionString`` is:: 
     
    144176 
    145177   +--------------------+-------------------------------------------------------+ 
    146    | Element            |                                                       | 
     178   | /UmitPluginUpdate  | Description                                           | 
    147179   +====================+=======================================================+ 
    148    | ``<update-uri>``   | A string (URL) pointing to the new version of the     | 
     180   | ``<version>``      | A *non-operative* ``VersionString`` like for Manifest.| 
     181   +--------------------+-------------------------------------------------------+ 
     182   | ``<desciption>``   | A string representing a description of the update or  | 
     183   |                    | a changelog. Optional.                                | 
     184   +--------------------+-------------------------------------------------------+ 
     185   | ``<url>`` *        | A string (URL) pointing to the new version of the     | 
    149186   |                    | plugin.                                               | 
    150187   +--------------------+-------------------------------------------------------+ 
    151    | ``<version>``      | A *non-operative* ``VersionString`` like for Manifest.| 
     188   | ``<integrity>`` *  | This element is optional and could compare several    | 
     189   |                    | times. You have to set also ``<type>`` and            | 
     190   |                    | ``value`` attribute. Example:                         | 
     191   |                    | ``<integrity type="sha1" value="yourhexdigest"/>``    | 
    152192   +--------------------+-------------------------------------------------------+ 
    153    | ``<md5>``          | This element is optional and contains the MD5 hex     | 
    154    |                    | digest string used for integrity check on the         | 
    155    |                    | downloaded file (the ``<update-uri>`` file).          | 
    156    +--------------------+-------------------------------------------------------+ 
    157193 
    158194An example of the ``latest.xml`` follows:: 
    159195 
    160     <UmitPluginUpdate> 
    161         <update-uri>http://localhost/~stack/plugins/systeminfo/SystemInfo.ump</update-uri> 
    162         <version>2.0.0</version> 
    163         <md5>c7487b08545f58999512f6155852050e</md5> 
     196    <UmitPluginUpdate xmlns="http://www.umitproject.org" xsi:schemaLocation="http://www.umitproject.org UmitPlugins.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
     197        <update> 
     198            <version>2.0</version> 
     199            <description>Don't use this is only there for testing.</description> 
     200            <url>http://localhost/test.ump</url> 
     201        </update> 
     202        <update> 
     203            <version>0.1</version> 
     204            <description>&lt;tt&gt;Changelog: 
     205    &lt;b&gt;* Version 1.0&lt;/b&gt;: 
     206    - Fixed blah 
     207    - Fixed blah 
     208    - Fixed blah 
     209    - Fixed blah&lt;/tt&gt;</description> 
     210            <url>http://localhost/system.ump</url> 
     211            <integrity type="md5" value="d488cbec9b6a3de7de1502ab962a907a"/> 
     212            <integrity type="sha1" value="1851a284568c2fa5fab81384559a3e945b1f2744"/> 
     213        </update> 
    164214    </UmitPluginUpdate> 
    165  
    166215 
    167216API Reference 
     
    251300   That returns an instance of the class *classname* (optional) of the plugin that provides *needstr* or the respective module if *need_module* is True, or None on error. 
    252301    
    253    For example taking a look to the setup.py of Notifier plugin we could see that the autogenerated ``Manifest.xml`` will have the ``<needs>`` element set to ``>=tray-2.0``. Assuming that we have already loaded the TrayPlugin that's taking care of providing ``=tray-2.0`` in his ``<provides>`` element in the Manifest file, we will have something like that:: 
     302   For example taking a look to the setup.py of Notifier plugin we could see that the autogenerated ``Manifest.xml`` will have the ``<need>`` element set to ``>=tray-2.0``. Assuming that we have already loaded the TrayPlugin that's taking care of providing ``=tray-2.0`` in his ``<provide>`` element in the Manifest file, we will have something like that:: 
    254303 
    255304        DEBUG - 2009-04-25 11:26:35,422 - >>> Core.get_need() -> [<main.TrayPlugin object at 0xa4c986c>] (module: False) 
     
    492541        name='helloworld', 
    493542        version='1.0', 
    494         author='Francesco Piccinno', 
     543        author=['Francesco Piccinno'], 
    495544        url='http://www.umitproject.org', 
    496         #update='http://localhost/~stack/plugins/dummywork', 
     545        #update=['http://localhost/~stack/plugins/dummywork'], 
     546        license=['GPL'], 
     547        copyright=['(C) 2009 Francesco Piccinno'], 
    497548        scripts=['sources/main.py'], 
    498549        start_file="main", 
     
    534585    running install_egg_info 
    535586    >> Creating plugin 
    536     Field url setted to http://www.umitproject.org 
    537     Field conflicts setted to 
    538     Field provides setted to =helloworld-1.0 
    539     Field needs setted to 
    540     Field type setted to 
    541     Field start_file setted to main 
    542     Field name setted to helloworld 
    543     Field version setted to 1.0 
    544     Field description setted to Say hello to world! 
    545     Field author setted to Francesco Piccinno 
    546     Field license setted to 
    547     Field artist setted to 
    548     Field copyright setted to 
    549     Field update setted to 
    550587    Adding file bin main.py bin 
    551588    Adding file data logo.png data 
  • trunk/source-plugins/context-menu/setup.py

    r4255 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    2424    name='Context menu', 
    2525    version='1.0', 
    26     author='Francesco Piccinno', 
    27     url='http://snippets.pornosecurity.org', 
     26    author=['Francesco Piccinno'], 
     27    url='http://blog.archpwn.org', 
     28    license=['GPL'], 
     29    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    2830    start_file='main', 
    29     provides='=context-menu-1.0', 
     31    provide=['=context-menu-1.0'], 
    3032    description='a context menu for host list', 
    3133    scripts=['sources/main.py'], 
  • trunk/source-plugins/dummy-working/setup.py

    r4255 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    2424    name='dummy-working', 
    2525    version='1.0', 
    26     author='Francesco Piccinno', 
    27     url='http://snippets.pornosecurity.org', 
    28     update='http://localhost/~stack/plugins/dummywork', 
     26    author=['Francesco Piccinno'], 
     27    url='http://blog.archpwn.org', 
     28    update=['http://localhost/~stack/plugins/dummywork'], 
     29    license=['GPL'], 
     30    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    2931    scripts=['sources/main.py'], 
    3032    start_file="main", 
    3133    data_files=[('data', ['dist/logo.png'])], 
    32     provides='=dummy-1.0', 
     34    provide=['=dummy-1.0'], 
    3335    description='a dummy plugin (working)', 
    3436    package_dir={'dummy' : 'sources/dummy'}, 
  • trunk/source-plugins/flow-analyzer/setup.py

    r4255 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    2424    name='Flow Analyzer', 
    2525    version='1.0', 
    26     author='Francesco Piccinno', 
    27     url='http://snippets.pornosecurity.org', 
     26    author=['Francesco Piccinno'], 
     27    url='http://blog.archpwn.org', 
    2828    start_file='main', 
    29     provides='=flow-analyzer-1.0', 
     29    provide=['=flow-analyzer-1.0'], 
    3030    description='a simple plugin that analyze parsed XML file from nmap', 
     31    license=['GPL'], 
     32    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    3133    scripts=['sources/main.py'], 
    3234    data_files=[('data', ['dist/logo.png'])], 
  • trunk/source-plugins/localized-example/setup.py

    r4255 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    3333    name='Localize-Example', 
    3434    version='1.0', 
    35     author='Francesco Piccinno', 
    36     url='http://snippets.pornosecurity.org', 
     35    author=['Francesco Piccinno'], 
     36    url='http://blog.archpwn.org', 
    3737    scripts=['sources/main.py'], 
    3838    start_file="main", 
    3939    data_files=[('data', ['dist/logo.png'])] + mo_files, 
    40     provides='=localize-1.0', 
     40    provide=['=localize-1.0'], 
    4141    description='a localized plugin for testing', 
     42    license=['GPL'], 
     43    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    4244    output='Localize.ump' 
    4345) 
  • trunk/source-plugins/notifier/setup.py

    r4592 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    2424    name='Notifier', 
    2525    version='0.1', 
    26     author='Francesco Piccinno', 
     26    author=['Francesco Piccinno'], 
    2727    url='http://blog.archpwn.org', 
    2828    start_file='main', 
    29     needs='>=tray-2.0', 
     29    need=['>=tray-2.0'], 
    3030    description='This plugin will warn you trough ballons or notification that a scan has finished', 
     31    license=['GPL'], 
     32    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    3133    data_files=[('data', ['dist/logo.png'])], 
    3234    scripts=['sources/main.py'], 
  • trunk/source-plugins/system-info-consumer/setup.py

    r4255 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    2424    name='SystemInfo-Consumer', 
    2525    version='0.1', 
    26     author='Francesco Piccinno', 
    27     url='http://snippets.pornosecurity.org', 
     26    author=['Francesco Piccinno'], 
     27    url='http://blog.archpwn.org', 
    2828    start_file='main', 
    29     needs='>=SystemInfo-0.1', 
     29    need=['>=SystemInfo-0.1'], 
    3030    description='A plugin that use SystemInfo <i>calls</i>', 
     31    license=['GPL'], 
     32    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    3133    data_files=[('data', ['dist/logo.png'])], 
    3234    scripts=['sources/main.py'], 
  • trunk/source-plugins/system-info/setup.py

    r4255 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    2424    name='SystemInfo', 
    2525    version='0.1', 
    26     author='Francesco Piccinno', 
    27     url='http://snippets.pornosecurity.org', 
    28     update='http://localhost/~stack/plugins/systeminfo', 
     26    author=['Francesco Piccinno'], 
     27    url='http://blog.archpwn.org', 
     28    update=['http://localhost/mia/', 'http://localhost/'], 
    2929    start_file='main', 
    30     provides='>=SystemInfo-1.0', 
     30    provide=['>=SystemInfo-1.0'], 
    3131    description='A plugin that provides info about the system', 
     32    license=['GPL'], 
     33    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    3234    scripts=['sources/main.py'], 
    3335    data_files=[('data', ['dist/logo.png'])], 
  • trunk/source-plugins/tabber/setup.py

    r4255 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    134134    name='Tabber', 
    135135    version='1.0', 
    136     author='Francesco Piccinno (code ripped from PIDA)', 
    137     url='http://snippets.pornosecurity.org', 
     136    author=['Francesco Piccinno (code ripped from PIDA)'], 
     137    url='http://blog.archpwn.org', 
    138138    start_file='main', 
    139     provides='=Tabber-1.0', 
     139    provide=['=Tabber-1.0'], 
    140140    description='Tabber provides docking functionality to UMIT UI (code ripped from PIDA)', 
     141    license=['GPL'], 
     142    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    141143    data_files=[('data', ['dist/logo.png'])], 
    142144    scripts=['sources/main.py'], 
  • trunk/source-plugins/terminal-pad/setup.py

    r4255 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    2424    name='Terminal', 
    2525    version='1.0', 
    26     author='Francesco Piccinno', 
    27     url='http://snippets.pornosecurity.org', 
     26    author=['Francesco Piccinno'], 
     27    url='http://blog.archpwn.org', 
    2828    start_file='main', 
    29     provides='=terminal-1.0', 
     29    provide=['=terminal-1.0'], 
    3030    description='A simple terminal page for UMIT (vte)', 
     31    license=['GPL'], 
     32    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    3133    scripts=['sources/main.py'], 
    3234    data_files=[('data', ['dist/logo.png'])], 
  • trunk/source-plugins/testcase/setup.py

    r4746 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    124124    name='TestCase', 
    125125    version='1.0', 
    126     author='Francesco Piccinno', 
     126    author=['Francesco Piccinno'], 
     127    license=['GPL'], 
     128    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    127129    url='http://blog.archpwn.org', 
    128130    scripts=['sources/main.py'], 
  • trunk/source-plugins/throbber/setup.py

    r4592 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Francesco Piccinno 
     3# Copyright (C) 2009 Francesco Piccinno 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    2424    name='ThrobberAnimation', 
    2525    version='1.0', 
    26     author='Francesco Piccinno', 
     26    author=['Francesco Piccinno'], 
    2727    url='http://blog.archpwn.org', 
    2828    scripts=['sources/main.py'], 
    2929    start_file="main", 
    3030    data_files=[('data', ['dist/logo.png', 'dist/throbber-16.gif'])], 
    31     provides='=ThrobberAnimation-1.0', 
     31    provide=['=ThrobberAnimation-1.0'], 
    3232    description='This plugin adds a throbber that\'s showed when a scan is running.', 
    33     license="GPL", 
    34     copyright="(C) 2009 - Francesco Piccinno", 
     33    license=["GPL"], 
     34    copyright=["(C) 2009 - Francesco Piccinno"], 
    3535    output='throbberanimation.ump' 
    3636) 
  • trunk/source-plugins/tray-icon/setup.py

    r4592 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    2424    name='Tray Icon', 
    2525    version='2.0', 
    26     author='Francesco Piccinno', 
     26    author=['Francesco Piccinno'], 
    2727    url='http://blog.archpwn.org', 
    2828    start_file='main', 
    29     provides='=tray-2.0', 
     29    provide=['=tray-2.0'], 
    3030    description='A simple tray icon for Umit', 
    3131    scripts=['sources/main.py'], 
     
    3333    package_dir={'notification' : 'sources/notification'}, 
    3434    packages=['notification'], 
    35     license='GPL', 
     35    license=['GPL'], 
     36    copyright=['(C) 2009 Adrian Monteiro Marques'], 
    3637    output='TrayIcon.ump' 
    3738) 
  • trunk/source-plugins/umit-console/setup.py

    r4255 r4909  
    11#!/usr/bin/env python 
    22# -*- coding: utf-8 -*- 
    3 # Copyright (C) 2008 Adriano Monteiro Marques 
     3# Copyright (C) 2009 Adriano Monteiro Marques 
    44# 
    55# Author: Francesco Piccinno <stack.box@gmail.com> 
     
    2424    name='Umit Console', 
    2525    version='1.0', 
    26     author='Francesco Piccinno', 
    27     url='http://snippets.pornosecurity.org', 
     26    author=['Francesco Piccinno'], 
     27    url='http://blog.archpwn.org', 
    2828    start_file='main', 
    29     needs='>=Tabber-1.0', 
     29    need=['>=Tabber-1.0'], 
    3030    description='a Python console for UMIT interacting', 
     31    license=['GPL'], 
     32    copyright=['(C) 2009 Adriano Monteiro Marques'], 
    3133    scripts=['sources/main.py'], 
    3234    package_dir={'console' : 'sources/console'}, 
  • trunk/umit/plugin/Containers.py

    r4746 r4909  
    2121import os 
    2222import os.path 
     23import sys 
    2324 
    2425from fnmatch import fnmatch 
    2526from zipfile import ZipFile, BadZipfile, ZIP_DEFLATED 
    26 from xml.dom.minidom import parseString, getDOMImplementation 
     27 
     28from StringIO import StringIO 
     29 
     30from xml.sax import handler, make_parser 
     31from xml.sax.saxutils import XMLGenerator 
     32from xml.sax.xmlreader import AttributesImpl 
     33 
    2734from tempfile import mktemp 
    2835 
     
    5562import shutil 
    5663 
    57 # FIXME: add others fields 
    58 FIELDS = ( 
    59     "url", 
    60     "conflicts", 
    61     "provides", 
    62     "needs", 
    63     "type", 
    64     "start_file", 
    65     "name", 
    66     "version", # only a convenient field 
    67     "description", 
    68     "author", 
    69     "license", 
    70     "artist", 
    71     "copyright", 
    72     "update" 
    73 ) 
    74  
    7564SIGNATURE = "UmitPlugin" 
     65 
     66class ManifestObject(object): 
     67    def __init__(self): 
     68 
     69        # Ok here we're using list object because py2.5 seems to not support 
     70        # index() for tuple. Stupid 2.5 :) 
     71 
     72        self.elements = [ 
     73            ['name', 'version', 'description', 'url'], 
     74            ['start_file', 'update'], 
     75            ['provide', 'need', 'conflict'], 
     76            ['license', 'copyright', 'author', 
     77             'contributor', 'translator', 'artist'] 
     78        ] 
     79 
     80        self.containers = [SIGNATURE, 'runtime', 'deptree', 'credits'] 
     81 
     82        self.name = '' 
     83        self.version = '' 
     84        self.description = '' 
     85        self.url = '' 
     86 
     87        self.start_file = '' 
     88        self.update = [] 
     89 
     90        self.provide = [] 
     91        self.need = [] 
     92        self.conflict = [] 
     93 
     94        self.license = [] 
     95        self.copyright = [] 
     96        self.author = [] 
     97        self.contributor = [] 
     98        self.translator = [] 
     99        self.artist = [] 
     100 
     101        self.attr_type = '' 
     102 
     103    def check_validity(self, use_print=False): 
     104        """ 
     105        Checks the fields presents and validity 
     106 
     107        @return True if it's ok 
     108        """ 
     109 
     110        # This fields should be present and not null 
     111        fields = ('name', 'version', 'description', 'url', 'start_file', 
     112                  'license', 'copyright', 'author') 
     113 
     114        for element in fields: 
     115            if not getattr(self, element, None): 
     116                txt = 'Element named %s should not be null.' % (element) 
     117 
     118                if use_print: 
     119                    print txt 
     120                else: 
     121                    log.warning(txt) 
     122 
     123                return False 
     124 
     125        return True 
     126 
     127    def get_provides(self): return self.provide 
     128    def get_conflicts(self): return self.conflict 
     129    def get_needs(self): return self.need 
     130 
     131    provides = property(get_provides) 
     132    conflicts = property(get_conflicts) 
     133    needs = property(get_needs) 
     134 
     135class ManifestLoader(handler.ContentHandler, ManifestObject): 
     136    def __init__(self): 
     137        ManifestObject.__init__(self) 
     138 
     139        self.element_idx = 0 
     140        self.parsing_pass = -1 
     141        self.current_element = None 
     142        self.data = None 
     143 
     144    def startElement(self, name, attrs): 
     145        try: 
     146            self.element_idx = self.elements[self.parsing_pass].index(name) 
     147            self.current_element = \ 
     148                self.elements[self.parsing_pass][self.element_idx] 
     149 
     150        except IndexError: 
     151            log.debug('Element named `%s` is not in %s' % \ 
     152                      (name, self.elements[self.parsing_pass])) 
     153 
     154        except ValueError: 
     155            try: 
     156                idx = self.containers.index(name) 
     157 
     158                if self.parsing_pass < idx: 
     159                    self.parsing_pass = idx 
     160                else: 
     161                    log.warning('Element `%s` is not valid at this point. ' \ 
     162                                'Should compare before %s' % (name, 
     163                                            self.containers[self.parsing_pass])) 
     164 
     165                if self.parsing_pass == 0: 
     166                    if type in attrs.keys(): 
     167                        self.attr_type = attrs.get('type') 
     168                    else: 
     169                        self.attr_type = 'ui' 
     170 
     171            except ValueError: 
     172                log.debug('Element named `%s` not excepted.' % name) 
     173 
     174    def characters(self, ch): 
     175        if not self.current_element: 
     176            return 
     177 
     178        if not self.data: 
     179            self.data = ch 
     180        else: 
     181            self.data += ch 
     182 
     183    def endElement(self, name): 
     184        if self.current_element == name: 
     185            try: 
     186                attr = getattr(self, name) 
     187 
     188                if isinstance(attr, basestring): 
     189                    setattr(self, name, self.data) 
     190                elif isinstance(attr, list): 
     191                    attr.append(self.data) 
     192            finally: 
     193                self.current_element = None 
     194                self.data = None 
     195 
     196class ManifestWriter(object): 
     197    def startElement(self, names, attrs): 
     198        self.depth_idx += 1 
     199        self.writer.characters('  ' * self.depth_idx) 
     200        self.writer.startElement(names, attrs) 
     201 
     202    def endElement(self, name): 
     203        self.writer.endElement(name) 
     204        self.writer.characters('\n') 
     205        self.depth_idx -= 1 
     206 
     207    def __init__(self, manifest): 
     208        assert isinstance(manifest, ManifestObject) 
     209 
     210        self.output = StringIO() 
     211        self.depth_idx = -1 
     212        self.manifest = manifest 
     213        self.writer = XMLGenerator(self.output, 'utf-8') 
     214        self.writer.startDocument() 
     215 
     216        attr_vals = { 
     217            'xmlns' : 'http://www.umitproject.org', 
     218            'xsi:schemaLocation' : 'http://www.umitproject.org UmitPlugins.xsd', 
     219            'xmlns:xsi' : 'http://www.w3.org/2001/XMLSchema-instance', 
     220            'type' : manifest.attr_type or 'ui' 
     221        } 
     222 
     223        self.startElement('UmitPlugin', AttributesImpl(attr_vals)), 
     224        self.writer.characters('\n') 
     225 
     226        # First phase saving 
     227        for elem in manifest.elements[0]: 
     228            self.add_element(elem) 
     229 
     230        # Runtime block 
     231        self.startElement('runtime', {}) 
     232        self.writer.characters('\n') 
     233 
     234        self.add_element('start_file') 
     235        self.add_element('update') 
     236 
     237        self.writer.characters('  ' * self.depth_idx) 
     238        self.endElement('runtime') 
     239 
     240        # Deptree block 
     241        if manifest.provide or manifest.need or manifest.conflict: 
     242            self.startElement('deptree', {}) 
     243            self.writer.characters('\n') 
     244 
     245            self.add_element('provide') 
     246            self.add_element('need') 
     247            self.add_element('conflict') 
     248 
     249            self.writer.characters('  ' * self.depth_idx) 
     250            self.endElement('deptree') 
     251 
     252        # Credits block 
     253        self.startElement('credits', {}) 
     254        self.writer.characters('\n') 
     255 
     256        for elem in manifest.elements[3]: 
     257            self.add_element(elem) 
     258 
     259        self.writer.characters('  ' * self.depth_idx) 
     260        self.endElement('credits') 
     261 
     262        self.endElement('UmitPlugin') 
     263        self.writer.endDocument() 
     264 
     265    def add_element(self, name): 
     266        value = getattr(self.manifest, name, None) 
     267 
     268        if not value: 
     269            return 
     270 
     271        if isinstance(value, basestring): 
     272            self.startElement(name, {}) 
     273            self.writer.characters(value) 
     274            self.endElement(name) 
     275        elif isinstance(value, list): 
     276            for item in value: 
     277                self.startElement(name, {}) 
     278                self.writer.characters(item) 
     279                self.endElement(name) 
     280 
     281    def get_output(self): 
     282        return self.output.getvalue() 
    76283 
    77284class BadPlugin(Exception): 
     
    79286    pass 
    80287 
    81 class PluginReader(object): 
     288class PluginReader(ManifestLoader): 
    82289    def __init__(self, file): 
     290        ManifestLoader.__init__(self) 
     291 
    83292        self.path = file 
    84293        self.enabled = False 
     
    88297        try: 
    89298            self.file = ZipFile(file, "r") 
    90         except BadZipfile: 
     299        except: 
    91300            raise BadPlugin("Not a valid umit plugin format") 
    92          
     301 
    93302        if not self.parse_manifest(): 
    94303            raise BadPlugin("Not a valid umit plugin manifest") 
    95          
     304 
    96305        if not self.check_validity(): 
    97306            raise BadPlugin("Validation phase not passed") 
     
    103312        """ 
    104313        Parse the Manifest.xml inside the zip file and set the fields 
    105          
     314 
    106315        @return 
    107316                False if the Manifest is not in the proper format 
    108317                True if everything is ok 
    109318        """ 
    110          
     319 
    111320        try: 
    112             data = self.file.read("Manifest.xml") 
    113             doc = parseString(data) 
    114         except Exception: 
     321            # TODO: add validation of the manifest 
     322 
     323            # Py2.5 doesn't have open on ZipFile object 
     324            fileobj = StringIO(self.file.read('Manifest.xml')) 
     325 
     326            parser = make_parser() 
     327            parser.setContentHandler(self) 
     328 
     329            parser.parse(fileobj) 
     330        except Exception, err: 
     331            log.debug('Exception in parse_manifest(): %s' % str(err)) 
    115332            return False 
    116          
    117         if doc.documentElement.tagName != SIGNATURE: 
    118             return False 
    119          
    120         for field in FIELDS: 
    121             setattr(self, field, "") 
    122          
    123         for node in doc.documentElement.childNodes: 
    124             if node.nodeName in FIELDS and node.firstChild: 
    125                 if node.nodeName in ('needs', 'provides', 'conflicts'): 
    126                     # Convert to list 
    127                     data = node.firstChild.data 
    128                     setattr(self, node.nodeName, \ 
    129                             data.replace(" ", "").split(",")) 
    130                 else: 
    131                     setattr(self, node.nodeName, node.firstChild.data) 
    132          
     333 
    133334        return True 
    134335 
     
    141342        except Exception, err: 
    142343            return 
    143      
    144     def check_validity(self): 
    145         """ 
    146         Checks the fields presents and validity 
    147          
    148         @return True if it's ok 
    149         """ 
    150         # TODO: implement me! 
    151          
    152         return True 
    153      
     344 
    154345    def __repr__(self): 
    155346        #FIXME: that 
     
    161352        try: 
    162353            # TODO: eliminate the mktemp workaround 
    163              
     354 
    164355            name = mktemp('.png') 
    165356            f = open(name, 'wb') 
     
    170361 
    171362            p = gtk.gdk.pixbuf_new_from_file_at_size(name, w, h) 
    172              
     363 
    173364            os.remove(name) 
    174365 
     
    213404 
    214405        return ret 
    215          
     406 
    216407    def extract_file(self, zip_path, keep_path=False): 
    217408        if zip_path not in self.file.namelist(): 
     
    288479        @return a catalog on success or None 
    289480        """ 
    290          
     481 
    291482        # We foreach inside locale dir and find a proper dir 
    292          
     483 
    293484        try: 
    294485            import gettext 
     
    304495        if LANG is None: 
    305496            LANG = "en_US" 
    306          
    307         # FIXME: is the '/' os indipendent? 
     497 
    308498        dir_lst = filter( \ 
    309499            lambda x: x.startswith("locale/") and x.endswith("%s.mo" % mofile), \ 
     
    313503 
    314504        avaiable_langs = [] 
    315          
     505 
    316506        for dirname in dir_lst: 
    317507            t = dirname.split("/") 
     
    319509            if len(t) < 3: 
    320510                continue 
    321              
     511 
    322512            avaiable_langs.append(t[-2]) 
    323513 
     
    331521                    self.file.read("locale/%s/%s.mo" % (req, mofile)) \ 
    332522                )) 
    333              
     523 
    334524        return None 
    335525 
    336 class PluginWriter(object): 
     526class PluginWriter(ManifestObject): 
    337527    def __init__(self, **fields): 
     528        ManifestObject.__init__(self) 
     529 
    338530        # Set to None and filter out the unused fields 
    339          
    340         for i in FIELDS: 
    341             setattr(self, i, "") 
    342          
     531 
     532        FIELDS = ('name', 'version', 'description', 'url', 'start_file', 
     533                  'update', 'provide', 'need', 'conflict', 'license', 
     534                  'copyright', 'author', 'contributor', 'translator', 'artist') 
     535 
     536        # Filter out fields that are not related to the schema 
     537 
    343538        for i in fields: 
    344539            if i in FIELDS: 
    345540                setattr(self, i, fields[i]) 
    346          
    347         for i in FIELDS: 
    348             print "Field %s setted to %s" % (i, getattr(self, i)) 
    349          
     541 
     542        if not self.check_validity(use_print=True): 
     543            print "!! Manifest could not be created." 
     544            sys.exit(-1) 
     545 
    350546        dirs = { 
    351547            'bin'  : '*', 
     
    354550            'locale' : '*' 
    355551        } 
    356          
     552 
    357553        self.file = ZipFile(fields['output'], "w", ZIP_DEFLATED) 
    358554 
     
    363559 
    364560        os.chdir("..") 
    365          
    366         self.file.writestr("Manifest.xml", self.create_manifest()) 
     561 
     562        writer = ManifestWriter(self) 
     563        self.file.writestr('Manifest.xml', writer.get_output()) 
    367564        self.file.close() 
    368          
     565 
    369566        print ">> Plugin %s created." % fields['output'] 
    370      
     567 
    371568    def dir_foreach(self, dir, pattern): 
    372569        "Add files contained in dir and that pass the pattern validation phase." 
     
    375572            if not files: 
    376573                continue 
    377              
     574 
    378575            for file in files: 
    379576                if not fnmatch(file, pattern): 
     
    381578 
    382579                print "Adding file %s %s %s" % (path, file, dir) 
    383                  
     580 
    384581                self.file.write(os.path.join(path, file), 
    385582                                os.path.join(path, file)) 
    386      
     583 
    387584    def create_manifest(self): 
    388585        """ 
    389586        Create a Manifest.xml file 
    390          
     587 
    391588        @return an xml manifest as string 
    392589        """ 
    393590        doc = getDOMImplementation().createDocument(None, SIGNATURE, None) 
    394          
     591 
    395592        for field in FIELDS: 
    396593            node = doc.createElement(field) 
    397594            node.appendChild(doc.createTextNode(getattr(self, field))) 
    398595            doc.documentElement.appendChild(node) 
    399          
     596 
    400597        print "Manifest.xml created" 
    401598        return doc.toxml() 
     
    452649    shutil.rmtree('build') 
    453650    shutil.rmtree('output') 
     651 
     652if __name__ == "__main__": 
     653    parser = make_parser() 
     654    loader = ManifestLoader() 
     655    parser.setContentHandler(loader) 
     656    parser.parse(open('test.xml')) 
     657    loader.dump() 
  • trunk/umit/plugin/Engine.py

    r4494 r4909  
    5151    {} 
    5252    """ 
    53      
     53 
    5454    def __init__(self, path): 
    5555        """ 
     
    7575        for file in os.listdir(self.path): 
    7676            path = os.path.join(self.path, file) 
    77              
     77 
    7878            if file.endswith(".ump") and \ 
    7979               os.path.isfile(path): 
     
    144144 
    145145        log.debug("Path.config_dir placed under %s" % Path.config_dir) 
    146          
     146 
    147147        dest_dir = os.path.join(Path.config_dir, 'plugins') 
    148148        temp_dir = os.path.join(Path.config_dir, 'plugins-temp') 
    149149        down_dir = os.path.join(Path.config_dir, 'plugins-download') 
    150          
     150 
    151151        for file in os.listdir(temp_dir): 
    152152            try: 
     
    169169                    os.remove(dst_name) 
    170170 
     171                log.debug("Installing new plugin from update: %s" % dst_name) 
     172 
    171173                os.rename(path, dst_name) 
    172174 
     
    283285        """ 
    284286        Load a plugin 
    285          
     287 
    286288        @param reader a PluginReader 
    287289        @param force True to not check depends 
     
    305307                log.debug(">>> Removing plugin from autoload") 
    306308                lst.remove(path) 
    307                  
     309 
    308310                self.plugins.plugins = lst 
    309311 
     
    311313        except PluginException, err: 
    312314            return (False, err) 
    313          
     315 
    314316    def uninstall_plugin(self, reader): 
    315317        """ 
    316318        Low level uninstall procedure 
    317          
     319 
    318320        @param reader a PluginReader 
    319321        @return True if ok or False 
    320322        """ 
    321          
     323 
    322324        try: 
    323325            os.remove(reader.get_path()) 
  • trunk/umit/plugin/Network.py

    r4240 r4909  
    4747            func(*args, **kwargs) 
    4848        except Exception, err: 
    49             log.error(_('>>> safecall(): Ignoring exception %s') % err) 
     49            log.error(_('>>> safecall(): Ignoring exception %s -> %s (%s, %s)')\ 
     50                      % (err, func, args, kwargs)) 
    5051    return proxy 
    5152 
     
    6364 
    6465        self.args = obj.args 
    65          
     66 
    6667        # FIXME: check this 
    6768        if isinstance(obj, urllib2.HTTPError): 
    6869            self.reason = '%d %s' % (obj.code, obj.msg) 
    6970        else: 
    70             self.reason = obj.reason 
     71            try: 
     72                self.reason = obj.reason 
     73            except: 
     74                self.reason = str(obj) 
    7175 
    7276class StartNetException(NetException): 
     
    106110        @param udata the additional data to pass to the callback 
    107111        """ 
    108          
     112 
    109113        log.debug(_(">>> Calling get_url() for %s") % url) 
    110114 
     
    150154            m.update("".join(udata)) 
    151155            print "MD5", m.hexdigest() 
    152              
     156 
    153157            return 
    154158 
  • trunk/umit/plugin/PluginPage.py

    r4240 r4909  
    3131 
    3232from umit.plugin.Core import Core 
    33 from umit.plugin.Update import FILE_GETTING, FILE_CHECKING 
     33from umit.plugin.Atoms import Version 
     34from umit.plugin.Update import FILE_GETTING, FILE_CHECKING, FILE_ERROR 
    3435from umit.plugin.Update import LATEST_GETTED, LATEST_ERROR, LATEST_GETTING 
    3536 
     
    4344        self.__create_widgets() 
    4445        self.__pack_widgets() 
    45          
     46 
    4647        self.install_updates_btn.hide() 
    4748 
     
    6263        self.restart_btn = \ 
    6364            HIGButton(_('Restart UMIT'), gtk.STOCK_REFRESH) 
    64      
     65 
    6566    def __pack_widgets(self): 
    6667        self.hbbox.pack_start(self.find_updates_btn) 
     
    6869        self.hbbox.pack_start(self.install_updates_btn) 
    6970        self.hbbox.pack_start(self.restart_btn) 
    70          
     71 
    7172        self.pack_start(self.richlist) 
    7273        self.pack_start(self.hbbox, False, False, 0) 
    73          
     74 
    7475        self.find_updates_btn.connect('clicked', self.__on_find_updates) 
    7576        self.install_updates_btn.connect('clicked', self.__on_install_updates) 
     
    7879 
    7980        self.show_all() 
    80      
     81 
    8182    def clear(self, include_loaded=True): 
    8283        if include_loaded: 
     
    140141        "Called when the user click on the restart button" 
    141142 
    142         # TODO: implement me 
    143         log.critical("Restart is not implemented!") 
     143        Core().mainwindow.emit('delete-event', None) 
    144144 
    145145    def __on_skip_updates(self, widget): 
     
    151151 
    152152        self.p_window.toolbar.unset_status() 
    153         self.p_window.animated_bar.label = \ 
    154                 _('Update skipped') 
     153 
     154        if self.restart_btn.flags() & gtk.VISIBLE: 
     155            # That callback is called from a self.___on_install_updates 
     156 
     157            self.restart_btn.hide() 
     158            self.p_window.animated_bar.label = \ 
     159                _('Rembember to restart UMIT to use new version of plugins.') 
     160 
     161        else: 
     162            self.p_window.animated_bar.label = \ 
     163                    _('Update skipped') 
     164 
    155165        self.p_window.animated_bar.start_animation(True) 
    156166 
     
    160170 
    161171        self.menu_enabled = True 
    162      
     172 
    163173    def __on_install_updates(self, widget): 
    164174        """ 
     
    174184            if obj.status != LATEST_GETTED: 
    175185                self.richlist.remove_row(obj.object) 
    176              
     186                continue 
     187 
    177188            if obj.object.show_include: 
    178189                lst.append(obj) 
    179              
     190 
    180191            obj.object.show_include = False 
    181          
     192 
     193            # Reset indexes 
     194            obj.last_update_idx = 0 
     195            obj.selected_update_idx = obj.object.versions_button.get_active()-1 
     196 
    182197        self.install_updates_btn.set_sensitive(False) 
    183198        self.skip_install_btn.set_sensitive(False) 
     
    191206        ) 
    192207        gobject.timeout_add(300, self.__refresh_row_download) 
    193      
     208 
    194209    def __refresh_row_download(self): 
    195210        """ 
     
    199214 
    200215        working = False 
    201          
     216 
    202217        for obj in self.p_window.update_eng.list: 
    203218            obj.lock.acquire() 
     
    207222                   obj.status == FILE_CHECKING: 
    208223                    working = True 
    209                      
     224 
    210225                row = obj.object 
    211226                row.message = obj.label 
     
    213228            finally: 
    214229                obj.lock.release() 
    215          
     230 
    216231        if not working: 
    217              
     232 
     233            errors = '' 
     234 
    218235            for obj in self.p_window.update_eng.list: 
    219236                row = obj.object 
    220237                row.message = obj.label 
    221238                row.progress = None 
    222              
     239 
     240                if not errors and obj.status == FILE_ERROR: 
     241                    errors = ' but with <b>some errors</b>' 
     242 
    223243            # Only warn the user about changes take effects on restart 
    224244            # on restart just move the plugins stored in home directory 
    225245            # in the proper location 
    226              
     246 
    227247            self.p_window.animated_bar.label = \ 
    228                 _('Update phase complete. Now restart ' \ 
    229                   'UMIT to changes make effects.') 
     248                _('Update phase complete%s. Now restart ' \ 
     249                  'UMIT to changes make effects.') % errors 
    230250            self.p_window.animated_bar.start_animation(True) 
    231              
     251 
    232252            self.p_window.toolbar.unset_status() 
    233              
     253 
    234254            self.install_updates_btn.hide() 
    235             self.skip_install_btn.hide() 
     255 
     256            # Let the user to choose to restart or not UMIT 
     257            self.skip_install_btn.set_sensitive(True) 
    236258 
    237259            self.restart_btn.show() 
    238          
     260 
    239261        return working 
    240      
     262 
    241263    def __on_find_updates(self, widget): 
    242264        """ 
     
    250272        self.find_updates_btn.set_sensitive(False) 
    251273        self.menu_enabled = False 
    252          
     274 
    253275        lst = [] 
    254276 
     
    268290 
    269291            self.p_window.animated_bar.label = \ 
    270                 _("No plugins provides update url. Cannot procede.") 
     292                _("No plugins provide an update URL. Cannot proceed.") 
    271293            self.p_window.animated_bar.image = gtk.STOCK_DIALOG_ERROR 
    272294            self.p_window.animated_bar.start_animation(True) 
     
    292314        gobject.timeout_add(300, self.__update_rich_list) 
    293315 
     316    def __query_tooltip_versions_button(self, widget, x, y, keyboard_tip, \ 
     317                                        tooltip, obj): 
     318 
     319        idx = obj.object.versions_button.get_active() - 1 
     320 
     321        if idx >= 0: 
     322            desc = obj.updates[idx].description 
     323 
     324            if desc: 
     325                tooltip.set_markup(desc) 
     326                tooltip.set_icon_from_stock(gtk.STOCK_INDEX, gtk.ICON_SIZE_MENU) 
     327                return True 
     328 
     329        return False 
     330 
    294331    def __update_rich_list(self): 
    295332        """ 
     
    299336 
    300337        working = False 
    301          
     338 
    302339        for upd_obj in self.p_window.update_eng.list: 
    303340            upd_obj.lock.acquire() 
     
    307344                if upd_obj.status == LATEST_GETTING: 
    308345                    working = True 
    309                  
     346 
    310347                # Update the row 
    311348                row = upd_obj.object 
     
    313350            finally: 
    314351                upd_obj.lock.release() 
    315          
     352 
    316353        # No locking from here we have finished 
    317354 
     
    320357            self.p_window.update_eng.stop() 
    321358            self.find_updates_btn.set_sensitive(True) 
    322              
     359 
    323360            lst = filter( \ 
    324361                lambda x: (x.status == LATEST_GETTED) and (x) or (None),\ 
     
    329366                self.p_window.update_eng.list \ 
    330367            ) 
    331              
     368 
    332369            if not lst and not elst: 
    333370                self.p_window.toolbar.unset_status() 
     
    336373                    _('<b>No updates found</b>') 
    337374                self.p_window.animated_bar.start_animation(True) 
    338                  
     375 
    339376                self.richlist.clear() 
    340377                self.populate() 
     
    358395                    row = obj.object 
    359396                    active = (obj.status == LATEST_GETTED) 
    360                      
     397 
    361398                    if active: 
     399                        obj.last_update_idx = 0 
    362400                        row.show_include = True 
     401 
     402                        log.debug("Connecting 'query-tooltip' for %s" % obj) 
     403 
     404                        # The tooltip is showed and hidden continuously 
     405                        row.versions_button.props.has_tooltip = True 
     406                        row.versions_button.connect( 
     407                            'query-tooltip', 
     408                            self.__query_tooltip_versions_button, obj 
     409                        ) 
     410 
     411                        row.versions_model.clear() 
     412 
     413                        row.versions_model.append([ 
     414                            gtk.STOCK_CANCEL, _("Skip") 
     415                        ]) 
     416 
     417                        for update in obj.updates: 
     418                            cur_v = Version(row.reader.version) 
     419                            new_v = Version(update.version) 
     420 
     421                            if new_v > cur_v: 
     422                                row.versions_model.append([ 
     423                                    gtk.STOCK_GO_UP, _("Update to %s") % \ 
     424                                    update.version 
     425                                ]) 
     426                            elif new_v == cur_v: 
     427                                row.versions_model.append([ 
     428                                    gtk.STOCK_REFRESH, _("Reinstall %s") % \ 
     429                                    update.version 
     430                                ]) 
     431                            else: 
     432                                row.versions_model.append([ 
     433                                    gtk.STOCK_GO_DOWN, _("Downgrade to %s") % \ 
     434                                    update.version 
     435                                ]) 
     436 
     437                        row.versions_button.set_active(0) 
    363438                        row.message = obj.label 
    364439                    else: 
    365440                        row.saturate = True 
    366                  
     441 
    367442                if lst: 
    368443                    self.install_updates_btn.show() 
    369                      
     444 
    370445                self.find_updates_btn.hide() 
    371446                self.skip_install_btn.show() 
    372447 
    373448        return working 
    374      
     449 
    375450    def __on_row_popup(self, row, evt): 
    376451        "Popup menu" 
     
    476551            if r == gtk.RESPONSE_YES: 
    477552                r, err = self.p_window.engine.unload_plugin(row.reader) 
    478                  
     553 
    479554                if not r: 
    480555                    d = dialog( \ 
     
    501576 
    502577        row.activatable = False 
    503          
     578 
    504579        if self.p_window.engine.uninstall_plugin(row.reader): 
    505580            del row 
     
    508583        else: 
    509584            row.activatable = True 
    510              
     585 
    511586            self.p_window.animated_bar.label = \ 
    512587                _('Unable to uninstall %s plugin.') % row.reader 
     
    515590    def __on_row_preference(self, widget, row): 
    516591        "Preference button callback" 
    517          
     592 
    518593        if not self.p_window.engine.tree.show_preferences(row.reader): 
    519594            self.p_window.animated_bar.label = \ 
  • trunk/umit/plugin/Update.py

    r4240 r4909  
    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 
  • trunk/umit/plugin/Window.py

    r4240 r4909  
    1919 
    2020import gtk 
     21import os.path 
    2122 
    2223from higwidgets.higwindows import HIGWindow 
     
    2930from PluginPage import PluginPage 
    3031 
     32from umit.core.Paths import Path 
    3133from umit.plugin.Update import UpdateEngine 
    3234from umit.plugin.Engine import PluginEngine 
     
    4749        self.set_position(gtk.WIN_POS_CENTER) 
    4850        self.set_size_request(600, 400) 
     51        self.set_icon_from_file(os.path.join(Path.icons_dir, "umit_16.ico")) 
    4952 
    5053        self.__create_widgets() 
     
    97100        self.plug_page.skip_install_btn.hide() 
    98101        self.plug_page.restart_btn.hide() 
    99          
     102 
    100103        self.connect('delete-event', self.__on_delete_event) 
    101104 
     
    109112        self.plug_page.populate() 
    110113        self.path_page.populate() 
    111      
     114 
    112115    def __on_switch_page(self, widget, id): 
    113116        self.notebook.set_current_page(id)