%PDF- %PDF-
Direktori : /usr/share/hplip/installer/ |
Current File : //usr/share/hplip/installer/pluginhandler.py |
# -*- coding: utf-8 -*- # # (c) Copyright @ 20013 HP Development Company, L.P. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Author: Amarnath Chitumalla # import os import shutil from base import utils, tui, os_utils, validation, password from base.g import * from base.codes import * from base.strings import * from base.sixext.moves import configparser from installer import core_install try: import hashlib # new in 2.5 def get_checksum(s): return hashlib.sha1(s).hexdigest() except ImportError: import sha # deprecated in 2.6/3.0 def get_checksum(s): return sha.new(s).hexdigest() PLUGIN_STATE_FILE = '/var/lib/hp/hplip.state' PLUGIN_FALLBACK_LOCATION = 'https://developers.hp.com/sites/default/files/' class PluginHandle(object): def __init__(self, pluginPath = prop.user_dir): self.__plugin_path = pluginPath self.__required_version = "" self.__plugin_name = "" self.__plugin_state = PLUGIN_NOT_INSTALLED self.__installed_version = '' self.__plugin_conf_file = "" self.__setPluginConfFile() self.__setPluginVersion() self.__readPluginStatus() #################### Private functions ######################## def __getPluginFilesList(self, src_dir): if not os.path.exists(src_dir+"/plugin.spec"): log.warn("%s/plugin.spec file doesn't exists."%src_dir) return [] cwd = os.getcwd() os.chdir(src_dir) plugin_spec = ConfigBase("plugin.spec") products = plugin_spec.keys("products") BITNESS = utils.getBitness() ENDIAN = utils.getEndian() PPDDIR = sys_conf.get('dirs', 'ppd') DRVDIR = sys_conf.get('dirs', 'drv') HOMEDIR = sys_conf.get('dirs', 'home') DOCDIR = sys_conf.get('dirs', 'doc') CUPSBACKENDDIR = sys_conf.get('dirs', 'cupsbackend') CUPSFILTERDIR = sys_conf.get('dirs', 'cupsfilter') RULESDIR = '/etc/udev/rules.d' BIN = sys_conf.get('dirs', 'bin') # Copying plugin.spec file to home dir. if src_dir != HOMEDIR: shutil.copyfile(src_dir+"/plugin.spec", HOMEDIR+"/plugin.spec") os.chmod(HOMEDIR+"/plugin.spec",0o644) processor = utils.getProcessor() if processor == 'power_machintosh': ARCH = 'ppc' elif (processor == 'armv6l' or processor == 'armv7l' or processor == 'aarch64' or processor == 'aarch32'): ARCH = 'arm%d' % BITNESS else: ARCH = 'x86_%d' % BITNESS if BITNESS == 64: SANELIBDIR = '/usr/lib64/sane' LIBDIR = '/usr/lib64' else: SANELIBDIR = '/usr/lib/sane' LIBDIR = '/usr/lib' copies = [] for PRODUCT in products: MODEL = PRODUCT.replace('hp-', '').replace('hp_', '') for s in plugin_spec.get("products", PRODUCT).split(','): if not plugin_spec.has_section(s): log.error("Missing section [%s]" % s) os.chdir(cwd) return [] src = plugin_spec.get(s, 'src', '') trg = plugin_spec.get(s, 'trg', '') link = plugin_spec.get(s, 'link', '') if not src: log.error("Missing 'src=' value in section [%s]" % s) os.chdir(cwd) return [] if not trg: log.error("Missing 'trg=' value in section [%s]" % s) os.chdir(cwd) return [] src = os.path.basename(utils.cat(src)) trg = utils.cat(trg) if link: link = utils.cat(link) copies.append((src, trg, link)) copies = utils.uniqueList(copies) copies.sort() os.chdir(cwd) return copies def __setPluginVersion(self): self.__required_version = prop.installed_version self.__plugin_name = 'hplip-%s-plugin.run' % self.__required_version def __readPluginStatus(self): plugin_state_conf = ConfigBase( PLUGIN_STATE_FILE) self.__plugin_state = plugin_state_conf.get('plugin', 'installed', PLUGIN_NOT_INSTALLED) if self.__plugin_state == PLUGIN_NOT_INSTALLED: self.__installed_version = '' else: self.__installed_version = plugin_state_conf.get('plugin','version', '') hplip_version = sys_conf.get('hplip', 'version', '0.0.0') if self.__installed_version != hplip_version: self.__plugin_state = PLUGIN_VERSION_MISMATCH else: home = sys_conf.get('dirs', 'home') copies = self.__getPluginFilesList( home ) for src, trg, link in copies: #added below if condition to ignore "rules" files for checking links in plugin.spec for HPLIP-122-'Driver plug-in required' pop-up is shown even if plugin is installed. if src.find('.rules'): continue if link != "": if not utils.check_library(link): pass def __getPluginInformation(self, callback=None): status, url, check_sum = ERROR_NO_NETWORK, '','' if self.__plugin_conf_file.startswith('http://'): if not utils.check_network_connection(): log.error("Network connection not detected.") return ERROR_NO_NETWORK, '', 0 local_conf_fp, local_conf = utils.make_temp_file() try: try: if self.__plugin_conf_file.startswith('file://'): status, filename = utils.download_from_network(self.__plugin_conf_file, local_conf, True) else: wget = utils.which("wget", True) if wget: status, output = utils.run("%s --tries=3 --timeout=60 --output-document=%s %s --cache=off" %(wget, local_conf, self.__plugin_conf_file)) if status: log.error("Plugin download failed with error code = %d" %status) return status, url, check_sum else: log.error("Please install wget package to download the plugin.") return status, url, check_sum except IOError as e: log.error("I/O Error: %s" % e.strerror) return status, url, check_sum if not os.path.exists(local_conf): log.error("plugin.conf not found.") return status, url, check_sum try: plugin_conf_p = ConfigBase(local_conf) url = plugin_conf_p.get(self.__required_version, 'url','') check_sum = plugin_conf_p.get(self.__required_version, 'checksum') status = ERROR_SUCCESS except (KeyError, configparser.NoSectionError) as e: log.error("Error reading plugin.conf: Missing section [%s] Error[%s]" % (self.__required_version,e)) return ERROR_FILE_NOT_FOUND, url, check_sum if url == '': return ERROR_FILE_NOT_FOUND, url, check_sum finally: os.close(local_conf_fp) os.remove(local_conf) return status, url, check_sum def __validatePlugin(self,plugin_file, digsig_file, req_checksum): #Validate Checksum calc_checksum = get_checksum(open(plugin_file, 'rb').read()) log.debug("D/L file checksum=%s" % calc_checksum) if req_checksum and req_checksum != calc_checksum: return ERROR_CHECKSUM_ERROR, queryString(ERROR_CHECKSUM_ERROR, 0, plugin_file) #Validate Digital Signatures gpg_obj = validation.GPG_Verification() digsig_sts, error_str = gpg_obj.validate(plugin_file, digsig_file) return digsig_sts, error_str def __setPluginConfFile(self): home = sys_conf.get('dirs', 'home') if os.path.exists('/etc/hp/plugin.conf'): self.__plugin_conf_file = "file:///etc/hp/plugin.conf" elif os.path.exists(os.path.join(home, 'plugin.conf')): self.__plugin_conf_file = "file://" + os.path.join(home, 'plugin.conf') else: self.__plugin_conf_file = "http://hplip.sf.net/plugin.conf" #################### Public functions ######################## def download(self, pluginPath='',callback = None): core = core_install.CoreInstall() if pluginPath:# and os.path.exists(pluginPath): src = pluginPath checksum = "" # TBD: Local copy may have different checksum. So ignoring checksum else: sts, url, checksum = self.__getPluginInformation(callback) src = url if sts != ERROR_SUCCESS: return sts, "", queryString(ERROR_CHECKSUM_ERROR, 0, src) log.debug("Downloading %s plug-in file from '%s' to '%s'..." % (self.__required_version, src, self.__plugin_path)) plugin_file = os.path.join(self.__plugin_path, self.__plugin_name) try: os.umask(0) if not os.path.exists(self.__plugin_path): os.makedirs(self.__plugin_path, 0o755) if os.path.exists(plugin_file): os.remove(plugin_file) if os.path.exists(plugin_file+'.asc'): os.remove(plugin_file+'.asc') except (OSError, IOError) as e: log.error("Failed in OS operations:%s "%e.strerror) return ERROR_DIRECTORY_NOT_FOUND, "", self.__plugin_path + queryString(102) try: if src.startswith('file://'): status, filename = utils.download_from_network(src, plugin_file, True) else: wget = utils.which("wget", True) if wget: cmd = "%s --cache=off -P %s %s" % (wget,self.__plugin_path,src) log.debug(cmd) status, output = utils.run(cmd) log.debug("wget returned: %d" % status) #Check whether plugin is accessible in Openprinting.org website otherwise dowload plugin from alternate location. if status != 0 or os_utils.getFileSize(plugin_file) <= 0: src = os.path.join(PLUGIN_FALLBACK_LOCATION, self.__plugin_name) log.info("Plugin is not accessible. Trying to download it from fallback location: [%s]" % src) cmd = "%s --cache=off -P %s %s" % (wget,self.__plugin_path,src) log.debug(cmd) status, output = utils.run(cmd) except IOError as e: log.error("Plug-in download failed: %s" % e.strerror) return ERROR_FILE_NOT_FOUND, "", queryString(ERROR_FILE_NOT_FOUND, 0, plugin_file) if status !=0 or os_utils.getFileSize(plugin_file) <= 0: log.error("Plug-in download failed." ) return ERROR_FILE_NOT_FOUND, "", queryString(ERROR_FILE_NOT_FOUND, 0, plugin_file) if core.isErrorPage(open(plugin_file, 'r').read(1024)): log.debug("open(plugin_file, 'r').read(1024)") os.remove(plugin_file) return ERROR_FILE_NOT_FOUND, "", queryString(ERROR_FILE_NOT_FOUND, 0, plugin_file) # Try to download and check the GPG digital signature digsig_url = src + '.asc' digsig_file = plugin_file + '.asc' log.debug("Downloading %s plug-in digital signature file from '%s' to '%s'..." % (self.__required_version, digsig_url, digsig_file)) try: if digsig_url.startswith('file://'): status, filename = utils.download_from_network(digsig_url, digsig_file, True) else: cmd = "%s --cache=off -P %s %s" % (wget,self.__plugin_path,digsig_url) log.debug(cmd) status, output = utils.run(cmd) except IOError as e: log.error("Plug-in GPG file [%s] download failed: %s" % (digsig_url,e.strerror)) return ERROR_DIGITAL_SIGN_NOT_FOUND, plugin_file, queryString(ERROR_DIGITAL_SIGN_NOT_FOUND, 0, digsig_file) if status !=0: log.error("Plug-in GPG file [%s] download failed." % (digsig_url)) return ERROR_DIGITAL_SIGN_NOT_FOUND, plugin_file, queryString(ERROR_DIGITAL_SIGN_NOT_FOUND, 0, digsig_file) if core.isErrorPage(open(digsig_file, 'r').read(1024)): log.debug(open(digsig_file, 'r').read()) os.remove(digsig_file) return ERROR_DIGITAL_SIGN_NOT_FOUND, plugin_file, queryString(ERROR_DIGITAL_SIGN_NOT_FOUND, 0, digsig_file) sts, error_str = self.__validatePlugin(plugin_file, digsig_file, checksum) return sts, plugin_file, error_str def run_plugin(self, plugin_file, mode=GUI_MODE): result = False log.debug("run_plugin plugin_file =%s mode=%d"%(plugin_file, mode)) cwd = os.getcwd() os.chdir(self.__plugin_path) exec_str = sys.executable if mode == GUI_MODE: cmd = "sh %s --keep --nox11 -- -u %s" % (plugin_file, exec_str) status = os_utils.execute(cmd) else: cmd = "sh %s --keep --nox11 -- -i %s" % (plugin_file, exec_str) status = os_utils.execute(cmd) if status == 0: result = True else: log.error("Python gobject/dbus may be not installed") result = False utils.remove('./plugin_tmp') os.chdir(cwd) return result def copyFiles(self, src_dir): copies = self.__getPluginFilesList(src_dir) os.umask(0) for src, trg, link in copies: if not os.path.exists(src): log.debug("Source file %s does not exist. Skipping." % src) continue if os.path.exists(trg): log.debug("Target file %s already exists. Replacing." % trg) os.remove(trg) trg_dir = os.path.dirname(trg) if not os.path.exists(trg_dir): log.debug("Target directory %s does not exist. Creating." % trg_dir) os.makedirs(trg_dir, 0o755) if not os.path.isdir(trg_dir): log.error("Target directory %s exists but is not a directory. Skipping." % trg_dir) continue try: shutil.copyfile(src, trg) except (IOError, OSError) as e: log.error("File copy failed: %s" % e.strerror) continue else: if not os.path.exists(trg): log.error("Target file %s does not exist. File copy failed." % trg) continue else: os.chmod(trg, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) if link: if os.path.exists(link): log.debug("Symlink already exists. Replacing.") os.remove(link) log.debug("Creating symlink %s (link) to file %s (target)..." %(link, trg)) try: os.symlink(trg, link) except (OSError, IOError) as e: log.debug("Unable to create symlink: %s" % e.strerror) pass log.debug("Updating hplip.state - installed = 1") plugin_state_conf = ConfigBase( PLUGIN_STATE_FILE) plugin_state_conf.set('plugin', "installed", '1') log.debug("Updating hplip.state - eula = 1") plugin_state_conf.set('plugin', "eula", '1') hplip_version = sys_conf.get('hplip', 'version', '0.0.0') log.debug("Updating hplip.state - version = %s"%hplip_version) plugin_state_conf.set('plugin','version', hplip_version) self.__plugin_state = PLUGIN_INSTALLED self.__installed_version = hplip_version return True def uninstall(self): home = sys_conf.get('dirs', 'home') files = self.__getPluginFilesList(home) if len(files) == 0: log.debug("Fail to get Plugin files list") return False for src, trg, link in files: log.debug("Deleting %s,%s files."%(trg,link)) if trg != "": os.unlink(trg) if link != "": os.unlink(link) return True def getInstalledVersion(self): return self.__installed_version def getStatus(self): self.__readPluginStatus() log.debug("Plugin status = %s"%self.__plugin_state) return self.__plugin_state def getFileName(self): return self.__plugin_name def deleteInstallationFiles(self, plugin_file): digsig_file = plugin_file + ".asc" if os.path.exists(plugin_file): os.unlink(plugin_file) if os.path.exists(digsig_file): os.unlink(digsig_file)