def __init__ (self, parent=None, try_as_root=True, lock=False, host=None, port=None, encryption=None): if host != None: cups.setServer (host) if port != None: cups.setPort (port) if encryption != None: cups.setEncryption (encryption) self._use_password = '' self._parent = parent self._try_as_root = try_as_root self._use_user = cups.getUser () self._server = cups.getServer () self._port = cups.getPort() self._encryption = cups.getEncryption () self._prompt_allowed = True self._operation_stack = [] self._lock = lock self._gui_event = threading.Event () creds = global_authinfocache.lookup_auth_info (host=host, port=port) if creds != None: if (creds[0] != 'root' or try_as_root): (self._use_user, self._use_password) = creds del creds self._connect ()
def fetch_jobs (self, refresh_all): if not self.process_pending_events: # Skip this call. We'll get called again soon. return True user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) except RuntimeError: self.watcher.cups_connection_error (self) self.fetch_jobs_timer = None cups.setUser (user) return False limit = 1 try: fetched = c.getJobs (which_jobs=self.which_jobs, my_jobs=self.my_jobs, first_job_id=self.fetch_first_job_id, limit=limit) except cups.IPPError, (e, m): self.watcher.cups_ipp_error (self, e, m) self.fetch_jobs_timer = None cups.setUser (user) return False
def refresh(self, which_jobs=None, refresh_all=True): debugprint ("refresh") self.emit ('refresh') if which_jobs != None: self.which_jobs = which_jobs user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) except RuntimeError: self.emit ('cups-connection-error') cups.setUser (user) return if self.sub_id != -1: try: c.cancelSubscription (self.sub_id) except cups.IPPError, (e, m): self.emit ('cups-ipp-error', e, m) if self.update_timer: gobject.source_remove (self.update_timer) debugprint ("Canceled subscription %d" % self.sub_id)
def run (self): if self.host == None: self.host = cups.getServer () if self.port == None: self.port = cups.getPort () if self._encryption == None: self._encryption = cups.getEncryption () if self.user: cups.setUser (self.user) else: self.user = cups.getUser () try: cups.setPasswordCB2 (self._auth) except AttributeError: # Requires pycups >= 1.9.47. Fall back to rubbish API. cups.setPasswordCB (self._auth) try: conn = cups.Connection (host=self.host, port=self.port, encryption=self._encryption) self._reply (None) except RuntimeError, e: conn = None self._error (e)
def cleanup (self): if self.sub_id != -1: user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) c.cancelSubscription (self.sub_id) debugprint ("Canceled subscription %d" % self.sub_id) except: pass cups.setUser (user) if self.bus is not None: self.bus.remove_signal_receiver (self.handle_dbus_signal, path=self.DBUS_PATH, dbus_interface=self.DBUS_IFACE) timers = list(self.connecting_timers.values ()) for timer in [self.update_timer, self.fetch_jobs_timer]: if timer: timers.append (timer) for timer in timers: GLib.source_remove (timer) self.emit ('monitor-exited')
def __init__ (self, parent=None, try_as_root=True): self._use_password = '' self._parent = parent self._try_as_root = try_as_root self._use_user = cups.getUser () self._server = cups.getServer () self._port = cups.getPort() self._connect () self._prompt_allowed = True
def __init__(self, bus=None, my_jobs=True, specific_dests=None, monitor_jobs=True, host=None, port=None, encryption=None): GObject.GObject.__init__ (self) self.my_jobs = my_jobs self.specific_dests = specific_dests self.monitor_jobs = monitor_jobs self.jobs = {} self.printer_state_reasons = {} self.printers = set() self.process_pending_events = True self.fetch_jobs_timer = None self.cups_connection_in_error = False if host: cups.setServer (host) if port: cups.setPort (port) if encryption: cups.setEncryption (encryption) self.user = cups.getUser () self.host = cups.getServer () self.port = cups.getPort () self.encryption = cups.getEncryption () self.ppdcache = ppdcache.PPDCache (host=self.host, port=self.port, encryption=self.encryption) self.which_jobs = "not-completed" self.reasons_seen = {} self.connecting_timers = {} self.still_connecting = set() self.connecting_to_device = {} self.received_any_dbus_signals = False self.update_timer = None if bus is None: try: bus = dbus.SystemBus () except dbus.exceptions.DBusException: # System bus not running. pass self.bus = bus if bus is not None: bus.add_signal_receiver (self.handle_dbus_signal, path=self.DBUS_PATH, dbus_interface=self.DBUS_IFACE) self.sub_id = -1
def auth_handler (self, prompt, conn, method=None, resource=None): self._auth_called = True if self._reconnected: debugprint ("Supplying password after reconnection") self._reconnected = False conn.set_auth_info (self._use_password) return self._reconnected = False if not conn.prompt_allowed: conn.set_auth_info (self._use_password) return # If we've previously prompted, explain why we're prompting again. if self._dialog_shown: d = gtk.MessageDialog (self._conn.parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, _("Not authorized")) d.format_secondary_text (_("The password may be incorrect.")) d.run () d.destroy () op = None if conn.semantic: op = conn.semantic.current_operation () if op == None: d = authconn.AuthDialog (parent=conn.parent) else: title = _("Authentication (%s)") % op d = authconn.AuthDialog (title=title, parent=conn.parent) d.set_prompt (prompt) if self._user == None: self._user = cups.getUser() d.set_auth_info ([self._user, '']) d.field_grab_focus ('password') d.set_keep_above (True) d.show_all () d.connect ("response", self._on_auth_dialog_response) self._dialog_shown = True
def fetch_jobs (self, refresh_all): if not self.process_pending_events: # Skip this call. We'll get called again soon. return True user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) except RuntimeError: self.emit ('cups-connection-error') self.fetch_jobs_timer = None cups.setUser (user) return False limit = 1 r = ["job-id", "job-printer-uri", "job-state", "job-originating-user-name", "job-k-octets", "job-name", "time-at-creation"] try: try: fetched = c.getJobs (which_jobs=self.which_jobs, my_jobs=self.my_jobs, first_job_id=self.fetch_first_job_id, limit=limit, requested_attributes=r) except TypeError: # requested_attributes requires pycups 1.9.50 fetched = c.getJobs (which_jobs=self.which_jobs, my_jobs=self.my_jobs, first_job_id=self.fetch_first_job_id, limit=limit) except cups.IPPError, (e, m): self.emit ('cups-ipp-error', e, m) self.fetch_jobs_timer = None cups.setUser (user) return False
def cleanup (self): if self.sub_id != -1: user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) c.cancelSubscription (self.sub_id) debugprint ("Canceled subscription %d" % self.sub_id) except: pass cups.setUser (user) if self.bus != None: self.bus.remove_signal_receiver (self.handle_dbus_signal, path=self.DBUS_PATH, dbus_interface=self.DBUS_IFACE) self.watcher.monitor_exited (self)
def __init__(self, parent=None, try_as_root=True, lock=False, host=None, port=None, encryption=None): if host != None: cups.setServer(host) if port != None: cups.setPort(port) if encryption != None: cups.setEncryption(encryption) self._use_password = "" self._parent = parent self._try_as_root = try_as_root self._use_user = cups.getUser() self._server = cups.getServer() self._port = cups.getPort() self._encryption = cups.getEncryption() self._prompt_allowed = True self._operation_stack = [] self._lock = lock self._gui_event = threading.Event() self._connect()
def run (self): if self.host == None: self.host = cups.getServer () if self.port == None: self.port = cups.getPort () if self._encryption == None: self._encryption = cups.getEncryption () if self.user: cups.setUser (self.user) else: self.user = cups.getUser () cups.setPasswordCB2 (self._auth) try: conn = cups.Connection (host=self.host, port=self.port, encryption=self._encryption) self._reply (None) except RuntimeError, e: conn = None self._error (e)
def refresh(self, which_jobs=None, refresh_all=True): debugprint ("refresh") if which_jobs != None: self.which_jobs = which_jobs user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) except RuntimeError: self.watcher.cups_connection_error (self) cups.setUser (user) return if self.sub_id != -1: try: c.cancelSubscription (self.sub_id) except cups.IPPError, (e, m): self.watcher.cups_ipp_error (self, e, m) debugprint ("Canceled subscription %d" % self.sub_id)
def fetch_jobs (self, refresh_all): if not self.process_pending_events: # Skip this call. We'll get called again soon. return True user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) except RuntimeError: self.emit ('cups-connection-error') self.fetch_jobs_timer = None cups.setUser (user) return False limit = 1 r = ["job-id", "job-printer-uri", "job-state", "job-originating-user-name", "job-k-octets", "job-name", "time-at-creation"] try: fetched = c.getJobs (which_jobs=self.which_jobs, my_jobs=self.my_jobs, first_job_id=self.fetch_first_job_id, limit=limit, requested_attributes=r) except cups.IPPError as e: (e, m) = e.args self.emit ('cups-ipp-error', e, m) self.fetch_jobs_timer = None cups.setUser (user) return False cups.setUser (user) got = len (fetched) debugprint ("Got %s jobs, asked for %s" % (got, limit)) jobs = self.jobs.copy () jobids = list(fetched.keys ()) jobids.sort () if got > 0: last_jobid = jobids[got - 1] if last_jobid < self.fetch_first_job_id: last_jobid = self.fetch_first_job_id + limit - 1 debugprint ("Unexpected job IDs returned: %s" % repr (jobids)) debugprint ("That's not what we asked for!") else: last_jobid = self.fetch_first_job_id + limit - 1 for jobid in range (self.fetch_first_job_id, last_jobid + 1): try: job = fetched[jobid] if self.specific_dests is not None: uri = job.get('job-printer-uri', '/') i = uri.rfind ('/') printer = uri[i + 1:] if printer not in self.specific_dests: raise KeyError if jobid in jobs: n = 'job-event' else: n = 'job-added' jobs[jobid] = job self.emit (n, jobid, '', {}, job.copy ()) except KeyError: # No job by that ID. if jobid in jobs: del jobs[jobid] self.emit ('job-removed', jobid, '', {}) jobids = list(jobs.keys ()) jobids.sort () if got < limit: trim = False for i in range (len (jobids)): jobid = jobids[i] if not trim and jobid > last_jobid: trim = True if trim: del jobs[jobid] self.emit ('job-removed', jobid, '', {}) self.update_jobs (jobs) self.jobs = jobs if got < limit: # That's all. Don't run this timer again. self.fetch_jobs_timer = None return False # Remember where we got up to and run this timer again. next = jobid + 1 while not refresh_all and next in self.jobs: next += 1 self.fetch_first_job_id = next return True
def refresh(self, which_jobs=None, refresh_all=True): debugprint ("refresh") self.emit ('refresh') if which_jobs is not None: self.which_jobs = which_jobs user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) except RuntimeError: GLib.idle_add (self.emit, 'cups-connection-error') cups.setUser (user) return if self.sub_id != -1: try: c.cancelSubscription (self.sub_id) except cups.IPPError as e: (e, m) = e.args GLib.idle_add (lambda e, m: self.emit ('cups-ipp-error', e, m), e, m) if self.update_timer: GLib.source_remove (self.update_timer) self.update_timer = None debugprint ("Canceled subscription %d" % self.sub_id) try: del self.sub_seq except AttributeError: pass events = ["printer-added", "printer-modified", "printer-deleted", "printer-state-changed"] if self.monitor_jobs: events.extend (["job-created", "job-completed", "job-stopped", "job-state-changed", "job-progress"]) try: self.sub_id = c.createSubscription ("/", events=events) debugprint ("Created subscription %d, events=%s" % (self.sub_id, repr (events))) except cups.IPPError as e: (e, m) = e.args GLib.idle_add (lambda e, m: self.emit ('cups-ipp-error', e, m), e, m) cups.setUser (user) if self.sub_id != -1: if self.update_timer: GLib.source_remove (self.update_timer) self.update_timer = GLib.timeout_add_seconds ( MIN_REFRESH_INTERVAL, self.get_notifications) debugprint ("Next notifications fetch in %ds" % MIN_REFRESH_INTERVAL) if self.monitor_jobs: jobs = self.jobs.copy () if self.which_jobs not in ['all', 'completed']: # Filter out completed jobs. filtered = {} for jobid, job in jobs.items (): if job.get ('job-state', cups.IPP_JOB_CANCELED) < cups.IPP_JOB_CANCELED: filtered[jobid] = job jobs = filtered self.fetch_first_job_id = 1 if self.fetch_jobs_timer: GLib.source_remove (self.fetch_jobs_timer) self.fetch_jobs_timer = GLib.timeout_add (5, self.fetch_jobs, refresh_all) else: jobs = {} try: r = collect_printer_state_reasons (c, self.ppdcache) self.printer_state_reasons = r dests = c.getPrinters () self.printers = set(dests.keys ()) except cups.IPPError as e: (e, m) = e.args GLib.idle_add (lambda e, m: self.emit ('cups-ipp-error', e, m), e, m) return except RuntimeError: GLib.idle_add (self.emit, 'cups-connection-error') return if self.specific_dests is not None: for jobid in jobs.keys (): uri = jobs[jobid].get('job-printer-uri', '/') i = uri.rfind ('/') printer = uri[i + 1:] if printer not in self.specific_dests: del jobs[jobid] self.set_process_pending (False) for printer in self.printers: GLib.idle_add (lambda x: self.emit ('printer-added', x), printer) for jobid, job in jobs.items (): GLib.idle_add (lambda jobid, job: self.emit ('job-added', jobid, '', {}, job), jobid, job) self.update_jobs (jobs) self.jobs = jobs self.set_process_pending (True) return False
def get_notifications(self): if self.update_timer: GLib.source_remove (self.update_timer) self.update_timer = None if not self.process_pending_events: # Defer the timer callback. self.update_timer = GLib.timeout_add (200, self.get_notifications) debugprint ("Deferred get_notifications by 200ms") return False debugprint ("get_notifications") user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) try: try: notifications = c.getNotifications ([self.sub_id], [self.sub_seq + 1]) except AttributeError: notifications = c.getNotifications ([self.sub_id]) except cups.IPPError as e: (e, m) = e.args cups.setUser (user) if e == cups.IPP_NOT_FOUND: # Subscription lease has expired. self.sub_id = -1 debugprint ("Subscription not found, will refresh") self.refresh () return False self.emit ('cups-ipp-error', e, m) if e == cups.IPP_FORBIDDEN: return False debugprint ("getNotifications failed with %d (%s)" % (e, m)) return True except RuntimeError: cups.setUser (user) debugprint ("cups-connection-error, will retry") self.cups_connection_in_error = True self.emit ('cups-connection-error') return True if self.cups_connection_in_error: self.cups_connection_in_error = False debugprint ("cups-connection-recovered") self.emit ('cups-connection-recovered') cups.setUser (user) jobs = self.jobs.copy () for event in notifications['events']: seq = event['notify-sequence-number'] self.sub_seq = seq nse = event['notify-subscribed-event'] debugprint ("%d %s %s" % (seq, nse, event['notify-text'])) if get_debugging (): debugprint (pprint.pformat (event)) if nse.startswith ('printer-'): # Printer events name = event['printer-name'] if nse == 'printer-added' and name not in self.printers: self.printers.add (name) self.emit ('printer-added', name) elif nse == 'printer-deleted' and name in self.printers: self.printers.remove (name) items = list(self.reasons_seen.keys ()) for tuple in items: if tuple[1] == name: reason = self.reasons_seen[tuple] del self.reasons_seen[tuple] self.emit ('state-reason-removed', reason) if name in self.printer_state_reasons: del self.printer_state_reasons[name] self.emit ('printer-removed', name) elif name in self.printers: printer_state_reasons = event['printer-state-reasons'] reasons = [] for reason in printer_state_reasons: if reason == "none": break if state_reason_is_harmless (reason): continue reasons.append (StateReason (name, reason, self.ppdcache)) self.printer_state_reasons[name] = reasons self.emit ('printer-event', name, nse, event) continue # Job events if not nse.startswith ("job-"): # Some versions of CUPS give empty # notify-subscribed-event attributes (STR #3608). debugprint ("Unhandled nse %s" % repr (nse)) continue jobid = event['notify-job-id'] if (nse == 'job-created' or (nse == 'job-state-changed' and jobid not in jobs and event['job-state'] == cups.IPP_JOB_PROCESSING)): if (self.specific_dests is not None and event['printer-name'] not in self.specific_dests): continue try: attrs = c.getJobAttributes (jobid) if (self.my_jobs and attrs['job-originating-user-name'] != cups.getUser ()): continue jobs[jobid] = attrs except KeyError: jobs[jobid] = {'job-k-octets': 0} except cups.IPPError as e: (e, m) = e.args self.emit ('cups-ipp-error', e, m) jobs[jobid] = {'job-k-octets': 0} self.emit ('job-added', jobid, nse, event, jobs[jobid].copy ()) elif (nse == 'job-completed' or (nse == 'job-state-changed' and event['job-state'] == cups.IPP_JOB_COMPLETED)): if not (self.which_jobs in ['completed', 'all']): try: del jobs[jobid] self.emit ('job-removed', jobid, nse, event) except KeyError: pass continue try: job = jobs[jobid] except KeyError: continue if (self.specific_dests is not None and event['printer-name'] not in self.specific_dests): del jobs[jobid] self.emit ('job-removed', jobid, nse, event) continue for attribute in ['job-state', 'job-name']: job[attribute] = event[attribute] if 'notify-printer-uri' in event: job['job-printer-uri'] = event['notify-printer-uri'] self.emit ('job-event', jobid, nse, event, job.copy ()) self.set_process_pending (False) self.update_jobs (jobs) self.jobs = jobs self.set_process_pending (True) # Update again when we're told to. If we're getting CUPS # D-Bus signals, however, rely on those instead. if not self.received_any_dbus_signals: interval = notifications['notify-get-interval'] t = GLib.timeout_add_seconds (interval, self.get_notifications) debugprint ("Next notifications fetch in %ds" % interval) self.update_timer = t return False
def refresh(self, which_jobs=None, refresh_all=True): debugprint ("refresh") self.emit ('refresh') if which_jobs != None: self.which_jobs = which_jobs user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) except RuntimeError: GLib.idle_add (self.emit, 'cups-connection-error') cups.setUser (user) return if self.sub_id != -1: try: c.cancelSubscription (self.sub_id) except cups.IPPError as e: (e, m) = e.args GLib.idle_add (lambda (e, m): self.emit ('cups-ipp-error', e, m), (e, m)) if self.update_timer: GLib.source_remove (self.update_timer) debugprint ("Canceled subscription %d" % self.sub_id) try: del self.sub_seq except AttributeError: pass events = ["printer-added", "printer-modified", "printer-deleted", "printer-state-changed"] if self.monitor_jobs: events.extend (["job-created", "job-completed", "job-stopped", "job-state-changed", "job-progress"]) try: self.sub_id = c.createSubscription ("/", events=events) debugprint ("Created subscription %d, events=%s" % (self.sub_id, repr (events))) except cups.IPPError as e: (e, m) = e.args GLib.idle_add (lambda (e, m): self.emit ('cups-ipp-error', e, m), (e, m)) cups.setUser (user) if self.sub_id != -1: if self.update_timer: GLib.source_remove (self.update_timer) self.update_timer = GLib.timeout_add_seconds ( MIN_REFRESH_INTERVAL, self.get_notifications) debugprint ("Next notifications fetch in %ds" % MIN_REFRESH_INTERVAL) if self.monitor_jobs: jobs = self.jobs.copy () if self.which_jobs not in ['all', 'completed']: # Filter out completed jobs. filtered = {} for jobid, job in jobs.iteritems (): if job.get ('job-state', cups.IPP_JOB_CANCELED) < cups.IPP_JOB_CANCELED: filtered[jobid] = job jobs = filtered self.fetch_first_job_id = 1 if self.fetch_jobs_timer: GLib.source_remove (self.fetch_jobs_timer) self.fetch_jobs_timer = GLib.timeout_add (5, self.fetch_jobs, refresh_all) else: jobs = {} try: r = collect_printer_state_reasons (c, self.ppdcache) self.printer_state_reasons = r dests = c.getPrinters () self.printers = set(dests.keys ()) except cups.IPPError as e: (e, m) = e.args GLib.idle_add (lambda (e, m): self.emit ('cups-ipp-error', e, m), (e, m)) return except RuntimeError: GLib.idle_add (self.emit, 'cups-connection-error') return if self.specific_dests != None: for jobid in jobs.keys (): uri = jobs[jobid].get('job-printer-uri', '/') i = uri.rfind ('/') printer = uri[i + 1:] if printer not in self.specific_dests: del jobs[jobid] self.set_process_pending (False) for printer in self.printers: GLib.idle_add (lambda x: self.emit ('printer-added', x), printer) for jobid, job in jobs.iteritems (): GLib.idle_add (lambda (jobid, job): self.emit ('job-added', jobid, '', {}, job), (jobid, job)) self.update_jobs (jobs) self.jobs = jobs self.set_process_pending (True) return False
def fetch_jobs (self, refresh_all): if not self.process_pending_events: # Skip this call. We'll get called again soon. return True user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) except RuntimeError: self.emit ('cups-connection-error') self.fetch_jobs_timer = None cups.setUser (user) return False limit = 1 r = ["job-id", "job-printer-uri", "job-state", "job-originating-user-name", "job-k-octets", "job-name", "time-at-creation"] try: fetched = c.getJobs (which_jobs=self.which_jobs, my_jobs=self.my_jobs, first_job_id=self.fetch_first_job_id, limit=limit, requested_attributes=r) except cups.IPPError as e: (e, m) = e.args self.emit ('cups-ipp-error', e, m) self.fetch_jobs_timer = None cups.setUser (user) return False cups.setUser (user) got = len (fetched) debugprint ("Got %s jobs, asked for %s" % (got, limit)) jobs = self.jobs.copy () jobids = fetched.keys () jobids.sort () if got > 0: last_jobid = jobids[got - 1] if last_jobid < self.fetch_first_job_id: last_jobid = self.fetch_first_job_id + limit - 1 debugprint ("Unexpected job IDs returned: %s" % repr (jobids)) debugprint ("That's not what we asked for!") else: last_jobid = self.fetch_first_job_id + limit - 1 for jobid in xrange (self.fetch_first_job_id, last_jobid + 1): try: job = fetched[jobid] if self.specific_dests != None: uri = job.get('job-printer-uri', '/') i = uri.rfind ('/') printer = uri[i + 1:] if printer not in self.specific_dests: raise KeyError if jobs.has_key (jobid): n = 'job-event' else: n = 'job-added' jobs[jobid] = job self.emit (n, jobid, '', {}, job.copy ()) except KeyError: # No job by that ID. if jobs.has_key (jobid): del jobs[jobid] self.emit ('job-removed', jobid, '', {}) jobids = jobs.keys () jobids.sort () if got < limit: trim = False for i in range (len (jobids)): jobid = jobids[i] if not trim and jobid > last_jobid: trim = True if trim: del jobs[jobid] self.emit ('job-removed', jobid, '', {}) self.update_jobs (jobs) self.jobs = jobs if got < limit: # That's all. Don't run this timer again. self.fetch_jobs_timer = None return False # Remember where we got up to and run this timer again. next = jobid + 1 while not refresh_all and self.jobs.has_key (next): next += 1 self.fetch_first_job_id = next return True
def auth_handler(self, prompt, conn, method=None, resource=None): if self._auth_called == False: if self._user == None: self._user = cups.getUser() if self._user: host = conn.thread.host port = conn.thread.port creds = authconn.global_authinfocache.lookup_auth_info( host=host, port=port) if creds: if creds[0] == self._user: self._use_password = creds[1] self._reconnected = True del creds else: host = conn.thread.host port = conn.thread.port authconn.global_authinfocache.remove_auth_info(host=host, port=port) self._use_password = '' self._auth_called = True if self._reconnected: debugprint("Supplying password after reconnection") self._reconnected = False conn.set_auth_info(self._use_password) return self._reconnected = False if not conn.prompt_allowed: conn.set_auth_info(self._use_password) return # If we've previously prompted, explain why we're prompting again. if self._dialog_shown: d = Gtk.MessageDialog(parent=self._conn.parent, modal=True, destroy_with_parent=True, message_type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE, text=_("Not authorized")) d.format_secondary_text(_("The password may be incorrect.")) d.run() d.destroy() op = None if conn.semantic: op = conn.semantic.current_operation() if op == None: d = authconn.AuthDialog(parent=conn.parent) else: title = _("Authentication (%s)") % op d = authconn.AuthDialog(title=title, parent=conn.parent) d.set_prompt('') if self._user == None: self._user = cups.getUser() d.set_auth_info(['', '']) d.field_grab_focus('username') d.set_keep_above(True) d.show_all() d.connect("response", self._on_auth_dialog_response) self._dialog_shown = True
def run(self): if self.host == None: self.host = cups.getServer() if self.port == None: self.port = cups.getPort() if self._encryption == None: self._encryption = cups.getEncryption() if self.user: cups.setUser(self.user) else: self.user = cups.getUser() cups.setPasswordCB2(self._auth) try: conn = cups.Connection(host=self.host, port=self.port, encryption=self._encryption) self._reply(None) except RuntimeError as e: conn = None self._error(e) while True: # Wait to find out what operation to try. debugprint("Awaiting further instructions") self.idle = self._queue.empty() item = self._queue.get() debugprint("Next task: %s" % repr(item)) if item == None: # Our signal to quit. self._queue.task_done() break elif self._destroyed: # Just mark all tasks done self._queue.task_done() continue self.idle = False (fn, args, kwds, rh, eh, ah) = item if rh != False: self._reply_handler = rh if eh != False: self._error_handler = eh if ah != False: self._auth_handler = ah if fn == True: # Our signal to change user and reconnect. self.user = args[0] cups.setUser(self.user) debugprint("Set user=%s; reconnecting..." % self.user) cups.setPasswordCB2(self._auth) try: conn = cups.Connection(host=self.host, port=self.port, encryption=self._encryption) debugprint("...reconnected") self._queue.task_done() self._reply(None) except RuntimeError as e: debugprint("...failed") self._queue.task_done() self._error(e) continue # Normal IPP operation. Try to perform it. try: debugprint("Call %s" % fn) result = fn(conn, *args, **kwds) if fn == cups.Connection.adminGetServerSettings.__call__: # Special case for a rubbish bit of API. if result == {}: # Authentication failed, but we aren't told that. raise cups.IPPError(cups.IPP_NOT_AUTHORIZED, '') debugprint("...success") self._reply(result) except Exception as e: debugprint("...failure (%s)" % repr(e)) self._error(e) self._queue.task_done() debugprint("Thread exiting") del self._conn # already destroyed del self._reply_handler del self._error_handler del self._auth_handler del self._queue del self._auth_queue del conn cups.setPasswordCB2(None)
def get_notifications(self): if self.update_timer: GLib.source_remove (self.update_timer) self.update_timer = None if not self.process_pending_events: # Defer the timer callback. self.update_timer = GLib.timeout_add (200, self.get_notifications) debugprint ("Deferred get_notifications by 200ms") return False debugprint ("get_notifications") user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) try: try: notifications = c.getNotifications ([self.sub_id], [self.sub_seq + 1]) except AttributeError: notifications = c.getNotifications ([self.sub_id]) except cups.IPPError as e: (e, m) = e.args cups.setUser (user) if e == cups.IPP_NOT_FOUND: # Subscription lease has expired. self.sub_id = -1 debugprint ("Subscription not found, will refresh") self.refresh () return False self.emit ('cups-ipp-error', e, m) if e == cups.IPP_FORBIDDEN: return False debugprint ("getNotifications failed with %d (%s)" % (e, m)) return True except RuntimeError: cups.setUser (user) debugprint ("cups-connection-error, will retry") self.cups_connection_in_error = True self.emit ('cups-connection-error') return True if self.cups_connection_in_error: self.cups_connection_in_error = False debugprint ("cups-connection-recovered") self.emit ('cups-connection-recovered') cups.setUser (user) jobs = self.jobs.copy () for event in notifications['events']: seq = event['notify-sequence-number'] self.sub_seq = seq nse = event['notify-subscribed-event'] debugprint ("%d %s %s" % (seq, nse, event['notify-text'])) if get_debugging (): debugprint (pprint.pformat (event)) if nse.startswith ('printer-'): # Printer events name = event['printer-name'] if nse == 'printer-added' and name not in self.printers: self.printers.add (name) self.emit ('printer-added', name) elif nse == 'printer-deleted' and name in self.printers: self.printers.remove (name) items = list(self.reasons_seen.keys ()) for tuple in items: if tuple[1] == name: reason = self.reasons_seen[tuple] del self.reasons_seen[tuple] self.emit ('state-reason-removed', reason) if name in self.printer_state_reasons: del self.printer_state_reasons[name] self.emit ('printer-removed', name) elif name in self.printers: printer_state_reasons = event['printer-state-reasons'] reasons = [] for reason in printer_state_reasons: if reason == "none": break if state_reason_is_harmless (reason): continue reasons.append (StateReason (name, reason, self.ppdcache)) self.printer_state_reasons[name] = reasons self.emit ('printer-event', name, nse, event) continue # Job events if not nse.startswith ("job-"): # Some versions of CUPS give empty # notify-subscribed-event attributes (STR #3608). debugprint ("Unhandled nse %s" % repr (nse)) continue jobid = event['notify-job-id'] if (nse == 'job-created' or (nse == 'job-state-changed' and jobid not in jobs and event['job-state'] == cups.IPP_JOB_PROCESSING)): if (self.specific_dests != None and event['printer-name'] not in self.specific_dests): continue try: attrs = c.getJobAttributes (jobid) if (self.my_jobs and attrs['job-originating-user-name'] != cups.getUser ()): continue jobs[jobid] = attrs except KeyError: jobs[jobid] = {'job-k-octets': 0} except cups.IPPError as e: (e, m) = e.args self.emit ('cups-ipp-error', e, m) jobs[jobid] = {'job-k-octets': 0} self.emit ('job-added', jobid, nse, event, jobs[jobid].copy ()) elif (nse == 'job-completed' or (nse == 'job-state-changed' and event['job-state'] == cups.IPP_JOB_COMPLETED)): if not (self.which_jobs in ['completed', 'all']): try: del jobs[jobid] self.emit ('job-removed', jobid, nse, event) except KeyError: pass continue try: job = jobs[jobid] except KeyError: continue if (self.specific_dests != None and event['printer-name'] not in self.specific_dests): del jobs[jobid] self.emit ('job-removed', jobid, nse, event) continue for attribute in ['job-state', 'job-name']: job[attribute] = event[attribute] if 'notify-printer-uri' in event: job['job-printer-uri'] = event['notify-printer-uri'] self.emit ('job-event', jobid, nse, event, job.copy ()) self.set_process_pending (False) self.update_jobs (jobs) self.jobs = jobs self.set_process_pending (True) # Update again when we're told to. If we're getting CUPS # D-Bus signals, however, rely on those instead. if not self.received_any_dbus_signals: interval = notifications['notify-get-interval'] t = GLib.timeout_add_seconds (interval, self.get_notifications) debugprint ("Next notifications fetch in %ds" % interval) self.update_timer = t return False
def auth_handler(self, prompt, conn, method=None, resource=None): if self._auth_called == False: if self._user == None: self._user = cups.getUser() if self._user: host = conn.thread.host port = conn.thread.port creds = authconn.global_authinfocache.lookup_auth_info(host=host, port=port) if creds: if creds[0] == self._user: self._use_password = creds[1] self._reconnected = True del creds else: host = conn.thread.host port = conn.thread.port authconn.global_authinfocache.remove_auth_info(host=host, port=port) self._use_password = "" self._auth_called = True if self._reconnected: debugprint("Supplying password after reconnection") self._reconnected = False conn.set_auth_info(self._use_password) return self._reconnected = False if not conn.prompt_allowed: conn.set_auth_info(self._use_password) return # If we've previously prompted, explain why we're prompting again. if self._dialog_shown: d = Gtk.MessageDialog( parent=self._conn.parent, modal=True, destroy_with_parent=True, message_type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.CLOSE, text=_("Not authorized"), ) d.format_secondary_text(_("The password may be incorrect.")) d.run() d.destroy() op = None if conn.semantic: op = conn.semantic.current_operation() if op == None: d = authconn.AuthDialog(parent=conn.parent) else: title = _("Authentication (%s)") % op d = authconn.AuthDialog(title=title, parent=conn.parent) d.set_prompt("") if self._user == None: self._user = cups.getUser() d.set_auth_info(["", ""]) d.field_grab_focus("username") d.set_keep_above(True) d.show_all() d.connect("response", self._on_auth_dialog_response) self._dialog_shown = True
def run(self): if self.host == None: self.host = cups.getServer() if self.port == None: self.port = cups.getPort() if self._encryption == None: self._encryption = cups.getEncryption() if self.user: cups.setUser(self.user) else: self.user = cups.getUser() cups.setPasswordCB2(self._auth) try: conn = cups.Connection(host=self.host, port=self.port, encryption=self._encryption) self._reply(None) except RuntimeError as e: conn = None self._error(e) while True: # Wait to find out what operation to try. debugprint("Awaiting further instructions") self.idle = self._queue.empty() item = self._queue.get() debugprint("Next task: %s" % repr(item)) if item == None: # Our signal to quit. self._queue.task_done() break elif self._destroyed: # Just mark all tasks done self._queue.task_done() continue self.idle = False (fn, args, kwds, rh, eh, ah) = item if rh != False: self._reply_handler = rh if eh != False: self._error_handler = eh if ah != False: self._auth_handler = ah if fn == True: # Our signal to change user and reconnect. self.user = args[0] cups.setUser(self.user) debugprint("Set user=%s; reconnecting..." % self.user) cups.setPasswordCB2(self._auth) try: conn = cups.Connection(host=self.host, port=self.port, encryption=self._encryption) debugprint("...reconnected") self._queue.task_done() self._reply(None) except RuntimeError as e: debugprint("...failed") self._queue.task_done() self._error(e) continue # Normal IPP operation. Try to perform it. try: debugprint("Call %s" % fn) result = fn(conn, *args, **kwds) if fn == cups.Connection.adminGetServerSettings.__call__: # Special case for a rubbish bit of API. if result == {}: # Authentication failed, but we aren't told that. raise cups.IPPError(cups.IPP_NOT_AUTHORIZED, "") debugprint("...success") self._reply(result) except Exception as e: debugprint("...failure (%s)" % repr(e)) self._error(e) self._queue.task_done() debugprint("Thread exiting") del self._conn # already destroyed del self._reply_handler del self._error_handler del self._auth_handler del self._queue del self._auth_queue del conn cups.setPasswordCB2(None)
def get_notifications(self): debugprint ("get_notifications") user = cups.getUser () try: cups.setUser (self.user) c = cups.Connection (host=self.host, port=self.port, encryption=self.encryption) try: try: notifications = c.getNotifications ([self.sub_id], [self.sub_seq + 1]) except AttributeError: notifications = c.getNotifications ([self.sub_id]) except cups.IPPError, (e, m): cups.setUser (user) if e == cups.IPP_NOT_FOUND: # Subscription lease has expired. self.sub_id = -1 self.refresh () return False self.watcher.cups_ipp_error (self, e, m) return True except RuntimeError: cups.setUser (user) self.watcher.cups_connection_error (self) return True cups.setUser (user) deferred_calls = [] jobs = self.jobs.copy () for event in notifications['events']: seq = event['notify-sequence-number'] self.sub_seq = seq nse = event['notify-subscribed-event'] debugprint ("%d %s %s" % (seq, nse, event['notify-text'])) if get_debugging (): debugprint (pprint.pformat (event)) if nse.startswith ('printer-'): # Printer events name = event['printer-name'] if nse == 'printer-added' and name not in self.printers: self.printers.add (name) deferred_calls.append ((self.watcher.printer_added, (self, name))) elif nse == 'printer-deleted' and name in self.printers: self.printers.remove (name) items = self.reasons_seen.keys () for tuple in items: if tuple[1] == name: reason = self.reasons_seen[tuple] del self.reasons_seen[tuple] deferred_calls.append ((self.watcher.state_reason_removed, (self, reason))) if self.printer_state_reasons.has_key (name): del self.printer_state_reasons[name] deferred_calls.append ((self.watcher.printer_removed, (self, name))) elif name in self.printers: printer_state_reasons = event['printer-state-reasons'] reasons = [] for reason in printer_state_reasons: if reason == "none": break if state_reason_is_harmless (reason): continue reasons.append (StateReason (name, reason)) self.printer_state_reasons[name] = reasons deferred_calls.append ((self.watcher.printer_event, (self, name, nse, event))) continue # Job events if not nse.startswith ("job-"): # Some versions of CUPS give empty # notify-subscribed-event attributes (STR #3608). debugprint ("Unhandled nse %s" % repr (nse)) continue jobid = event['notify-job-id'] #BREAKAGE! if (nse == 'job-created' or (nse == 'job-state-changed' and not jobs.has_key (jobid) and event['job-state'] == cups.IPP_JOB_PROCESSING)): if (self.specific_dests != None and event['printer-name'] not in self.specific_dests): continue try: attrs = c.getJobAttributes (jobid) if (self.my_jobs and attrs['job-originating-user-name'] != cups.getUser ()): continue jobs[jobid] = attrs except AttributeError: jobs[jobid] = {'job-k-octets': 0} except cups.IPPError, (e, m): self.watcher.cups_ipp_error (self, e, m) jobs[jobid] = {'job-k-octets': 0} except KeyError: jobs[jobid] = {'job-k-octets': 0} deferred_calls.append ((self.watcher.job_added, (self, jobid, nse, event, jobs[jobid].copy ())))