home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / xbmc-9.11.exe / plugins / Programs / SVN Repo Installer / installerAPI / xbmcplugin_downloader.py < prev    next >
Encoding:
Python Source  |  2009-11-03  |  8.1 KB  |  226 lines

  1. """
  2. Update module
  3.  
  4. Nuka1195
  5. """
  6.  
  7. # main imports
  8. import sys
  9. import os
  10. import xbmc
  11. import xbmcgui
  12. import xbmcplugin
  13. import urllib
  14. import re
  15. from xml.sax.saxutils import unescape
  16. from xbmcplugin_lib import *
  17.  
  18. __plugin__ = sys.modules["__main__"].__plugin__
  19. __date__ = '19-06-2009'
  20. log("Module: %s Dated: %s loaded!" % (__name__, __date__))
  21.  
  22. class Parser:
  23.     """ Parser Class: grabs all tag versions and urls """
  24.     # regexpressions
  25.     revision_regex = re.compile( '<h2>.+?Revision ([0-9]*): ([^<]*)</h2>' )
  26.     asset_regex = re.compile( '<li><a href="([^"]*)">([^"]*)</a></li>' )
  27.  
  28.     def __init__( self, htmlSource ):
  29.         # set our initial status
  30.         self.dict = { "status": "fail", "revision": 0, "assets": [], "url": "" }
  31.         # fetch revision number
  32.         self._fetch_revision( htmlSource )
  33.         # if we were successful, fetch assets
  34.         if ( self.dict[ "revision" ] != 0 ):
  35.             self._fetch_assets( htmlSource )
  36.  
  37.     def _fetch_revision( self, htmlSource ):
  38.         try:
  39.             # parse revision and current dir level
  40.             revision, url = self.revision_regex.findall( htmlSource )[ 0 ]
  41.             # we succeeded :), set our info
  42.             self.dict[ "url" ] = url
  43.             self.dict[ "revision" ] = int( revision )
  44.         except:
  45.             pass
  46.  
  47.     def _fetch_assets( self, htmlSource ):
  48.         try:
  49.             assets = self.asset_regex.findall( htmlSource )
  50.             if ( len( assets ) ):
  51.                 for asset in assets:
  52.                     if ( asset[ 0 ] != "../" ):
  53.                         self.dict[ "assets" ] += [ unescape( asset[ 0 ] ) ]
  54.                 self.dict[ "status" ] = "ok"
  55.         except:
  56.             pass
  57.  
  58. class Main:
  59.     def __init__( self ):
  60.         log( "%s started!" % self.__class__ )
  61.  
  62.         self.dialog = xbmcgui.DialogProgress()
  63.  
  64.         if "update_all" in sys.argv[ 2 ]:
  65.             self.update_all()
  66.         else:
  67.             # parse sys.argv for our current url
  68.             self._parse_argv()
  69.             # get the repository info
  70.             self._get_repo_info()
  71.             self._create_title()
  72.             # get the list
  73.             self._download_item()
  74.  
  75.     def _get_repo_info( self ):
  76.         # path to info file
  77.         repopath = os.path.join( os.getcwd(), "resources", "repositories", self.args.repo, "repo.xml" )
  78.         try:
  79.             # grab a file object
  80.             fileobject = open( repopath, "r" )
  81.             # read the info
  82.             info = fileobject.read()
  83.             # close the file object
  84.             fileobject.close()
  85.             # repo's base url
  86.             self.REPO_URL = re.findall( '<url>([^<]+)</url>', info )[ 0 ]
  87.             log("_get_repo_info() repo_url=%s" % self.REPO_URL)
  88.         except:
  89.             # oops print error message
  90.             print "ERROR: %s::%s (%d) - %s" % ( self.__class__.__name__, sys.exc_info()[ 2 ].tb_frame.f_code.co_name, sys.exc_info()[ 2 ].tb_lineno, sys.exc_info()[ 1 ], )
  91.  
  92.     def _parse_argv( self ):
  93.         # call _Info() with our formatted argv to create the self.args object
  94.         exec "self.args = Info(%s)" % ( sys.argv[ 2 ][ 1 : ].replace( "&", ", " ), )
  95.         self.args.download_url = urllib.unquote_plus( self.args.download_url )
  96.         self.args.repo = urllib.unquote_plus( self.args.repo )
  97.  
  98.     def _create_title( self ):
  99.         # create the script/plugin/skin title
  100.         parts = self.args.download_url.split( "/" )
  101.         version = ""
  102.         if ( self.args.voffset != 0 ):
  103.             version = " - %s" % ( parts[ self.args.voffset ].replace( "%20", " " ) )
  104.             del parts[ self.args.voffset ]
  105.         self.title = parts[ -2 ].replace( "%20", " " ) + version
  106.         log("_create_title() %s" % self.title)
  107.  
  108.     def update_all( self ):
  109.         log("> _update_all()")
  110.         """ Download and install all new Addons as stored in update file """
  111.         # eg 'download_url="%2Ftrunk%2Fplugins%2Fmusic/iTunes%2F"&repo=\'xbmc-addons\'&install=""&ioffset=2&voffset=0'
  112.         fn = os.path.join( os.getcwd(), "update_all.dat" )
  113.         items = loadFileObj(fn)
  114.         if items:
  115.             if xbmcgui.Dialog().yesno( __plugin__, xbmc.getLocalizedString( 30019 ) + " ?", "", "", xbmc.getLocalizedString( 30020 ), xbmc.getLocalizedString( 30021 ) ):
  116.                 # enumerate throu item to download & install
  117.                 sz = len(items)
  118.                 for url_args in items:
  119.                     log("_update_all() updating: %s" % url_args)
  120.                     # load item args
  121.                     sys.argv[ 2 ] = url_args
  122.                     # parse sys.argv for our current url
  123.                     self._parse_argv()
  124.                     # get the repository info
  125.                     self._get_repo_info()
  126.                     # create title
  127.                     self._create_title()
  128.                     # download & install
  129.                     self._download_item( forceInstall=True )
  130.  
  131.                 self.dialog.close()
  132.                 # force list refresh
  133. #                xbmc.executebuiltin('Container.Refresh')
  134.         else:
  135.             xbmcgui.Dialog().ok("update_all()", "'Update All' file missing/empty!", os.path.split(fn)[0], os.path.basename(fn))
  136.         log("< _update_all()")
  137.  
  138.     def _download_item( self, forceInstall=False ):
  139.         log("> _download_item() forceInstall=%s" % forceInstall)
  140.         try:
  141.             if ( forceInstall or xbmcgui.Dialog().yesno( self.title, xbmc.getLocalizedString( 30000 ), "", "", xbmc.getLocalizedString( 30020 ), xbmc.getLocalizedString( 30021 ) ) ):
  142.                 self.dialog.create( self.title, xbmc.getLocalizedString( 30002 ), xbmc.getLocalizedString( 30003 ) )
  143.                 asset_files = []
  144.                 folders = [ self.args.download_url.replace( " ", "%20" ) ]
  145.                 while folders:
  146.                     try:
  147.                         htmlsource = readURL( self.REPO_URL + folders[ 0 ] )
  148.                         if ( not htmlsource ): raise
  149.                         items = self._parse_html_source( htmlsource )
  150.                         if ( not items or items[ "status" ] == "fail" ): raise
  151.                         files, dirs = self._parse_items( items )
  152.                         for file in files:
  153.                             asset_files.append( "%s/%s" % ( items[ "url" ], file, ) )
  154.                         for folder in dirs:
  155.                             folders.append( folders[ 0 ] + folder )
  156.                         folders = folders[ 1 : ]
  157.                     except:
  158.                         folders = []
  159.  
  160.                 finished_path = self._get_files( asset_files )
  161.                 self.dialog.close()
  162.                 if finished_path and not forceInstall:
  163.                     xbmcgui.Dialog().ok( self.title, xbmc.getLocalizedString( 30008 ), finished_path )
  164.                     # force list refresh
  165. #                    xbmc.executebuiltin('Container.Refresh')
  166.         except:
  167.             # oops print error message
  168.             print "ERROR: %s::%s (%d) - %s" % ( self.__class__.__name__, sys.exc_info()[ 2 ].tb_frame.f_code.co_name, sys.exc_info()[ 2 ].tb_lineno, sys.exc_info()[ 1 ], )
  169.             self.dialog.close()
  170.             xbmcgui.Dialog().ok( self.title, xbmc.getLocalizedString( 30030 ) )
  171.         log("< _download_item()")
  172.         
  173.     def _get_files( self, asset_files ):
  174.         """ fetch the files """
  175.         try:
  176.             finished_path = ""
  177.             for cnt, url in enumerate( asset_files ):
  178.                 items = os.path.split( url )
  179.                 # base path
  180.                 drive = xbmc.translatePath( "/".join( [ "special://home", self.args.install ] ) )
  181.                 # create the script/plugin/skin title
  182.                 parts = items[ 0 ].split( "/" )
  183.                 version = ""
  184.                 if ( self.args.voffset != 0 ):
  185.                     version = " - %s" % ( parts[ self.args.voffset ], )
  186.                     del parts[ self.args.voffset ]
  187.                     parts[ self.args.voffset - 1 ] = parts[ self.args.voffset - 1 ].replace( "%20", " " ) + version
  188.                 path = os.path.join( drive, os.path.sep.join( parts[ self.args.ioffset : ] ).replace( "%20", " " ) )
  189.                 if ( not finished_path ): finished_path = path
  190.                 file = items[ 1 ].replace( "%20", " " )
  191.                 pct = int( ( float( cnt ) / len( asset_files ) ) * 100 )
  192.                 self.dialog.update( pct, "%s %s" % ( xbmc.getLocalizedString( 30005 ), url, ), "%s %s" % ( xbmc.getLocalizedString( 30006 ), path, ), "%s %s" % ( xbmc.getLocalizedString( 30007 ), file, ) )
  193.                 if ( self.dialog.iscanceled() ): raise
  194.                 if ( not os.path.isdir( path ) ): os.makedirs( path )
  195.                 url = self.REPO_URL + url.replace( " ", "%20" )
  196.                 fpath = os.path.join( path, file )
  197.                 log("urlretrieve() %s -> %s" % (url, fpath))
  198.                 urllib.urlretrieve( url, fpath )
  199.         except:
  200.             finished_path = ""
  201.             # oops print error message
  202.             print "ERROR: %s::%s (%d) - %s" % ( self.__class__.__name__, sys.exc_info()[ 2 ].tb_frame.f_code.co_name, sys.exc_info()[ 2 ].tb_lineno, sys.exc_info()[ 1 ], )
  203.             raise
  204.  
  205.         log("_get_files() finished_path=%s" % finished_path)
  206.         return finished_path
  207.             
  208.     def _parse_html_source( self, htmlsource ):
  209.         """ parse html source for tagged version and url """
  210.         try:
  211.             parser = Parser( htmlsource )
  212.             return parser.dict
  213.         except:
  214.             return {}
  215.             
  216.     def _parse_items( self, items ):
  217.         """ separates files and folders """
  218.         folders = []
  219.         files = []
  220.         for item in items[ "assets" ]:
  221.             if ( item.endswith( "/" ) ):
  222.                 folders.append( item )
  223.             else:
  224.                 files.append( item )
  225.         return files, folders
  226.