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
Exemplo n.º 7
0
    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
Exemplo n.º 8
0
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()
Exemplo n.º 10
0
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 ()
Exemplo n.º 11
0
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
Exemplo n.º 12
0
    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