""" Update module Nuka1195 """ # main imports import sys import os import xbmc import xbmcgui import xbmcplugin import urllib import re from xml.sax.saxutils import unescape from xbmcplugin_lib import * __plugin__ = sys.modules["__main__"].__plugin__ __date__ = '15-10-2009' log("Module: %s Dated: %s loaded!" % (__name__, __date__)) class Parser: """ Parser Class: grabs all tag versions and urls """ # regexpressions revision_regex = re.compile( '

.+?Revision ([0-9]*): ([^<]*)

' ) asset_regex = re.compile( '
  • ([^"]*)
  • ' ) def __init__( self, htmlSource ): # set our initial status self.dict = { "status": "fail", "revision": 0, "assets": [], "url": "" } # fetch revision number self._fetch_revision( htmlSource ) # if we were successful, fetch assets if ( self.dict[ "revision" ] != 0 ): self._fetch_assets( htmlSource ) def _fetch_revision( self, htmlSource ): try: # parse revision and current dir level revision, url = self.revision_regex.findall( htmlSource )[ 0 ] # we succeeded :), set our info self.dict[ "url" ] = url self.dict[ "revision" ] = int( revision ) except: pass def _fetch_assets( self, htmlSource ): try: assets = self.asset_regex.findall( htmlSource ) if ( len( assets ) ): for asset in assets: if ( asset[ 0 ] != "../" ): self.dict[ "assets" ] += [ unescape( asset[ 0 ] ) ] self.dict[ "status" ] = "ok" except: pass class Main: def __init__( self ): log( "%s started!" % self.__class__ ) self.dialog = xbmcgui.DialogProgress() if "update_all" in sys.argv[ 2 ]: self.update_all() else: # parse sys.argv for our current url self._parse_argv() # get the repository info self._get_repo_info() self._create_title() # get the list self._download_item( forceInstall=True ) def _get_repo_info( self ): # path to info file # repopath = os.path.join( os.getcwd(), "resources", "repositories", self.args.repo, "repo.xml" ) repopath = os.path.join( HOME_DIR, "resources", "repositories", self.args.repo, "repo.xml" ) try: # read file info = readFile( repopath ) # repo's base url self.REPO_URL = re.findall( '([^<]+)', info )[ 0 ] log("_get_repo_info() repo_url=%s" % self.REPO_URL) except: # oops print error message 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 ], ) def _parse_argv( self ): # call _Info() with our formatted argv to create the self.args object exec "self.args = Info(%s)" % ( sys.argv[ 2 ][ 1 : ].replace( "&", ", " ), ) self.args.download_url = urllib.unquote_plus( self.args.download_url ) self.args.repo = urllib.unquote_plus( self.args.repo ) def _create_title( self ): # create the script/plugin/skin title parts = self.args.download_url.split( "/" ) version = "" if ( self.args.voffset != 0 ): version = " - %s" % ( parts[ self.args.voffset ].replace( "%20", " " ) ) del parts[ self.args.voffset ] self.title = parts[ -2 ].replace( "%20", " " ) + version log("_create_title() %s" % self.title) def update_all( self ): log("> _update_all()") """ Download and install all new Addons as stored in update file """ # eg 'download_url="%2Ftrunk%2Fplugins%2Fmusic/iTunes%2F"&repo=\'xbmc-addons\'&install=""&ioffset=2&voffset=0' # fn = os.path.join( os.getcwd(), "update_all.dat" ) fn = os.path.join( HOME_DIR, "update_all.dat" ) items = loadFileObj(fn) if items: if xbmcgui.Dialog().yesno( __plugin__, xbmc.getLocalizedString( 30019 ) + " ?", "", "", xbmc.getLocalizedString( 30020 ), xbmc.getLocalizedString( 30021 ) ): # enumerate throu item to download & install sz = len(items) for url_args in items: log("_update_all() updating: %s" % url_args) # load item args sys.argv[ 2 ] = url_args # parse sys.argv for our current url self._parse_argv() # get the repository info self._get_repo_info() # create title self._create_title() # download & install self._download_item( forceInstall=True ) self.dialog.close() # force list refresh # xbmc.executebuiltin('Container.Refresh') else: xbmcgui.Dialog().ok("update_all()", "'Update All' file missing/empty!", os.path.split(fn)[0], os.path.basename(fn)) log("< _update_all()") def _download_item( self, forceInstall=False ): log("> _download_item() forceInstall=%s" % forceInstall) try: if ( forceInstall or xbmcgui.Dialog().yesno( self.title, xbmc.getLocalizedString( 30000 ), "", "", xbmc.getLocalizedString( 30020 ), xbmc.getLocalizedString( 30021 ) ) ): self.dialog.create( self.title, xbmc.getLocalizedString( 30002 ), xbmc.getLocalizedString( 30003 ) ) asset_files = [] folders = [ self.args.download_url.replace( " ", "%20" ) ] while folders: try: htmlsource = readURL( self.REPO_URL + folders[ 0 ] ) if ( not htmlsource ): raise items = self._parse_html_source( htmlsource ) if ( not items or items[ "status" ] == "fail" ): raise files, dirs = self._parse_items( items ) for file in files: asset_files.append( "%s/%s" % ( items[ "url" ], file, ) ) for folder in dirs: folders.append( folders[ 0 ] + folder ) folders = folders[ 1 : ] except: folders = [] finished_path = self._get_files( asset_files ) self.dialog.close() if finished_path and not forceInstall: xbmcgui.Dialog().ok( self.title, xbmc.getLocalizedString( 30008 ), finished_path ) # force list refresh # xbmc.executebuiltin('Container.Refresh') except: # oops print error message 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 ], ) self.dialog.close() xbmcgui.Dialog().ok( self.title, xbmc.getLocalizedString( 30030 ) ) log("< _download_item()") def _get_files( self, asset_files ): """ fetch the files """ try: finished_path = "" for cnt, url in enumerate( asset_files ): items = os.path.split( url ) # base path drive = xbmc.translatePath( "/".join( [ "special://home", self.args.install ] ) ) # create the script/plugin/skin title parts = items[ 0 ].split( "/" ) version = "" if ( self.args.voffset != 0 ): version = " - %s" % ( parts[ self.args.voffset ], ) del parts[ self.args.voffset ] parts[ self.args.voffset - 1 ] = parts[ self.args.voffset - 1 ].replace( "%20", " " ) + version path = os.path.join( drive, os.path.sep.join( parts[ self.args.ioffset : ] ).replace( "%20", " " ) ) if ( not finished_path ): finished_path = path file = items[ 1 ].replace( "%20", " " ) pct = int( ( float( cnt ) / len( asset_files ) ) * 100 ) self.dialog.update( pct, "%s %s" % ( xbmc.getLocalizedString( 30005 ), url, ), "%s %s" % ( xbmc.getLocalizedString( 30006 ), path, ), "%s %s" % ( xbmc.getLocalizedString( 30007 ), file, ) ) if ( self.dialog.iscanceled() ): raise if ( not os.path.isdir( path ) ): os.makedirs( path ) url = self.REPO_URL + url.replace( " ", "%20" ) fpath = os.path.join( path, file ) log("urlretrieve() %s -> %s" % (url, fpath)) urllib.urlretrieve( url, fpath ) except: finished_path = "" # oops print error message 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 ], ) raise log("_get_files() finished_path=%s" % finished_path) return finished_path def _parse_html_source( self, htmlsource ): """ parse html source for tagged version and url """ try: parser = Parser( htmlsource ) return parser.dict except: return {} def _parse_items( self, items ): """ separates files and folders """ folders = [] files = [] for item in items[ "assets" ]: if ( item.endswith( "/" ) ): folders.append( item ) else: files.append( item ) return files, folders