2 # -*- coding: utf-8 -*-
4 # (c) Copyright 2003-2009 Hewlett-Packard Development Company, L.P.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 __title__ = 'Plugin Download and Install Utility'
39 from base import device, utils, tui, module
44 def plugin_download_callback(c, s, t):
45 pm.update(int(100*c*s/t),
46 utils.format_bytes(c*s))
49 def plugin_install_callback(s):
52 def clean_exit(code=0):
56 USAGE = [ (__doc__, "", "name", True),
57 ("Usage: %s [MODE] [OPTIONS]" % __mod__, "", "summary", True),
60 utils.USAGE_INTERACTIVE_MODE,
61 ("Installation for required printer mode:", "--required (Qt4 only)", "option", False),
62 ("Installation for optional printer mode:", "--optional (Qt4 only)", "option", False),
63 #("Installation generic mode:", "--generic (default)", "option", False),
66 ("Specify the path to the plugin file:", "-p <path> or --path=<path> or --plugin=<path>", "option", False),
67 utils.USAGE_LOGGING1, utils.USAGE_LOGGING2, utils.USAGE_LOGGING3,
71 ("hp-setup", "", "seealso", False),
72 ("hp-firmware", "", "seealso", False),
76 mod = module.Module(__mod__, __title__, __version__, __doc__, USAGE,
77 (INTERACTIVE_MODE, GUI_MODE),
78 (UI_TOOLKIT_QT3, UI_TOOLKIT_QT4), True)
80 opts, device_uri, printer_name, mode, ui_toolkit, loc = \
81 mod.parseStdOpts('p:', ['path=', 'plugin=', 'plug-in=', 'reason=',
82 'generic', 'optional', 'required'],
83 handle_device_printer=False)
86 install_mode = PLUGIN_NONE # reuse plugin types for mode (PLUGIN_NONE = generic)
87 plugin_reason = PLUGIN_REASON_NONE
90 if o in ('-p', '--path', '--plugin', '--plug-in'):
91 plugin_path = os.path.normpath(os.path.abspath(os.path.expanduser(a)))
93 elif o == '--required':
94 install_mode = PLUGIN_REQUIRED
95 if ui_toolkit == 'qt3':
96 log.warn("--required switch ignored.")
98 elif o == '--optional':
99 install_mode = PLUGIN_OPTIONAL
100 if ui_toolkit == 'qt3':
101 log.warn("--optional switch ignored.")
103 elif o == '--reason':
104 plugin_reason = int(a)
107 version = prop.installed_version
108 plugin_filename = 'hplip-%s-plugin.run' % version
110 ok= mod.lockInstance()
112 log.error("Plug-in lock acquire failed. check if hp-plugin is already running")
115 if plugin_path is not None:
116 if not os.path.exists(plugin_path):
117 log.error("Plug-in path '%s' not found." % plugin_path)
120 if os.path.isdir(plugin_path):
121 plugin_path = os.path.join(plugin_path, 'hplip-%s-plugin.run' % version)
123 if not os.path.exists(plugin_path):
124 log.error("Plug-in path '%s' not found." % plugin_path)
127 if os.path.basename(plugin_path) != plugin_filename:
128 log.error("Plug-in filename must be '%s'." % plugin_filename)
132 size, checksum, timestamp = os.stat(plugin_path)[6], '', 0.0
133 plugin_path = 'file://' + plugin_path
134 log.debug("Plugin path=%s (%d)" % (plugin_path, size))
138 if ui_toolkit == 'qt3':
139 if not utils.canEnterGUIMode():
140 log.error("%s requires GUI support (try running with --qt4). Try using interactive (-i) mode." % __mod__)
143 if not utils.canEnterGUIMode4():
144 log.error("%s requires GUI support (try running with --qt3). Try using interactive (-i) mode." % __mod__)
148 PKIT = utils.to_bool(sys_conf.get('configure', 'policy-kit'))
151 from base.pkit import *
154 pkit_installed = True
155 except dbus.DBusException, ex:
156 log.error("PolicyKit support requires DBUS or PolicyKit support files missing")
157 pkit_installed = False
159 log.error("Unable to load pkit...is HPLIP installed?")
160 pkit_installed = False
162 pkit_installed = False
166 if ui_toolkit == 'qt3':
169 from ui import pluginform2
171 log.error("Unable to load Qt3 support. Is it installed?")
174 app = QApplication(sys.argv)
175 QObject.connect(app, SIGNAL("lastWindowClosed()"), app, SLOT("quit()"))
178 loc = user_conf.get('ui', 'loc', 'system')
179 if loc.lower() == 'system':
180 loc = str(QTextCodec.locale())
181 log.debug("Using system locale: %s" % loc)
183 if loc.lower() != 'c':
186 l, x = loc.split('.')
187 loc = '.'.join([l, e])
190 loc = '.'.join([loc, e])
192 log.debug("Trying to load .qm file for %s locale." % loc)
193 trans = QTranslator(None)
195 qm_file = 'hplip_%s.qm' % l
196 log.debug("Name of .qm file: %s" % qm_file)
197 loaded = trans.load(qm_file, prop.localization_dir)
200 app.installTranslator(trans)
205 log.debug("Using default 'C' locale")
207 log.debug("Using locale: %s" % loc)
208 QLocale.setDefault(QLocale(loc))
211 locale.setlocale(locale.LC_ALL, locale.normalize(loc))
215 if not pkit_installed and not os.geteuid() == 0:
216 log.error("You must be root to run this utility.")
218 QMessageBox.critical(None,
219 "HP Device Manager - Plug-in Installer",
220 "You must be root to run hp-plugin.",
222 QMessageBox.NoButton,
223 QMessageBox.NoButton)
227 w = pluginform2.PluginForm2()
235 from PyQt4.QtGui import QApplication, QMessageBox
236 from ui4.plugindialog import PluginDialog
238 log.error("Unable to load Qt4 support. Is it installed?")
241 app = QApplication(sys.argv)
243 if not pkit_installed and not os.geteuid() == 0:
244 log.error("You must be root to run this utility.")
246 QMessageBox.critical(None,
247 "HP Device Manager - Plug-in Installer",
248 "You must be root to run hp-plugin.",
250 QMessageBox.NoButton,
251 QMessageBox.NoButton)
256 dialog = PluginDialog(None, install_mode, plugin_reason)
259 log.debug("Starting GUI loop...")
261 except KeyboardInterrupt:
262 log.error("User exit")
266 else: # INTERACTIVE_MODE
268 if not os.geteuid() == 0:
269 log.error("You must be root to run this utility.")
272 log.info("(Note: Defaults for each question are maked with a '*'. Press <enter> to accept the default.)")
275 from installer import core_install
276 core = core_install.CoreInstall()
278 core.set_plugin_version()
280 tui.header("PLUG-IN INSTALLATION FOR HPLIP %s" % version)
282 if core.check_for_plugin() == PLUGIN_INSTALLED and plugin_path is None:
283 log.info("The driver plugin for HPLIP %s appears to already be installed." % version)
285 cont, ans = tui.enter_yes_no("Do you wish to download and re-install the plug-in?")
287 if not cont or not ans:
291 if plugin_path is None:
292 table = tui.Formatter(header=('Option', 'Description'), min_widths=(10, 50))
293 table.add(('d', 'Download plug-in from HP (recomended)'))
294 table.add(('p', 'Specify a path to the plug-in (advanced)'))
295 table.add(('q', 'Quit hp-plugin (skip installation)'))
299 cont, ans = tui.enter_choice("\nEnter option (d=download*, p=specify path, q=quit) ? ",
306 if ans == 'd': # d - download
307 # read plugin.conf (local or on sf.net) to get plugin_path (http://)
308 plugin_conf_url = core.get_plugin_conf_url()
310 if plugin_conf_url.startswith('file://'):
311 tui.header("COPY CONFIGURATION")
313 tui.header("DOWNLOAD CONFIGURATION")
315 log.info("Checking for network connection...")
316 ok = core.check_network_connection()
319 log.error("Network connection not detected.")
323 log.info("Downloading configuration file from: %s" % plugin_conf_url)
324 pm = tui.ProgressMeter("Downloading configuration:")
326 plugin_path, size, checksum, timestamp, ok = core.get_plugin_info(plugin_conf_url,
327 plugin_download_callback)
331 if not plugin_path.startswith('http://') and not plugin_path.startswith('file://'):
332 plugin_path = 'file://' + plugin_path
334 else: # p - specify plugin path
337 plugin_path = raw_input(log.bold("Enter the path to the 'hplip-%s-plugin.run' file (q=quit) : " %
340 if plugin_path.strip().lower() == 'q':
343 if not plugin_path.startswith('http://'):
344 plugin_path = os.path.normpath(os.path.abspath(os.path.expanduser(plugin_path)))
346 if not os.path.exists(plugin_path):
347 log.error("Plug-in path '%s' not found." % plugin_path)
350 if os.path.isdir(plugin_path):
351 plugin_path = os.path.join(plugin_path, plugin_filename)
353 if not os.path.exists(plugin_path):
354 log.error("Plug-in path '%s' not found." % plugin_path)
357 if os.path.basename(plugin_path) != plugin_filename:
358 log.error("Plug-in filename must be '%s'." % plugin_filename)
361 size, checksum, timestamp = os.stat(plugin_path)[6], '', 0.0
362 plugin_path = 'file://' + plugin_path
367 if plugin_path.startswith('file://'):
368 tui.header("COPY PLUGIN")
370 tui.header("DOWNLOAD PLUGIN")
372 log.info("Checking for network connection...")
373 ok = core.check_network_connection()
376 log.error("Network connection not detected.")
379 log.info("Downloading plug-in from: %s" % plugin_path)
380 pm = tui.ProgressMeter("Downloading plug-in:")
382 status, ret = core.download_plugin(plugin_path, size, checksum, timestamp, plugin_download_callback)
385 if status in (core_install.PLUGIN_INSTALL_ERROR_UNABLE_TO_RECV_KEYS, core_install.PLUGIN_INSTALL_ERROR_DIGITAL_SIG_NOT_FOUND):
386 log.error("Digital signature file download failed. Without this file, it is not possible to authenticate and validate the plug-in prior to installation.")
387 cont, ans = tui.enter_yes_no("Do you still want to install the plug-in?", 'n')
389 if not cont or not ans:
392 elif status != core_install.PLUGIN_INSTALL_ERROR_NONE:
394 if status == core_install.PLUGIN_INSTALL_ERROR_PLUGIN_FILE_NOT_FOUND:
395 desc = "Plug-in file not found (server returned 404 or similar error). Error code: %s" % str(ret)
397 elif status == core_install.PLUGIN_INSTALL_ERROR_DIGITAL_SIG_BAD:
398 desc = "Plug-in file does not match its digital signature. File may have been corrupted or altered. Error code: %s" % str(ret)
400 elif status == core_install.PLUGIN_INSTALL_ERROR_PLUGIN_FILE_CHECKSUM_ERROR:
401 desc = "Plug-in file does not match its checksum. File may have been corrupted or altered."
403 elif status == core_install.PLUGIN_INSTALL_ERROR_NO_NETWORK:
404 desc = "Unable to connect to network to download the plug-in. Please check your network connection and try again."
406 elif status == core_install.PLUGIN_INSTALL_ERROR_DIRECTORY_ERROR:
407 desc = "Unable to create the plug-in directory. Please check your permissions and try again."
414 tui.header("INSTALLING PLUG-IN")
416 core.run_plugin(mode, plugin_install_callback)
418 cups_devices = device.getSupportedCUPSDevices(['hp']) #, 'hpfax'])
423 for dev in cups_devices:
424 mq = device.queryModelByURI(dev)
426 if mq.get('fw-download', 0):
429 tui.header("DOWNLOADING FIRMWARE")
432 # Download firmware if needed
433 log.info(log.bold("\nDownloading firmware to device %s..." % dev))
435 d = device.Device(dev)
437 log.error("Error opening device. Exiting.")
440 if d.downloadFirmware():
441 log.info("Firmware download successful.\n")
446 except KeyboardInterrupt:
447 log.error("User exit")