class CheckSELinux(Question): def __init__(self, troubleshooter): Question.__init__(self, troubleshooter, "Check SELinux contexts") troubleshooter.new_page(Gtk.Label(), self) def display(self): self.answers = {} #answers = self.troubleshooter.answers RESTORECON = "/sbin/restorecon" if not os.access(RESTORECON, os.X_OK): return False try: import selinux except ImportError: return False if not selinux.is_selinux_enabled(): return False paths = ["/etc/cups/", "/usr/lib/cups/", "/usr/share/cups/"] null = file("/dev/null", "r+") parent = self.troubleshooter.get_window() contexts = {} new_environ = os.environ.copy() new_environ['LC_ALL'] = "C" restorecon_args = [RESTORECON, "-nvR"].extend(paths) try: # Run restorecon -nvR self.op = TimedSubprocess(parent=parent, args=restorecon_args, close_fds=True, env=new_environ, stdin=null, stdout=subprocess.PIPE, stderr=null) (restorecon_stdout, restorecon_stderr, result) = self.op.run() except: # Problem executing command. return False for line in restorecon_stdout: l = shlex.split(line) if (len(l) < 1): continue contexts[l[2]] = l[4] self.answers['selinux_contexts'] = contexts return False def collect_answer(self): return self.answers def cancel_operation(self): self.op.cancel()
class CheckSELinux(Question): def __init__ (self, troubleshooter): Question.__init__ (self, troubleshooter, "Check SELinux contexts") troubleshooter.new_page (Gtk.Label (), self) def display (self): self.answers = {} #answers = self.troubleshooter.answers RESTORECON = "/sbin/restorecon" if not os.access (RESTORECON, os.X_OK): return False try: import selinux except ImportError: return False if not selinux.is_selinux_enabled(): return False paths = ["/etc/cups/", "/usr/lib/cups/", "/usr/share/cups/"] null = open ("/dev/null", "r+") parent = self.troubleshooter.get_window () contexts = {} new_environ = os.environ.copy() new_environ['LC_ALL'] = "C" restorecon_args = [RESTORECON, "-nvR"].extend(paths) try: # Run restorecon -nvR self.op = TimedSubprocess (parent=parent, args=restorecon_args, close_fds=True, env=new_environ, stdin=null, stdout=subprocess.PIPE, stderr=null) (restorecon_stdout, restorecon_stderr, result) = self.op.run () except: # Problem executing command. return False for line in restorecon_stdout: l = shlex.split (line) if (len (l) < 1): continue contexts[l[2]] = l[4] self.answers['selinux_contexts'] = contexts return False def collect_answer (self): return self.answers def cancel_operation (self): self.op.cancel ()
class VerifyPackages(Question): def __init__ (self, troubleshooter): Question.__init__ (self, troubleshooter, "Verify packages") troubleshooter.new_page (Gtk.Label (), self) def display (self): self.answers = {} packages_verification = {} package_manager="/bin/rpm" if not os.access (package_manager, os.X_OK): return False packages = ["cups", "foomatic", "gutenprint", "hpijs", "hplip", "system-config-printer"] null = open ("/dev/null", "r+") parent = self.troubleshooter.get_window () new_environ = os.environ.copy() new_environ['LC_ALL'] = "C" for package in packages: verification_args = [package_manager, "-V", package] try: self.op = TimedSubprocess (parent=parent, args=verification_args, close_fds=True, env=new_environ, stdin=null, stdout=subprocess.PIPE, stderr=null) (verif_stdout, verif_stderr, result) = self.op.run () except: # Problem executing command. return False packages_verification[package] = verif_stdout[:-1] self.answers['packages_verification'] = packages_verification return False def collect_answer (self): return self.answers def cancel_operation (self): self.op.cancel ()
class VerifyPackages(Question): def __init__(self, troubleshooter): Question.__init__(self, troubleshooter, "Verify packages") troubleshooter.new_page(Gtk.Label(), self) def display(self): self.answers = {} packages_verification = {} package_manager = "/bin/rpm" if not os.access(package_manager, os.X_OK): return False packages = [ "cups", "foomatic", "gutenprint", "hpijs", "hplip", "system-config-printer" ] null = file("/dev/null", "r+") parent = self.troubleshooter.get_window() new_environ = os.environ.copy() new_environ['LC_ALL'] = "C" for package in packages: verification_args = [package_manager, "-V", package] try: self.op = TimedSubprocess(parent=parent, args=verification_args, close_fds=True, env=new_environ, stdin=null, stdout=subprocess.PIPE, stderr=null) (verif_stdout, verif_stderr, result) = self.op.run() except: # Problem executing command. return False packages_verification[package] = verif_stdout[:-1] self.answers['packages_verification'] = packages_verification return False def collect_answer(self): return self.answers def cancel_operation(self): self.op.cancel()
class CheckNetworkServerSanity(Question): def __init__ (self, troubleshooter): Question.__init__ (self, troubleshooter, "Check network server sanity") troubleshooter.new_page (Gtk.Label (), self) def display (self): # Collect useful information. self.answers = {} answers = self.troubleshooter.answers if (not answers.has_key ('remote_server_name') and not answers.has_key ('remote_server_ip_address')): return False parent = self.troubleshooter.get_window () server_name = answers['remote_server_name'] server_port = answers.get('remote_server_port', 631) try_connect = False if server_name: # Try resolving the hostname. try: ai = socket.getaddrinfo (server_name, server_port) resolves = map (lambda (family, socktype, proto, canonname, sockaddr): sockaddr[0], ai) try_connect = True except socket.gaierror: resolves = False self.answers['remote_server_name_resolves'] = resolves ipaddr = answers.get ('remote_server_ip_address', '') if resolves: if ipaddr: try: resolves.index (ipaddr) except ValueError: # The IP address given doesn't match the server name. # Use the IP address instead of the name. server_name = ipaddr try_connect = True elif ipaddr: server_name = ipaddr try_connect = True else: server_name = answers['remote_server_ip_address'] # Validate it. try: ai = socket.getaddrinfo (server_name, server_port) resolves = map (lambda (family, socktype, proto, canonname, sockaddr): sockaddr[0], ai) except socket.gaierror: resolves = False self.answers['remote_server_name_resolves'] = resolves try_connect = True self.answers['remote_server_try_connect'] = server_name if (try_connect and answers.get ('cups_device_uri_scheme', 'ipp') in ['ipp', 'http', 'https']): if answers.get ('cups_device_uri_scheme') == 'https': encryption = cups.HTTP_ENCRYPT_REQUIRED else: encryption = cups.HTTP_ENCRYPT_IF_REQUESTED try: self.op = TimedOperation (cups.Connection, kwargs={"host": server_name, "port": server_port, "encryption": encryption}, parent=parent) c = self.op.run () ipp_connect = True except RuntimeError: ipp_connect = False self.answers['remote_server_connect_ipp'] = ipp_connect if ipp_connect: try: self.op = TimedOperation (c.getPrinters, parent=parent) self.op.run () cups_server = True except: cups_server = False self.answers['remote_server_cups'] = cups_server if cups_server: cups_printer_dict = answers.get ('cups_printer_dict', {}) uri = cups_printer_dict.get ('device-uri', None) if uri: try: self.op = TimedOperation (c.getPrinterAttributes, kwargs={"uri": uri}, parent=parent) attr = self.op.run () self.answers['remote_cups_queue_attributes'] = attr except: pass if try_connect: # Try to see if we can connect using smbc. context = None try: context = smbc.Context () name = self.answers['remote_server_try_connect'] self.op = TimedOperation (context.opendir, args=("smb://%s/" % name,), parent=parent) dir = self.op.run () self.op = TimedOperation (dir.getdents, parent=parent) shares = self.op.run () self.answers['remote_server_smb'] = True self.answers['remote_server_smb_shares'] = shares except NameError: # No smbc support pass except RuntimeError as e: (e, s) = e.args self.answers['remote_server_smb_shares'] = (e, s) if context != None and answers.has_key ('cups_printer_dict'): uri = answers['cups_printer_dict'].get ('device-uri', '') u = smburi.SMBURI (uri) (group, host, share, user, password) = u.separate () accessible = False try: self.op = TimedOperation (context.open, args=("smb://%s/%s" % (host, share), os.O_RDWR, 0777), parent=parent) f = self.op.run () accessible = True except RuntimeError as e: (e, s) = e.args accessible = (e, s) self.answers['remote_server_smb_share_anon_access'] = accessible # Try traceroute if we haven't already. if (try_connect and not answers.has_key ('remote_server_traceroute')): try: self.op = TimedSubprocess (parent=parent, close_fds=True, args=['traceroute', '-w', '1', server_name], stdin=file("/dev/null"), stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.answers['remote_server_traceroute'] = self.op.run () except: # Problem executing command. pass return False def collect_answer (self): return self.answers def cancel_operation (self): self.op.cancel ()
class CheckPPDSanity(Question): def __init__ (self, troubleshooter): Question.__init__ (self, troubleshooter, "Check PPD sanity") vbox = Gtk.VBox () vbox.set_border_width (12) vbox.set_spacing (12) self.label = Gtk.Label () self.label.set_line_wrap (True) self.label.set_use_markup (True) self.label.set_alignment (0, 0) vbox.pack_start (self.label, False, False, 0) box = Gtk.HButtonBox () box.set_layout (Gtk.ButtonBoxStyle.START) self.install_button = Gtk.Button.new_with_label (_("Install")) box.add (self.install_button) # Although we want this hidden initially, # troubleshooter.new_page will call show_all() on the widget # we give it. We'll need to hide this button in the display() # callback instead. vbox.pack_start (box, False, False, 0) troubleshooter.new_page (vbox, self) def display (self): self.answers = {} answers = self.troubleshooter.answers if not answers['cups_queue_listed']: return False parent = self.troubleshooter.get_window () name = answers['cups_queue'] tmpf = None try: cups.setServer ('') self.op = TimedOperation (cups.Connection, parent=parent) c = self.op.run () self.op = TimedOperation (c.getPPD, args=(name,), parent=parent) tmpf = self.op.run () except RuntimeError: return False except cups.IPPError: return False self.install_button.hide () title = None text = None try: ppd = cups.PPD (tmpf) self.answers['cups_printer_ppd_valid'] = True def options (options_list): o = {} for option in options_list: o[option.keyword] = option.defchoice return o defaults = {} for group in ppd.optionGroups: g = options (group.options) for subgroup in group.subgroups: g[subgroup.name] = options (subgroup.options) defaults[group.name] = g self.answers['cups_printer_ppd_defaults'] = defaults except RuntimeError: title = _("Invalid PPD File") self.answers['cups_printer_ppd_valid'] = False try: self.op = TimedSubprocess (parent=parent, args=['cupstestppd', '-rvv', tmpf], close_fds=True, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = self.op.run () self.answers['cupstestppd_output'] = result text = _("The PPD file for printer '%s' does not conform " "to the specification. " "Possible reason follows:") % name text += '\n' + reduce (lambda x, y: x + '\n' + y, result[0]) except OSError: # Perhaps cupstestppd is not in the path. text = _("There is a problem with the PPD file for " "printer '%s'.") % name if tmpf: os.unlink (tmpf) if title == None and not answers['cups_printer_remote']: (pkgs, exes) = cupshelpers.missingPackagesAndExecutables (ppd) self.answers['missing_pkgs_and_exes'] = (pkgs, exes) if len (pkgs) > 0 or len (exes) > 0: title = _("Missing Printer Driver") if len (pkgs) > 0: try: self.packagekit = installpackage.PackageKit () except: pkgs = [] if len (pkgs) > 0: self.package = pkgs[0] text = _("Printer '%s' requires the %s package but it " "is not currently installed.") % (name, self.package) self.install_button.show () else: text = _("Printer '%s' requires the '%s' program but it " "is not currently installed.") % (name, (exes + pkgs)[0]) if title != None: self.label.set_markup ('<span weight="bold" size="larger">' + title + '</span>\n\n' + text) return title != None def connect_signals (self, handle): self.button_sigid = self.install_button.connect ("clicked", self.install_clicked) def disconnect_signals (self): self.install_button.disconnect (self.button_sigid) def collect_answer (self): return self.answers def cancel_operation (self): self.op.cancel () def install_clicked (self, button): pkgs = self.answers.get('packages_installed', []) pkgs.append (self.package) self.answers['packages_installed'] = pkgs try: self.packagekit.InstallPackageName (0, 0, self.package) except: pass
def display (self): # Collect information useful for the various checks. self.answers = {} answers = self.troubleshooter.answers if not answers['cups_queue_listed']: return False name = answers['cups_queue'] parent = self.troubleshooter.get_window () # Find out if this is a printer or a class. try: cups.setServer ('') c = TimedOperation (cups.Connection, parent=parent).run () printers = TimedOperation (c.getPrinters, parent=parent).run () if printers.has_key (name): self.answers['is_cups_class'] = False queue = printers[name] self.answers['cups_printer_dict'] = queue else: self.answers['is_cups_class'] = True classes = TimedOperation (c.getClasses, parent=parent).run () queue = classes[name] self.answers['cups_class_dict'] = queue attrs = TimedOperation (c.getPrinterAttributes, (name,), parent=parent).run () self.answers['local_cups_queue_attributes'] = attrs except: pass if self.answers.has_key ('cups_printer_dict'): cups_printer_dict = self.answers['cups_printer_dict'] uri = cups_printer_dict['device-uri'] (scheme, rest) = urllib.splittype (uri) self.answers['cups_device_uri_scheme'] = scheme if scheme in ["ipp", "http", "https"]: (hostport, rest) = urllib.splithost (rest) (host, port) = urllib.splitnport (hostport, defport=631) self.answers['remote_server_name'] = host self.answers['remote_server_port'] = port elif scheme == "smb": u = smburi.SMBURI (uri) (group, host, share, user, password) = u.separate () new_environ = os.environ.copy() new_environ['LC_ALL'] = "C" if group: args = ["nmblookup", "-W", group, host] else: args = ["nmblookup", host] try: p = TimedSubprocess (parent=parent, timeout=5000, args=args, env=new_environ, close_fds=True, stdin=file("/dev/null"), stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = p.run () self.answers['nmblookup_output'] = result for line in result[0]: if line.startswith ("querying"): continue spc = line.find (' ') if (spc != -1 and not line[spc:].startswith (" failed ")): # Remember the IP address. self.answers['remote_server_name'] = line[:spc] break except OSError: # Problem executing command. pass elif scheme == "hp": new_environ = os.environ.copy() new_environ['LC_ALL'] = "C" new_environ['DISPLAY'] = "" try: p = TimedSubprocess (parent=parent, timeout=3000, args=["hp-info", "-d" + uri], close_fds=True, env=new_environ, stdin=file("/dev/null"), stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.answers['hplip_output'] = p.run () except OSError: # Problem executing command. pass r = cups_printer_dict['printer-type'] & cups.CUPS_PRINTER_REMOTE self.answers['cups_printer_remote'] = (r != 0) return False
class CheckUSBPermissions(Question): def __init__(self, troubleshooter): Question.__init__(self, troubleshooter, "Check USB permissions") troubleshooter.new_page(Gtk.Label(), self) def display(self): self.answers = {} answers = self.troubleshooter.answers if answers['cups_queue_listed']: if answers['is_cups_class']: return False cups_printer_dict = answers['cups_printer_dict'] device_uri = cups_printer_dict['device-uri'] elif answers.get('cups_device_listed', False): device_uri = answers['cups_device_uri'] else: return False (scheme, rest) = urllib.parse.splittype(device_uri) if scheme not in ['hp', 'hpfax', 'usb', 'hal']: return False LSUSB = "/sbin/lsusb" if not os.access(LSUSB, os.X_OK): return False GETFACL = "/usr/bin/getfacl" if not os.access(GETFACL, os.X_OK): return False new_environ = os.environ.copy() new_environ['LC_ALL'] = "C" # Run lsusb parent = self.troubleshooter.get_window() try: self.op = TimedSubprocess(parent=parent, args=[LSUSB, "-v"], close_fds=True, env=new_environ, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (lsusb_stdout, lsusb_stderr, result) = self.op.run() except: # Problem executing command. return False # Now parse it. dev_by_id = {} this_dev = None for line in lsusb_stdout: if (this_dev is not None and ((line.find("bInterfaceClass") != -1 and line.find("7 Printer") != -1) or (line.find("bInterfaceSubClass") != -1 and line.find("1 Printer") != -1))): mfr = dev_by_id.get(this_mfr_id, {}) mdl = mfr.get(this_mdl_id, []) mdl.append(this_dev) mfr[this_mdl_id] = mdl dev_by_id[this_mfr_id] = mfr this_dev = None continue separators = [('Bus ', 3), (' Device ', 3), (': ID ', 4), (':', 4), (' ', -1)] fields = [] i = 0 p = line while i < len(separators): (sep, length) = separators[i] if not p.startswith(sep): break start = len(sep) if length == -1: end = len(p) fields.append(p[start:]) else: end = start + length fields.append(p[start:end]) p = p[end:] i += 1 if i < len(separators): continue if not scheme.startswith('hp') and fields[2] != '03f0': # Skip non-HP printers if we know we're using HPLIP. continue this_dev = { 'bus': fields[0], 'dev': fields[1], 'name': fields[4], 'full': line } this_mfr_id = fields[2] this_mdl_id = fields[3] infos = {} paths = [] if not scheme.startswith('hp'): paths.extend(glob.glob("/dev/usb/lp?")) for mfr_id, mdls in dev_by_id.items(): for mdl_id, devs in mdls.items(): for dev in devs: path = "/dev/bus/usb/%s/%s" % (dev['bus'], dev['dev']) paths.append(path) infos[path] = dev['full'] perms = [] for path in paths: try: self.op = TimedSubprocess(parent=parent, args=[GETFACL, path], close_fds=True, env=new_environ, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (getfacl_stdout, getfacl_stderr, result) = self.op.run() output = [x for x in getfacl_stdout if len(x) > 0] except: # Problem executing command. output = [] info = infos.get(path, path) perms.append((info, output)) self.answers['getfacl_output'] = perms # Don't actually display anything, just collect information. return False def collect_answer(self): return self.answers def cancel_operation(self): self.op.cancel()
class CheckNetworkServerSanity(Question): def __init__(self, troubleshooter): Question.__init__(self, troubleshooter, "Check network server sanity") troubleshooter.new_page(Gtk.Label(), self) def display(self): # Collect useful information. self.answers = {} answers = self.troubleshooter.answers if ('remote_server_name' not in answers and 'remote_server_ip_address' not in answers): return False parent = self.troubleshooter.get_window() server_name = answers['remote_server_name'] server_port = answers.get('remote_server_port', 631) try_connect = False if server_name: # Try resolving the hostname. try: ai = socket.getaddrinfo(server_name, server_port) resolves = [ family_socktype_proto_canonname_sockaddr[4][0] for family_socktype_proto_canonname_sockaddr in ai ] try_connect = True except socket.gaierror: resolves = False self.answers['remote_server_name_resolves'] = resolves ipaddr = answers.get('remote_server_ip_address', '') if resolves: if ipaddr: try: resolves.index(ipaddr) except ValueError: # The IP address given doesn't match the server name. # Use the IP address instead of the name. server_name = ipaddr try_connect = True elif ipaddr: server_name = ipaddr try_connect = True else: server_name = answers['remote_server_ip_address'] # Validate it. try: ai = socket.getaddrinfo(server_name, server_port) resolves = [ family_socktype_proto_canonname_sockaddr1[4][0] for family_socktype_proto_canonname_sockaddr1 in ai ] except socket.gaierror: resolves = False self.answers['remote_server_name_resolves'] = resolves try_connect = True self.answers['remote_server_try_connect'] = server_name if (try_connect and answers.get('cups_device_uri_scheme', 'ipp') in ['ipp', 'http', 'https']): if answers.get('cups_device_uri_scheme') == 'https': encryption = cups.HTTP_ENCRYPT_REQUIRED else: encryption = cups.HTTP_ENCRYPT_IF_REQUESTED try: self.op = TimedOperation(cups.Connection, kwargs={ "host": server_name, "port": server_port, "encryption": encryption }, parent=parent) c = self.op.run() ipp_connect = True except RuntimeError: ipp_connect = False self.answers['remote_server_connect_ipp'] = ipp_connect if ipp_connect: try: self.op = TimedOperation(c.getPrinters, parent=parent) self.op.run() cups_server = True except: cups_server = False self.answers['remote_server_cups'] = cups_server if cups_server: cups_printer_dict = answers.get('cups_printer_dict', {}) uri = cups_printer_dict.get('device-uri', None) if uri: try: self.op = TimedOperation(c.getPrinterAttributes, kwargs={"uri": uri}, parent=parent) attr = self.op.run() self.answers['remote_cups_queue_attributes'] = attr except: pass if try_connect: # Try to see if we can connect using smbc. context = None try: context = smbc.Context() name = self.answers['remote_server_try_connect'] self.op = TimedOperation(context.opendir, args=("smb://%s/" % name, ), parent=parent) dir = self.op.run() self.op = TimedOperation(dir.getdents, parent=parent) shares = self.op.run() self.answers['remote_server_smb'] = True self.answers['remote_server_smb_shares'] = shares except NameError: # No smbc support pass except RuntimeError as e: (e, s) = e.args self.answers['remote_server_smb_shares'] = (e, s) if context != None and 'cups_printer_dict' in answers: uri = answers['cups_printer_dict'].get('device-uri', '') u = smburi.SMBURI(uri) (group, host, share, user, password) = u.separate() accessible = False try: self.op = TimedOperation( context.open, args=("smb://%s/%s" % (host, share), os.O_RDWR, 0o777), parent=parent) f = self.op.run() accessible = True except RuntimeError as e: (e, s) = e.args accessible = (e, s) self.answers[ 'remote_server_smb_share_anon_access'] = accessible # Try traceroute if we haven't already. if (try_connect and 'remote_server_traceroute' not in answers): try: self.op = TimedSubprocess( parent=parent, close_fds=True, args=['traceroute', '-w', '1', server_name], stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.answers['remote_server_traceroute'] = self.op.run() except: # Problem executing command. pass return False def collect_answer(self): return self.answers def cancel_operation(self): self.op.cancel()
class CheckUSBPermissions(Question): def __init__ (self, troubleshooter): Question.__init__ (self, troubleshooter, "Check USB permissions") troubleshooter.new_page (Gtk.Label (), self) def display (self): self.answers = {} answers = self.troubleshooter.answers if answers['cups_queue_listed']: if answers['is_cups_class']: return False cups_printer_dict = answers['cups_printer_dict'] device_uri = cups_printer_dict['device-uri'] elif answers.get ('cups_device_listed', False): device_uri = answers['cups_device_uri'] else: return False (scheme, rest) = urllib.splittype (device_uri) if scheme not in ['hp', 'hpfax', 'usb', 'hal']: return False LSUSB = "/sbin/lsusb" if not os.access (LSUSB, os.X_OK): return False GETFACL = "/usr/bin/getfacl" if not os.access (GETFACL, os.X_OK): return False new_environ = os.environ.copy() new_environ['LC_ALL'] = "C" # Run lsusb parent = self.troubleshooter.get_window () try: self.op = TimedSubprocess (parent=parent, args=[LSUSB, "-v"], close_fds=True, env=new_environ, stdin=file("/dev/null"), stdout=subprocess.PIPE, stderr=subprocess.PIPE) (lsusb_stdout, lsusb_stderr, result) = self.op.run () except: # Problem executing command. return False # Now parse it. dev_by_id = {} this_dev = None for line in lsusb_stdout: if (this_dev != None and ((line.find ("bInterfaceClass") != -1 and line.find ("7 Printer") != -1) or (line.find ("bInterfaceSubClass") != -1 and line.find ("1 Printer") != -1))): mfr = dev_by_id.get (this_mfr_id, {}) mdl = mfr.get (this_mdl_id, []) mdl.append (this_dev) mfr[this_mdl_id] = mdl dev_by_id[this_mfr_id] = mfr this_dev = None continue separators = [ ('Bus ', 3), (' Device ', 3), (': ID ', 4), (':', 4), (' ', -1)] fields = [] i = 0 p = line while i < len (separators): (sep, length) = separators[i] if not p.startswith (sep): break start = len (sep) if length == -1: end = len (p) fields.append (p[start:]) else: end = start + length fields.append (p[start:end]) p = p[end:] i += 1 if i < len (separators): continue if not scheme.startswith ('hp') and fields[2] != '03f0': # Skip non-HP printers if we know we're using HPLIP. continue this_dev = { 'bus': fields[0], 'dev': fields[1], 'name': fields[4], 'full': line } this_mfr_id = fields[2] this_mdl_id = fields[3] infos = {} paths = [] if not scheme.startswith ('hp'): paths.extend (glob.glob ("/dev/usb/lp?")) for mfr_id, mdls in dev_by_id.iteritems (): for mdl_id, devs in mdls.iteritems (): for dev in devs: path = "/dev/bus/usb/%s/%s" % (dev['bus'], dev['dev']) paths.append (path) infos[path] = dev['full'] perms = [] for path in paths: try: self.op = TimedSubprocess (parent=parent, args=[GETFACL, path], close_fds=True, env=new_environ, stdin=file("/dev/null"), stdout=subprocess.PIPE, stderr=subprocess.PIPE) (getfacl_stdout, getfacl_stderr, result) = self.op.run () output = filter (lambda x: len (x) > 0, getfacl_stdout) except: # Problem executing command. output = [] info = infos.get (path, path) perms.append ((info, output)) self.answers['getfacl_output'] = perms # Don't actually display anything, just collect information. return False def collect_answer (self): return self.answers def cancel_operation (self): self.op.cancel ()
class CheckPPDSanity(Question): def __init__(self, troubleshooter): Question.__init__(self, troubleshooter, "Check PPD sanity") vbox = Gtk.VBox() vbox.set_border_width(12) vbox.set_spacing(12) self.label = Gtk.Label() self.label.set_line_wrap(True) self.label.set_use_markup(True) self.label.set_alignment(0, 0) vbox.pack_start(self.label, False, False, 0) box = Gtk.HButtonBox() box.set_layout(Gtk.ButtonBoxStyle.START) self.install_button = Gtk.Button.new_with_label(_("Install")) box.add(self.install_button) # Although we want this hidden initially, # troubleshooter.new_page will call show_all() on the widget # we give it. We'll need to hide this button in the display() # callback instead. vbox.pack_start(box, False, False, 0) troubleshooter.new_page(vbox, self) def display(self): self.answers = {} answers = self.troubleshooter.answers if not answers['cups_queue_listed']: return False parent = self.troubleshooter.get_window() name = answers['cups_queue'] tmpf = None try: cups.setServer('') self.op = TimedOperation(cups.Connection, parent=parent) c = self.op.run() self.op = TimedOperation(c.getPPD, args=(name, ), parent=parent) tmpf = self.op.run() except RuntimeError: return False except cups.IPPError: return False self.install_button.hide() title = None text = None try: ppd = cups.PPD(tmpf) self.answers['cups_printer_ppd_valid'] = True def options(options_list): o = {} for option in options_list: o[option.keyword] = option.defchoice return o defaults = {} for group in ppd.optionGroups: g = options(group.options) for subgroup in group.subgroups: g[subgroup.name] = options(subgroup.options) defaults[group.name] = g self.answers['cups_printer_ppd_defaults'] = defaults except RuntimeError: title = _("Invalid PPD File") self.answers['cups_printer_ppd_valid'] = False try: self.op = TimedSubprocess(parent=parent, args=['cupstestppd', '-rvv', tmpf], close_fds=True, stdin=file("/dev/null"), stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = self.op.run() self.answers['cupstestppd_output'] = result text = _("The PPD file for printer '%s' does not conform " "to the specification. " "Possible reason follows:") % name text += '\n' + reduce(lambda x, y: x + '\n' + y, result[0]) except OSError: # Perhaps cupstestppd is not in the path. text = _("There is a problem with the PPD file for " "printer '%s'.") % name if tmpf: os.unlink(tmpf) if title == None and not answers['cups_printer_remote']: (pkgs, exes) = cupshelpers.missingPackagesAndExecutables(ppd) self.answers['missing_pkgs_and_exes'] = (pkgs, exes) if len(pkgs) > 0 or len(exes) > 0: title = _("Missing Printer Driver") if len(pkgs) > 0: try: self.packagekit = installpackage.PackageKit() except: pkgs = [] if len(pkgs) > 0: self.package = pkgs[0] text = _( "Printer '%s' requires the %s package but it " "is not currently installed.") % (name, self.package) self.install_button.show() else: text = _( "Printer '%s' requires the '%s' program but it " "is not currently installed.") % (name, (exes + pkgs)[0]) if title != None: self.label.set_markup('<span weight="bold" size="larger">' + title + '</span>\n\n' + text) return title != None def connect_signals(self, handle): self.button_sigid = self.install_button.connect( "clicked", self.install_clicked) def disconnect_signals(self): self.install_button.disconnect(self.button_sigid) def collect_answer(self): return self.answers def cancel_operation(self): self.op.cancel() def install_clicked(self, button): pkgs = self.answers.get('packages_installed', []) pkgs.append(self.package) self.answers['packages_installed'] = pkgs try: self.packagekit.InstallPackageName(0, 0, self.package) except: pass