def get_lpinfo_drv(make_and_model): command = shlex.split(LPINFO) + ["--make-and-model", make_and_model, "-m"] def preexec(): os.setsid() log("get_lpinfo_drv(%s) command=%s", make_and_model, command) try: proc = subprocess.Popen( command, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, close_fds=True, preexec_fn=preexec, ) except Exception as e: log("get_lp_info_drv(%s) lpinfo command %s failed", make_and_model, command, exc_info=True) log.error("Error: lpinfo command failed to run") log.error(" %s", e) log.error(" command used: '%s'", " ".join(command)) return None # use the global child reaper to make sure this doesn't end up as a zombie from xpra.child_reaper import getChildReaper from xpra.util import nonl cr = getChildReaper() cr.add_process(proc, "lpinfo", command, ignore=True, forget=True) from xpra.make_thread import make_thread def watch_lpinfo(): # give it 15 seconds to run: for _ in range(15): if proc.poll() is not None: return # finished already time.sleep(1) log.warn("Warning: lpinfo command is taking too long") proc.terminate() make_thread(watch_lpinfo, "lpinfo watcher", daemon=True).start() out, err = proc.communicate() if proc.wait() != 0: log.warn("Warning: lpinfo command failed and returned %s", proc.returncode) log.warn(" command used: '%s'", " ".join(command)) return None if sys.version_info[0] >= 3: try: out = out.decode() except: out = str(out) log("lpinfo out=%s", nonl(out)) log("lpinfo err=%s", nonl(err)) if err: log.warn("Warning: lpinfo command produced some warnings:") log.warn(" '%s'", nonl(err)) for line in out.splitlines(): if line.startswith("drv://"): return line.split(" ")[0] return None
def _process_disconnect(self, packet): #ie: ("disconnect", "version error", "incompatible version") reason = bytestostr(packet[1]) info = packet[2:] s = nonl(reason) if len(info): s += " (%s)" % (", ".join([nonl(bytestostr(x)) for x in info])) if self.server_capabilities is None or len( self.server_capabilities) == 0: #server never sent hello to us - so disconnect is an error #(but we don't know which one - the info message may help) log.warn( "server failure: disconnected before the session could be established" ) e = EXIT_FAILURE elif disconnect_is_an_error(reason): log.warn("server failure: %s", reason) e = EXIT_FAILURE else: if self.exit_code is None: #we're not in the process of exiting already, #tell the user why the server is disconnecting us log.info("server requested disconnect: %s", s) self.quit(EXIT_OK) return self.warn_and_quit(e, "server requested disconnect: %s" % s)
def query_xkbmap(self): ( self.xkbmap_layout, self.xkbmap_layouts, self.xkbmap_variant, self.xkbmap_variants, self.xkbmap_options, ) = self.get_layout_spec() self.xkbmap_print, self.xkbmap_query, self.xkbmap_query_struct = self.get_keymap_spec( ) self.xkbmap_keycodes = self.get_full_keymap() self.xkbmap_x11_keycodes = self.keyboard.get_x11_keymap() ( self.xkbmap_mod_meanings, self.xkbmap_mod_managed, self.xkbmap_mod_pointermissing, ) = self.keyboard.get_keymap_modifiers() self.update_hash() log("layout=%s, layouts=%s, variant=%s, variants=%s", self.xkbmap_layout, self.xkbmap_layouts, self.xkbmap_variant, self.xkbmap_variants) log("print=%s, query=%s, struct=%s", nonl(self.xkbmap_print), nonl(self.xkbmap_query), self.xkbmap_query_struct) log("keycodes=%s", repr_ellipsized(str(self.xkbmap_keycodes))) log("x11 keycodes=%s", repr_ellipsized(str(self.xkbmap_x11_keycodes))) log("mod managed: %s", self.xkbmap_mod_managed) log("mod meanings: %s", self.xkbmap_mod_meanings) log("mod pointermissing: %s", self.xkbmap_mod_pointermissing) log("hash=%s", self.hash)
def safe_exec(cmd, stdin=None, log_errors=True, **kwargs): process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) out, err = process.communicate(stdin) code = process.poll() l=log.debug if code!=0 and log_errors: l=log.error l("signal_safe_exec(%s, %s, %s) stdout='%s'", cmd, stdin, kwargs, nonl(out)) l("signal_safe_exec(%s, %s, %s) stderr='%s'", cmd, stdin, kwargs, nonl(err)) return code, out, err
def get_lpinfo_drv(make_and_model): command = shlex.split(LPINFO)+["--make-and-model", make_and_model, "-m"] def preexec(): os.setsid() log("get_lpinfo_drv(%s) command=%s", make_and_model, command) try: proc = subprocess.Popen(command, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, close_fds=True, preexec_fn=preexec) except Exception as e: log("get_lp_info_drv(%s) lpinfo command %s failed", make_and_model, command, exc_info=True) log.error("Error: lpinfo command failed to run") log.error(" %s", e) log.error(" command used: '%s'", " ".join(command)) return None #use the global child reaper to make sure this doesn't end up as a zombie from xpra.child_reaper import getChildReaper from xpra.util import nonl cr = getChildReaper() cr.add_process(proc, "lpinfo", command, ignore=True, forget=True) from xpra.make_thread import start_thread def watch_lpinfo(): #give it 15 seconds to run: for _ in range(15): if proc.poll() is not None: return #finished already time.sleep(1) if proc.poll() is not None: return log.warn("Warning: lpinfo command is taking too long,") log.warn(" is the cups server running?") try: proc.terminate() except Exception as e: log("%s.terminate()", proc, exc_info=True) log.error("Error: failed to terminate lpinfo command") log.error(" %s", e) start_thread(watch_lpinfo, "lpinfo watcher", daemon=True) out, err = proc.communicate() if proc.wait()!=0: log.warn("Warning: lpinfo command failed and returned %s", proc.returncode) log.warn(" command used: '%s'", " ".join(command)) return None if sys.version_info[0]>=3: try: out = out.decode() except: out = str(out) log("lpinfo out=%s", nonl(out)) log("lpinfo err=%s", nonl(err)) if err: log.warn("Warning: lpinfo command produced some warnings:") log.warn(" '%s'", nonl(err)) for line in out.splitlines(): if line.startswith("drv://"): return line.split(" ")[0] return None
def get_keymap_spec(self): log("get_keymap_spec() keyboard_bindings=%s", self.keyboard_bindings) if not self.keyboard_bindings: return None _query_struct = self.keyboard_bindings.getXkbProperties() _query = xkbmap_query_tostring(_query_struct) log("get_keymap_spec() Xkb query tostring(%s)=%s", _query_struct, _query) #we no longer support servers via xkbmap_print: xkbmap_print = "" log("get_keymap_spec()=(%s, %s, %s)", nonl(xkbmap_print), nonl(_query), nonl(_query_struct)) return xkbmap_print, _query, _query_struct
def dialog_confirm(title, prompt, qinfo="", icon="", buttons=[("OK", 1)]): cmd = get_xpra_command() + [ "_dialog", nonl(title), nonl(prompt), nonl("\\n".join(qinfo)), icon ] for label, code in buttons: cmd.append(nonl(label)) cmd.append(str(code)) return exec_dialog_subprocess(cmd)
def query_xkbmap(self): self.xkbmap_layout, self.xkbmap_variant, self.xkbmap_variants = self.keyboard.get_layout_spec() self.xkbmap_print, self.xkbmap_query = self.keyboard.get_keymap_spec() self.xkbmap_keycodes = self.get_full_keymap() self.xkbmap_x11_keycodes = self.keyboard.get_x11_keymap() self.xkbmap_mod_meanings, self.xkbmap_mod_managed, self.xkbmap_mod_pointermissing = self.keyboard.get_keymap_modifiers() debug("layout=%s, variant=%s", self.xkbmap_layout, self.xkbmap_variant) debug("print=%s, query=%s", nonl(self.xkbmap_print), nonl(self.xkbmap_query)) debug("keycodes=%s", str(self.xkbmap_keycodes)[:80]+"...") debug("x11 keycodes=%s", str(self.xkbmap_x11_keycodes)[:80]+"...") debug("xkbmap_mod_meanings: %s", self.xkbmap_mod_meanings)
def query_xkbmap(self): self.xkbmap_layout, self.xkbmap_variant, self.xkbmap_variants = self.keyboard.get_layout_spec( ) self.xkbmap_print, self.xkbmap_query = self.keyboard.get_keymap_spec() self.xkbmap_keycodes = self.get_full_keymap() self.xkbmap_x11_keycodes = self.keyboard.get_x11_keymap() self.xkbmap_mod_meanings, self.xkbmap_mod_managed, self.xkbmap_mod_pointermissing = self.keyboard.get_keymap_modifiers( ) debug("layout=%s, variant=%s", self.xkbmap_layout, self.xkbmap_variant) debug("print=%s, query=%s", nonl(self.xkbmap_print), nonl(self.xkbmap_query)) debug("keycodes=%s", str(self.xkbmap_keycodes)[:80] + "...") debug("x11 keycodes=%s", str(self.xkbmap_x11_keycodes)[:80] + "...") debug("xkbmap_mod_meanings: %s", self.xkbmap_mod_meanings)
def query_xkbmap(self): self.xkbmap_layout, _, self.xkbmap_variant, self.xkbmap_variants = self.keyboard.get_layout_spec() self.xkbmap_print, self.xkbmap_query, self.xkbmap_query_struct = self.keyboard.get_keymap_spec() self.xkbmap_keycodes = self.get_full_keymap() self.xkbmap_x11_keycodes = self.keyboard.get_x11_keymap() self.xkbmap_mod_meanings, self.xkbmap_mod_managed, self.xkbmap_mod_pointermissing = self.keyboard.get_keymap_modifiers() self.update_hash() log("layout=%s, variant=%s, variants=%s", self.xkbmap_layout, self.xkbmap_variant, self.xkbmap_variants) log("print=%s, query=%s, struct=%s", nonl(self.xkbmap_print), nonl(self.xkbmap_query), nonl(self.xkbmap_query_struct)) log("keycodes=%s", str(self.xkbmap_keycodes)[:80]+"...") log("x11 keycodes=%s", str(self.xkbmap_x11_keycodes)[:80]+"...") log("mod managed: %s", self.xkbmap_mod_managed) log("mod meanings: %s", self.xkbmap_mod_meanings) log("mod pointermissing: %s", self.xkbmap_mod_pointermissing) log("hash=%s", self.hash)
def query_xkbmap(self): self.xkbmap_layout, self.xkbmap_layouts, self.xkbmap_variant, self.xkbmap_variants = self.get_layout_spec() self.xkbmap_print, self.xkbmap_query, self.xkbmap_query_struct = self.get_keymap_spec() self.xkbmap_keycodes = self.get_full_keymap() self.xkbmap_x11_keycodes = self.keyboard.get_x11_keymap() self.xkbmap_mod_meanings, self.xkbmap_mod_managed, self.xkbmap_mod_pointermissing = self.keyboard.get_keymap_modifiers() self.update_hash() log("layout=%s, layouts=%s, variant=%s, variants=%s", self.xkbmap_layout, self.xkbmap_layouts, self.xkbmap_variant, self.xkbmap_variants) log("print=%s, query=%s, struct=%s", nonl(self.xkbmap_print), nonl(self.xkbmap_query), nonl(self.xkbmap_query_struct)) log("keycodes=%s", str(self.xkbmap_keycodes)[:80]+"...") log("x11 keycodes=%s", str(self.xkbmap_x11_keycodes)[:80]+"...") log("mod managed: %s", self.xkbmap_mod_managed) log("mod meanings: %s", self.xkbmap_mod_meanings) log("mod pointermissing: %s", self.xkbmap_mod_pointermissing) log("hash=%s", self.hash)
def verify_capture(self, ss): #verify capture works: log("verify_capture(%s)", ss) try: capture = GTKImageCapture(self.root) bdata = capture.take_screenshot()[-1] nid = XPRA_DISPLAY_NOTIFICATION_ID title = body = "" if any(b!=0 for b in bdata): log("verify_capture(%s) succeeded", ss) if is_Wayland(): title = "Wayland Session Warning" body = "Wayland sessions are not supported,\n"+\ "the screen capture is likely to be empty" else: log.warn("Warning: shadow screen capture is blank") body = "The shadow display capture is blank" if get_loaded_kernel_modules("vboxguest", "vboxvideo"): body += "\nthis may be caused by the VirtualBox video driver." title = "Shadow Capture Failure" log("verify_capture: title='%s', body='%s'", ss, title, nonl(body)) if title and body: ss.may_notify(nid, title, body, icon_name="server") except Exception as e: ss.may_notify(nid, "Shadow Error", "Error shadowing the display:\n%s" % e, icon_name="bugs")
def main(): from xpra.platform import init as platform_init, clean from xpra.util import nonl from xpra.log import enable_color try: platform_init("GUI-Properties") enable_color() init() verbose = "-v" in sys.argv or "--verbose" in sys.argv if verbose: from xpra.log import get_all_loggers for x in get_all_loggers(): x.enable_debug() #naughty, but how else can I hook this up? import os if os.name == "posix": try: from xpra.x11.bindings import posix_display_source #@UnusedImport except: pass #maybe running on OSX? hope for the best.. i = get_info() for k in sorted(i.keys()): v = i[k] print("* %s : %s" % (k.ljust(32), nonl(v))) finally: clean()
def get_text_data(self): data = [] tb = self.description.get_buffer() buf = tb.get_text(*tb.get_bounds(), include_hidden_chars=False) if len(buf): data.append(("Description", "", "txt", buf)) for name, dtype, title, value_cb, tooltip in self.toggles: if not bool(value_cb): continue cb = getattr(self, name) assert cb is not None if not cb.get_active(): continue #OK, the checkbox is selected, get the data value = value_cb if type(value_cb)!=dict: try: value = value_cb() except TypeError: log.error("error on %s", value_cb, exc_info=True) value = str(value_cb) dtype = "txt" except Exception as e: value = e dtype = "txt" if value is None: value = "not available" elif type(value)==dict: s = os.linesep.join("%s : %s" % (k.ljust(32), nonl(str(v))) for k,v in sorted(value.items())) elif type(value) in (list, tuple): s = os.linesep.join(str(x) for x in value) else: s = str(value) data.append((title, tooltip, dtype, s)) return data
def _process_ack_file_chunk(self, packet): #the other end received our send-file or send-file-chunk, #send some more file data filelog("ack-file-chunk: %s", packet[1:]) chunk_id, state, error_message, chunk = packet[1:5] if not state: filelog.error("Error: remote end is cancelling the file transfer:") filelog.error(" %s", error_message) del self.send_chunks_in_progress[chunk_id] return chunk_state = self.send_chunks_in_progress.get(chunk_id) if not chunk_state: filelog.error("Error: cannot find the file transfer id '%s'", nonl(chunk_id)) return if chunk_state[-1]!=chunk: filelog.error("Error: chunk number mismatch (%i vs %i)", chunk_state, chunk) del self.send_chunks_in_progress[chunk_id] return start_time, data, chunk_size, timer, chunk = chunk_state if not data: #all sent! elapsed = time.time()-start_time filelog("%i chunks of %i bytes sent in %ims (%sB/s)", chunk, chunk_size, elapsed*1000, std_unit(chunk*chunk_size/elapsed)) del self.send_chunks_in_progress[chunk_id] return assert chunk_size>0 #carve out another chunk: cdata = self.compressed_wrapper("file-data", data[:chunk_size]) data = data[chunk_size:] chunk += 1 if timer: self.source_remove(timer) timer = self.timeout_add(CHUNK_TIMEOUT, self._check_chunk_sending, chunk_id, chunk) self.send_chunks_in_progress[chunk_id] = [start_time, data, chunk_size, timer, chunk] self.send("send-file-chunk", chunk_id, chunk, cdata, bool(data))
def _process_send_file_chunk(self, packet): chunk_id, chunk, file_data, has_more = packet[1:5] filelog("_process_send_file_chunk%s", (chunk_id, chunk, "%i bytes" % len(file_data), has_more)) chunk_state = self.receive_chunks_in_progress.get(chunk_id) if not chunk_state: filelog.error("Error: cannot find the file transfer id '%s'", nonl(bytestostr(chunk_id))) self.send("ack-file-chunk", chunk_id, False, "file transfer id not found", chunk) return fd = chunk_state[1] if chunk_state[-1]+1!=chunk: filelog.error("Error: chunk number mismatch, expected %i but got %i", chunk_state[-1]+1, chunk) self.send("ack-file-chunk", chunk_id, False, "chunk number mismatch", chunk) del self.receive_chunks_in_progress[chunk_id] os.close(fd) return #update chunk number: chunk_state[-1] = chunk digest = chunk_state[8] written = chunk_state[9] try: os.write(fd, file_data) digest.update(file_data) written += len(file_data) chunk_state[9] = written except OSError as e: filelog.error("Error: cannot write file chunk") filelog.error(" %s", e) self.send("ack-file-chunk", chunk_id, False, "write error: %s" % e, chunk) del self.receive_chunks_in_progress[chunk_id] try: os.close(fd) except (OSError, IOError): pass return self.send("ack-file-chunk", chunk_id, True, "", chunk) if has_more: timer = chunk_state[-2] if timer: self.source_remove(timer) #remote end will send more after receiving the ack timer = self.timeout_add(CHUNK_TIMEOUT, self._check_chunk_receiving, chunk_id, chunk) chunk_state[-2] = timer return del self.receive_chunks_in_progress[chunk_id] os.close(fd) #check file size and digest then process it: filename, mimetype, printit, openit, filesize, options = chunk_state[2:8] if written!=filesize: filelog.error("Error: expected a file of %i bytes, got %i", filesize, written) return expected_digest = options.get("sha1") if expected_digest: self.check_digest(filename, digest.hexdigest(), expected_digest) start_time = chunk_state[0] elapsed = monotonic_time()-start_time mimetype = bytestostr(mimetype) filelog("%i bytes received in %i chunks, took %ims", filesize, chunk, elapsed*1000) t = start_thread(self.do_process_downloaded_file, "process-download", daemon=False, args=(filename, mimetype, printit, openit, filesize, options)) filelog("started process-download thread: %s", t)
def get_keymap_spec(self): v = self.get_keymap_spec_from_xkb() if not v: v = self.get_keymap_spec_using_setxkbmap() from xpra.util import nonl log("get_keymap_spec()=%s", nonl(str(v))) return v
def do_command(self, caps : typedict): def print_fn(s): sys.stdout.write("%s\n" % (s,)) if not caps: self.quit(EXIT_NO_DATA) return exit_code = EXIT_OK try: if FLATTEN_INFO<2: #compatibility mode: c = flatten_dict(caps) for k in sorted_nicely(c.keys()): v = c.get(k) #FIXME: this is a nasty and horrible python3 workaround (yet again) #we want to print bytes as strings without the ugly 'b' prefix.. #it assumes that all the strings are raw or in (possibly nested) lists or tuples only #we assume that all strings we get are utf-8, #and fallback to the bytestostr hack if that fails def fixvalue(w): if isinstance(w, bytes): if k.endswith(".data"): return hexstr(w) return u(w) elif isinstance(w, (tuple,list)): return type(w)([fixvalue(x) for x in w]) return w v = fixvalue(v) k = fixvalue(k) print_fn("%s=%s" % (k, nonl(v))) else: print_nested_dict(caps, print_fn=print_fn) except OSError: exit_code = EXIT_IO_ERROR self.quit(exit_code)
def get_text_data(self): data = [] tb = self.description.get_buffer() buf = tb.get_text(*tb.get_bounds()) if len(buf): data.append(("Description", "", "txt", buf)) for name, dtype, title, value_cb, tooltip in self.toggles: if not bool(value_cb): continue cb = getattr(self, name) assert cb is not None if not cb.get_active(): continue #OK, the checkbox is selected, get the data value = value_cb if type(value_cb) != dict: try: value = value_cb() except TypeError: log.error("error on %s", value_cb, exc_info=True) value = str(value_cb) dtype = "txt" except Exception, e: value = e dtype = "txt" if value is None: continue if type(value) == dict: s = os.linesep.join("%s : %s" % (k.ljust(32), nonl(str(v))) for k, v in sorted(value.items())) elif type(value) in (list, tuple): s = os.linesep.join(str(x) for x in value) else: s = str(value) data.append((title, tooltip, dtype, s))
def main(): from xpra.platform import init as platform_init, clean from xpra.util import nonl from xpra.log import enable_color try: platform_init("GUI-Properties") enable_color() init() verbose = "-v" in sys.argv or "--verbose" in sys.argv if verbose: from xpra.log import get_all_loggers for x in get_all_loggers(): x.enable_debug() # naughty, but how else can I hook this up? import os if os.name == "posix": try: from xpra.x11.bindings import posix_display_source # @UnusedImport except: pass # maybe running on OSX? hope for the best.. i = get_info() for k in sorted(i.keys()): v = i[k] print("* %s : %s" % (k.ljust(32), nonl(v))) finally: clean()
def authenticate(self, challenge_response, client_salt): if not self.salt: log.error( "Error: illegal challenge response received - salt cleared or unset" ) return None salt = self.get_response_salt(client_salt) password = self.get_password() if not password: log.error("Error: authentication failed") log.error(" no password for '%s' in '%s'", self.username, self.password_filename) return False verify = hmac.HMAC(strtobytes(password), strtobytes(salt), digestmod=hashlib.md5).hexdigest() log("authenticate(%s) password='******', hex(salt)=%s, hash=%s", challenge_response, nonl(password), binascii.hexlify(strtobytes(salt)), verify) if hasattr(hmac, "compare_digest"): eq = hmac.compare_digest(verify, challenge_response) else: eq = verify == challenge_response if not eq: log("expected '%s' but got '%s'", verify, challenge_response) log.error("Error: hmac password challenge for '%s' does not match", self.username) return False return True
def _process_hello(self, packet): log.debug("process_hello: %s", packet) props = packet[1] if props: def sorted_nicely(l): """ Sort the given iterable in the way that humans expect.""" def convert(text): if text.isdigit(): return int(text) else: return text alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', bytestostr(key)) ] return sorted(l, key=alphanum_key) for k in sorted_nicely(props.keys()): v = props.get(k) if sys.version_info[0] >= 3: #FIXME: this is a nasty and horrible python3 workaround (yet again) #we want to print bytes as strings without the ugly 'b' prefix.. #it assumes that all the strings are raw or in (possibly nested) lists or tuples only def fixvalue(w): if type(w) == bytes: return bytestostr(w) elif type(w) in (tuple, list): return type(w)([fixvalue(x) for x in w]) return w v = fixvalue(v) log.info("%s=%s", bytestostr(k), nonl(v)) self.quit(0)
def confirm_key(info=()) -> bool: if SKIP_UI: return False from xpra.platform.paths import get_icon_filename from xpra.os_util import use_tty if not use_tty(): icon = get_icon_filename("authentication", "png") or "" prompt = "Are you sure you want to continue connecting?" code = dialog_confirm("Confirm Key", prompt, info, icon, buttons=[("yes", 200), ("NO", 201)]) log("dialog return code=%s", code) r = code == 200 log.info("host key %sconfirmed", ["not ", ""][r]) return r log("confirm_key(%s) will use stdin prompt", nonl(info)) prompt = "Are you sure you want to continue connecting (yes/NO)? " sys.stderr.write(os.linesep.join(info) + os.linesep + prompt) try: v = sys.stdin.readline().rstrip(os.linesep) except KeyboardInterrupt: sys.exit(128 + signal.SIGINT) return v and v.lower() in ("y", "yes")
def __init__(self, app_id=0, title="", move_callbacks=None, click_callback=None, exit_callback=None, command_callback=None, iconPathName=None): log("win32NotifyIcon: app_id=%i, title='%s'", app_id, nonl(title)) self.app_id = app_id self.title = title self.current_icon = None self.move_callback = move_callbacks self.click_callback = click_callback self.exit_callback = exit_callback self.command_callback = command_callback self.reset_function = None self.image_cache = {} # Create the Window. if iconPathName: try: iconPathName = iconPathName.decode() except: pass self.current_icon = self.LoadImage(iconPathName) or FALLBACK_ICON self.create_tray_window() #register callbacks: win32NotifyIcon.instances[self.hwnd] = self
def _parse_protocol_handshake(self, packet): log("parse_protocol_handshake(%s)", nonl(packet)) if len(packet) < 12: return 0 if not packet.startswith(b'RFB '): self._invalid_header( packet, "invalid RFB protocol handshake packet header") return 0 #ie: packet==b'RFB 003.008\n' self._protocol_version = tuple( int(x) for x in packet[4:11].split(b".")) log.info("RFB version %s connection from %s", ".".join(str(x) for x in self._protocol_version), self._conn.target) if self._protocol_version != (3, 8): msg = "unsupported protocol version" log.error("Error: %s", msg) self.send(struct.pack(b"!BI", 0, len(msg)) + msg) self.invalid(msg, packet) return 0 #reply with Security Handshake: self._packet_parser = self._parse_security_handshake if self._authenticator and self._authenticator.requires_challenge(): security_types = [RFBAuth.VNC] else: security_types = [RFBAuth.NONE] packet = struct.pack(b"B", len(security_types)) for x in security_types: packet += struct.pack(b"B", x) self.send(packet) return 12
def make_nid(self, flags): nid = NOTIFYICONDATA() nid.cbSize = sizeof(NOTIFYICONDATA) nid.hWnd = self.hwnd nid.uCallbackMessage = win32con.WM_MENUCOMMAND nid.hIcon = self.current_icon #don't ask why we have to use sprintf to get what we want: title = bytestostr(self.title[:MAX_TIP_SIZE - 1]) nid.szTip = title nid.dwState = 0 nid.dwStateMask = 0 nid.guidItem = XPRA_GUID nid.uID = self.app_id flags |= NIF_GUID #balloon notification bits: #szInfo #uTimeout #szInfoTitle #dwInfoFlags #hBalloonIcon #flags |= NIF_SHOWTIP nid.uVersion = 4 nid.uFlags = flags log("make_nid(..)=%s tooltip='%s', app_id=%i, actual flags=%s", nid, nonl(title), self.app_id, csv([v for k, v in NIF_FLAGS.items() if k & flags])) return nid
def _process_clipboard_packet(self, proto, packet): assert self.clipboard if self.readonly: return ss = self._server_sources.get(proto) if not ss: #protocol has been dropped! return if self._clipboard_client != ss: log( "the clipboard packet '%s' does not come from the clipboard owner!", packet[0]) return if not ss.clipboard_enabled: #this can happen when we disable clipboard in the middle of transfers #(especially when there is a clipboard loop) log.warn("Warning: unexpected clipboard packet") log.warn(" clipboard is disabled for %s", nonl(ss.uuid)) return ch = self._clipboard_helper assert ch, "received a clipboard packet but clipboard sharing is disabled" def do_check(): if self.clipboard_nesting_check("receiving", packet[0], ss): ch.process_clipboard_packet(packet) #the nesting check and the clipboard handlers call gtk: self.idle_add(do_check)
def main(): from xpra.util import nonl from xpra.platform.displayfd import read_displayfd, parse_displayfd import subprocess r_pipe, w_pipe = os.pipe() cmd = [ "xpra", "start", "--daemon=yes", "--systemd-run=no", "--start-via-proxy=no", "--displayfd=%s" % w_pipe, ] proc = subprocess.Popen(cmd, pass_fds=(w_pipe, )) print("Popen(%s)=%s" % (cmd, proc)) buf = read_displayfd(r_pipe, timeout=30, proc=proc) print("read_displayfd(%i)='%s'" % (r_pipe, nonl(buf))) os.close(r_pipe) os.close(w_pipe) def displayfd_err(msg): print("Error: displayfd failed") print(" %s" % msg) sys.exit(1) n = parse_displayfd(buf, displayfd_err) print("Success: display='%s'" % n)
def _process_hello(self, packet): log.debug("process_hello: %s", packet) props = packet[1] if props: def sorted_nicely(l): """ Sort the given iterable in the way that humans expect.""" def convert(text): if text.isdigit(): return int(text) else: return text alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', bytestostr(key)) ] return sorted(l, key = alphanum_key) for k in sorted_nicely(props.keys()): v = props.get(k) if sys.version_info[0]>=3: #FIXME: this is a nasty and horrible python3 workaround (yet again) #we want to print bytes as strings without the ugly 'b' prefix.. #it assumes that all the strings are raw or in (possibly nested) lists or tuples only def fixvalue(w): if type(w)==bytes: return bytestostr(w) elif type(w) in (tuple,list): return type(w)([fixvalue(x) for x in w]) return w v = fixvalue(v) log.info("%s=%s", bytestostr(k), nonl(v)) self.quit(0)
def _process_gibberish(self, packet): log("process_gibberish(%s)", ellipsizer(packet)) message, data = packet[1:3] from xpra.net.socket_util import guess_packet_type #pylint: disable=import-outside-toplevel packet_type = guess_packet_type(data) p = self._protocol exit_code = EXIT_PACKET_FAILURE pcount = p.input_packetcount if p else 0 if pcount<=1: exit_code = EXIT_CONNECTION_FAILED netlog.error("Error: failed to connect") else: netlog.error("Error: received an invalid packet") if packet_type=="xpra": netlog.error(" xpra server bug or mangled packet") if packet_type and packet_type!="xpra": netlog.error(" this is a '%s' packet,", packet_type) netlog.error(" not from an xpra server?") else: netlog.error(" received uninterpretable nonsense: %r", message) data = bytestostr(data).strip("\n\r") show_as_text = pcount<=1 and len(data)<128 and all((c in string.printable) or c in ("\n\r") for c in data) if show_as_text: if data.find("\n")>=0: netlog.error(" data:") for x in data.split("\n"): netlog.error(" %r", x.split("\0")[0]) else: netlog.error(" data: %r", data) else: netlog.error(" packet no %i data: %s", pcount, nonl(repr_ellipsized(data))) self.quit(exit_code)
def do_command(self): if self.server_capabilities: if FLATTEN_INFO<2: #compatibility mode: c = flatten_dict(self.server_capabilities) for k in sorted_nicely(c.keys()): v = c.get(k) if PYTHON3: #FIXME: this is a nasty and horrible python3 workaround (yet again) #we want to print bytes as strings without the ugly 'b' prefix.. #it assumes that all the strings are raw or in (possibly nested) lists or tuples only #we assume that all strings we get are utf-8, #and fallback to the bytestostr hack if that fails def fixvalue(w): if type(w)==bytes: try: return w.decode("utf-8") except: return bytestostr(w) elif type(w) in (tuple,list): return type(w)([fixvalue(x) for x in w]) return w v = fixvalue(v) k = fixvalue(k) log.info("%s=%s", k, nonl(v)) else: print_nested_dict(self.server_capabilities) self.quit(EXIT_OK)
def safe_exec(cmd, stdin=None, log_errors=True, **kwargs): process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) out, err = process.communicate(stdin) code = process.poll() l = log.debug if code != 0 and log_errors: l = log.error l("signal_safe_exec(%s, %s, %s) stdout='%s'", cmd, stdin, kwargs, nonl(out)) l("signal_safe_exec(%s, %s, %s) stderr='%s'", cmd, stdin, kwargs, nonl(err)) return code, out, err
def print_options(o): for k, ot in sorted(OPTION_TYPES.items()): v = getattr(o, name_to_field(k), "") if ot == bool and v is None: v = "Auto" if type(v) == list: v = ", ".join(str(x) for x in v) print("* %-32s : %s" % (k, nonl(v)))
def print_options(o): for k,ot in sorted(OPTION_TYPES.items()): v = getattr(o, name_to_field(k), "") if ot==bool and v is None: v = "Auto" if type(v)==list: v = ", ".join(str(x) for x in v) print("* %-32s : %s" % (k, nonl(v)))
def _process_disconnect(self, packet): #ie: ("disconnect", "version error", "incompatible version") reason = ss(packet[1]) info = packet[2:] s = nonl(reason) if len(info): s += " (%s)" % (", ".join([nonl(ss(x)) for x in info])) if self.server_capabilities is None or len(self.server_capabilities)==0: #server never sent hello to us - so disconnect is an error #(but we don't know which one - the info message may help) log.warn("server failure: disconnected before the session could be established") e = EXIT_FAILURE elif disconnect_is_an_error(reason): log.warn("server failure: %s", reason) e = EXIT_FAILURE else: e = EXIT_OK self.warn_and_quit(e, "server requested disconnect: %s" % s)
def _process_disconnect(self, packet): #ie: ("disconnect", "version error", "incompatible version") reason = bytestostr(packet[1]) info = packet[2:] s = nonl(reason) if len(info): s += " (%s)" % (", ".join([nonl(bytestostr(x)) for x in info])) if self.server_capabilities is None or len(self.server_capabilities)==0: #server never sent hello to us - so disconnect is an error #(but we don't know which one - the info message may help) log.warn("server failure: disconnected before the session could be established") e = EXIT_FAILURE elif disconnect_is_an_error(reason): log.warn("server failure: %s", reason) e = EXIT_FAILURE else: e = EXIT_OK self.warn_and_quit(e, "server requested disconnect: %s" % s)
def print_options(o): for k, ot in sorted(OPTION_TYPES.items()): attr_name = k.replace("-", "_") v = getattr(o, attr_name, "") if ot == bool and v is None: v = "Auto" if type(v) == list: v = ", ".join(str(x) for x in v) print("* %-32s : %s" % (k, nonl(v)))
def get_keymap_spec(self): log("get_keymap_spec() keyboard_bindings=%s", self.keyboard_bindings) if is_Wayland() or not self.keyboard_bindings: locale = self.get_locale_status() query_struct = {} if locale: layout = locale.get("X11 Layout") if layout: query_struct["layout"] = layout log("query_struct(%s)=%s", locale, query_struct) return None, None, query_struct query_struct = self.keyboard_bindings.getXkbProperties() _query = xkbmap_query_tostring(query_struct) log("get_keymap_spec() Xkb query tostring(%s)=%s", query_struct, _query) #we no longer support servers via xkbmap_print: xkbmap_print = "" log("get_keymap_spec()=(%s, %s, %s)", nonl(xkbmap_print), nonl(_query), nonl(query_struct)) return xkbmap_print, _query, query_struct
def print_options(o): for k,ot in sorted(OPTION_TYPES.items()): attr_name = k.replace("-", "_") v = getattr(o, attr_name, "") if ot==bool and v is None: v = "Auto" if type(v)==list: v = ", ".join(str(x) for x in v) print("* %-32s : %s" % (k, nonl(v)))
def _process_send_file_chunk(self, packet): chunk_id, chunk, file_data, has_more = packet[1:5] filelog("_process_send_file_chunk%s", (chunk_id, chunk, "%i bytes" % len(file_data), has_more)) chunk_state = self.receive_chunks_in_progress.get(chunk_id) if not chunk_state: filelog.error("Error: cannot find the file transfer id '%s'", nonl(chunk_id)) self.send("ack-file-chunk", chunk_id, False, "file transfer id not found", chunk) return fd = chunk_state[1] if chunk_state[-1]+1!=chunk: filelog.error("Error: chunk number mismatch, expected %i but got %i", chunk_state[-1]+1, chunk) self.send("ack-file-chunk", chunk_id, False, "chunk number mismatch", chunk) del self.receive_chunks_in_progress[chunk_id] os.close(fd) return #update chunk number: chunk_state[-1] = chunk digest = chunk_state[8] written = chunk_state[9] try: os.write(fd, file_data) digest.update(file_data) written += len(file_data) chunk_state[9] = written except OSError as e: filelog.error("Error: cannot write file chunk") filelog.error(" %s", e) self.send("ack-file-chunk", chunk_id, False, "write error: %s" % e, chunk) del self.receive_chunks_in_progress[chunk_id] try: os.close(fd) except: pass return self.send("ack-file-chunk", chunk_id, True, "", chunk) if has_more: timer = chunk_state[-2] if timer: self.source_remove(timer) #remote end will send more after receiving the ack timer = self.timeout_add(CHUNK_TIMEOUT, self._check_chunk_receiving, chunk_id, chunk) chunk_state[-2] = timer return del self.receive_chunks_in_progress[chunk_id] os.close(fd) #check file size and digest then process it: filename, mimetype, printit, openit, filesize, options = chunk_state[2:8] if written!=filesize: filelog.error("Error: expected a file of %i bytes, got %i", filesize, written) return expected_digest = options.get("sha1") if expected_digest: self.check_digest(filename, digest.hexdigest(), expected_digest) start_time = chunk_state[0] elapsed = time.time()-start_time filelog("%i bytes received in %i chunks, took %ims", filesize, chunk, elapsed*1000) self.do_process_downloaded_file(filename, mimetype, printit, openit, filesize, options)
def _open_file(self, filename): if not self.open_files: log.warn("Warning: opening files automatically is disabled,") log.warn(" ignoring uploaded file:") log.warn(" '%s'", filename) return import subprocess PIPE = subprocess.PIPE process = subprocess.Popen([self.open_command, filename], stdin=PIPE, stdout=PIPE, stderr=PIPE) out, err = process.communicate() r = process.wait() filelog.info("opened file %s with %s, exit code: %s", filename, self.open_command, r) if r!=0: l = filelog.warn else: l = filelog if out: l("stdout=%s", nonl(out)[:512]) if err: l("stderr=%s", nonl(err)[:512])
def get_lpinfo_drv(make_and_model): command = shlex.split(LPINFO) + ["--make-and-model", make_and_model, "-m"] def preexec(): os.setsid() log("get_lpinfo_drv(%s) command=%s", make_and_model, command) proc = subprocess.Popen( command, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, close_fds=True, preexec_fn=preexec, ) # use the global child reaper to make sure this doesn't end up as a zombie from xpra.child_reaper import getChildReaper from xpra.util import nonl cr = getChildReaper() cr.add_process(proc, "lpinfo", command, ignore=True, forget=True) out, err = proc.communicate() if proc.wait() != 0: log.warn("Warning: lpinfo command failed and returned %s", proc.returncode) log.warn(" command used: '%s'", command) return None if sys.version_info[0] >= 3: try: out = out.decode() except: out = str(out) log("lpinfo out=%s", nonl(out)) log("lpinfo err=%s", nonl(err)) if err: log.warn("Warning: lpinfo command produced some warnings:") log.warn(" '%s'", nonl(err)) for line in out.splitlines(): if line.startswith("drv://"): return line.split(" ")[0] return None
def defaults_init(self): #skip warning when running the client from xpra import child_reaper child_reaper.POLL_WARNING = False getChildReaper() log("XpraClientBase.defaults_init() os.environ:") for k,v in os.environ.items(): log(" %s=%s", k, nonl(v)) #client state: self.exit_code = None self.exit_on_signal = False self.display_desc = {} #connection attributes: self.hello_extra = {} self.compression_level = 0 self.display = None self.username = None self.password = None self.password_file = None self.password_sent = False self.bandwidth_limit = 0 self.encryption = None self.encryption_keyfile = None self.server_padding_options = [DEFAULT_PADDING] self.quality = -1 self.min_quality = 0 self.speed = 0 self.min_speed = -1 self.printer_attributes = [] self.send_printers_timer = None self.exported_printers = None self.can_shutdown_server = True #protocol stuff: self._protocol = None self._priority_packets = [] self._ordinary_packets = [] self._mouse_position = None self._aliases = {} self._reverse_aliases = {} #server state and caps: self.server_capabilities = None self.completed_startup = False self._remote_machine_id = None self._remote_uuid = None self._remote_version = None self._remote_revision = None self._remote_platform = None self._remote_platform_release = None self._remote_platform_platform = None self._remote_platform_linux_distribution = None self.uuid = get_user_uuid() self.init_packet_handlers() sanity_checks()
def main(): #use gtk as display source: from xpra.x11.gtk_x11 import gdk_display_source assert gdk_display_source from xpra.util import nonl from xpra.platform import init as platform_init platform_init("GTK-Keyboard", "GTK Keyboard") x = GTKKeyboardHelper(None, True, "") x.query_xkbmap() for k,v in x.get_keymap_properties().items(): print("%s=%s" % (k,nonl(v)))
def _process_disconnect(self, packet): #overriden method so we can avoid printing a warning, #we haven't received the hello back from the server #but that's fine for a request client info = tuple(nonl(bytestostr(x)) for x in packet[1:]) reason = info[0] if disconnect_is_an_error(reason): self.server_disconnect_warning(*info) elif self.exit_code is None: #we're not in the process of exiting already, #tell the user why the server is disconnecting us self.server_disconnect(*info)
def defaults_init(self): # skip warning when running the client from xpra import child_reaper child_reaper.POLL_WARNING = False getChildReaper() log("XpraClientBase.defaults_init() os.environ:") for k, v in os.environ.items(): log(" %s=%s", k, nonl(v)) # client state: self.exit_code = None self.exit_on_signal = False self.display_desc = {} # connection attributes: self.hello_extra = {} self.compression_level = 0 self.display = None self.username = None self.password = None self.password_file = None self.password_sent = False self.encryption = None self.encryption_keyfile = None self.server_padding_options = [DEFAULT_PADDING] self.quality = -1 self.min_quality = 0 self.speed = 0 self.min_speed = -1 self.printer_attributes = [] self.send_printers_timer = None self.exported_printers = None # protocol stuff: self._protocol = None self._priority_packets = [] self._ordinary_packets = [] self._mouse_position = None self._aliases = {} self._reverse_aliases = {} # server state and caps: self.server_capabilities = None self._remote_machine_id = None self._remote_uuid = None self._remote_version = None self._remote_revision = None self._remote_platform = None self._remote_platform_release = None self._remote_platform_platform = None self._remote_platform_linux_distribution = None self.uuid = get_user_uuid() self.init_packet_handlers() sanity_checks()
def dump_dict(d): pk = None try: for pk,pv in d.items(): try: if type(pv)==unicode: sv = pv.encode("utf8") else: sv = nonl(pver(pv)) except Exception as e: sv = repr(pv) print(" %s : %s" % (pk.ljust(32), sv)) except Exception as e: print(" error on %s: %s" % (pk, e)) print(" raw attributes: " % d)
def get_pactl_stat_line(prefix): if not has_pa(): return "" code, out, err = pactl_output(False, "stat") if code!=0: log.warn("Warning: failed to query pulseaudio using 'pactl list'") if err: log.warn(" %s", nonl(err)) return "" stat = "" for line in out.splitlines(): if line.startswith(prefix): stat = line[len(prefix):].strip() break log("get_pactl_stat_line(%s)=%s", prefix, stat) return stat
def _process_hello(self, packet): log.debug("process_hello: %s", packet) props = packet[1] if props: def sorted_nicely(l): """ Sort the given iterable in the way that humans expect.""" def convert(text): if text.isdigit(): return int(text) else: return text alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] return sorted(l, key = alphanum_key) for k in sorted_nicely(props.keys()): v = props.get(k) log.info("%s=%s", k, nonl(v)) self.quit(0)
def do_command(self): if self.server_capabilities: if FLATTEN_INFO<2: #compatibility mode: for k in sorted_nicely(self.server_capabilities.keys()): v = self.server_capabilities.get(k) if sys.version_info[0]>=3: #FIXME: this is a nasty and horrible python3 workaround (yet again) #we want to print bytes as strings without the ugly 'b' prefix.. #it assumes that all the strings are raw or in (possibly nested) lists or tuples only def fixvalue(w): if type(w)==bytes: return bytestostr(w) elif type(w) in (tuple,list): return type(w)([fixvalue(x) for x in w]) return w v = fixvalue(v) log.info("%s=%s", bytestostr(k), nonl(v)) else: print_nested_dict(self.server_capabilities) self.quit(EXIT_OK)
def dump_printers(d): for k in sorted(d.keys()): v = d[k] print("* %s" % k) pk = None try: for pk,pv in v.items(): try: if type(pv)==unicode: sv = pv.encode("utf8") else: sv = nonl(pver(pv)) except Exception as e: sv = repr(pv) print(" %s : %s" % (pk.ljust(32), sv)) except Exception as e: print(" error on %s: %s" % (pk, e)) print(" raw attributes: " % v) attr = get_printer_attributes(k) if attr: print(" attributes:") for a in attr: print(" %s" % a)
def update_server_settings(self, settings, reset=False): if not self.xsettings_enabled: settingslog("ignoring xsettings update: %s", settings) return if reset: #FIXME: preserve serial? (what happens when we change values which had the same serial?) self.reset_settings() self._settings = {} if self.default_xsettings: self._settings = self._default_xsettings[1] old_settings = dict(self._settings) settingslog("server_settings: old=%s, updating with=%s", nonl(old_settings), nonl(settings)) settingslog("overrides: dpi=%s, double click time=%s, double click distance=%s", self.dpi, self.double_click_time, self.double_click_distance) settingslog("overrides: antialias=%s", self.antialias) self._settings.update(settings) root = gtk.gdk.get_default_root_window() for k, v in settings.items(): #cook the "resource-manager" value to add the DPI: if k=="resource-manager" and self.dpi>0: value = v.decode("utf-8") #parse the resources into a dict: values={} options = value.split("\n") for option in options: if not option: continue parts = option.split(":\t") if len(parts)!=2: continue values[parts[0]] = parts[1] values["Xft.dpi"] = self.dpi values["Xft/DPI"] = self.dpi*1024 values["gnome.Xft/DPI"] = self.dpi*1024 if self.antialias: ad = typedict(self.antialias) values.update({ "Xft.antialias" : ad.intget("enabled", -1), "Xft.hinting" : ad.intget("hinting", -1), "Xft.rgba" : ad.strget("orientation", "none").lower(), "Xft.hintstyle" : self._get_antialias_hintstyle()}) settingslog("server_settings: resource-manager values=%s", nonl(values)) #convert the dict back into a resource string: value = '' for vk, vv in values.items(): value += "%s:\t%s\n" % (vk, vv) #record the actual value used self._settings["resource-manager"] = value v = value.encode("utf-8") #cook xsettings to add double-click settings: #(as those may not be present in xsettings on some platforms.. like win32 and osx) if k=="xsettings-blob" and (self.double_click_time>0 or self.double_click_distance!=(-1, -1)): from xpra.x11.xsettings_prop import XSettingsTypeInteger, XSettingsTypeString def set_xsettings_value(name, value_type, value): #remove existing one, if any: serial, values = v new_values = [(_t,_n,_v,_s) for (_t,_n,_v,_s) in values if _n!=name] new_values.append((value_type, name, value, 0)) return serial, new_values def set_xsettings_int(name, value): if value<0: #not set, return v unchanged return v return set_xsettings_value(name, XSettingsTypeInteger, value) if self.dpi>0: v = set_xsettings_int("Xft/DPI", self.dpi*1024) if self.double_click_time>0: v = set_xsettings_int("Net/DoubleClickTime", self.double_click_time) if self.antialias: ad = typedict(self.antialias) v = set_xsettings_int("Xft/Antialias", ad.intget("enabled", -1)) v = set_xsettings_int("Xft/Hinting", ad.intget("hinting", -1)) v = set_xsettings_value("Xft/RGBA", XSettingsTypeString, ad.strget("orientation", "none").lower()) v = set_xsettings_value("Xft/HintStyle", XSettingsTypeString, self._get_antialias_hintstyle()) if self.double_click_distance!=(-1, -1): #some platforms give us a value for each axis, #but X11 only has one, so take the average try: x,y = self.double_click_distance if x>0 and y>0: d = (x+y)//2 d = max(1, min(128, d)) #sanitize it a bit v = set_xsettings_int("Net/DoubleClickDistance", d) except Exception as e: log.warn("error setting double click distance from %s: %s", self.double_click_distance, e) if k not in old_settings or v != old_settings[k]: def root_set(p): settingslog("server_settings: setting %s to %s", nonl(p), nonl(v)) prop_set(root, p, "latin1", v.decode("utf-8")) if k == "xsettings-blob": self.set_xsettings(v) elif k == "resource-manager": root_set("RESOURCE_MANAGER") elif self.pulseaudio: if k == "pulse-cookie": root_set("PULSE_COOKIE") elif k == "pulse-id": root_set("PULSE_ID") elif k == "pulse-server": root_set("PULSE_SERVER")
def print_version_dict(d, vformat=pver): for k in sorted(d.keys()): v = d[k] print("* %-48s : %s" % (str(k).replace(".version", "").ljust(12), nonl(vformat(v))))
def root_set(p): settingslog("server_settings: setting %s to %s", nonl(p), nonl(v)) prop_set(root, p, "latin1", v.decode("utf-8"))
def authenticate(self, challenge_response, client_salt): if not self.salt: log.error("Error: illegal challenge response received - salt cleared or unset") return None #ensure this salt does not get re-used: if client_salt is None: salt = self.salt else: salt = xor(self.salt, client_salt) self.salt = None password = self.get_password() if not password: log.error("Error: authentication failed") log.error(" no password for '%s' in '%s'", self.username, self.password_filename) return False verify = hmac.HMAC(strtobytes(password), strtobytes(salt), digestmod=hashlib.md5).hexdigest() log("authenticate(%s) password='******', hex(salt)=%s, hash=%s", challenge_response, nonl(password), binascii.hexlify(strtobytes(salt)), verify) if not hmac.compare_digest(verify, challenge_response): log("expected '%s' but got '%s'", verify, challenge_response) log.error("Error: hmac password challenge for '%s' does not match", self.username) return False return True
def set_keymap(self): if not self.enabled: return clean_keyboard_state() log("set_keymap() layout=%s, variant=%s, print=%s, query=%s", self.xkbmap_layout, self.xkbmap_variant, nonl(self.xkbmap_print), nonl(self.xkbmap_query)) try: do_set_keymap(self.xkbmap_layout, self.xkbmap_variant, self.xkbmap_print, self.xkbmap_query, self.xkbmap_query_struct) except: log.error("error setting new keymap", exc_info=True) self.is_native_keymap = bool(self.xkbmap_print) or bool(self.xkbmap_query) try: #first clear all existing modifiers: clean_keyboard_state() if not self.xkbmap_raw: clear_modifiers(ALL_X11_MODIFIERS.keys()) #just clear all of them (set or not) #now set all the keycodes: clean_keyboard_state() has_keycodes = (self.xkbmap_x11_keycodes and len(self.xkbmap_x11_keycodes)>0) or \ (self.xkbmap_keycodes and len(self.xkbmap_keycodes)>0) assert has_keycodes, "client failed to provide any keycodes!" #first compute the modifier maps as this may have an influence #on the keycode mappings (at least for the from_keycodes case): if self.xkbmap_mod_meanings: #Unix-like OS provides modifier meanings: self.keynames_for_mod = get_modifiers_from_meanings(self.xkbmap_mod_meanings) elif self.xkbmap_keycodes: #non-Unix-like OS provides just keycodes for now: self.keynames_for_mod = get_modifiers_from_keycodes(self.xkbmap_keycodes) else: log.error("missing both xkbmap_mod_meanings and xkbmap_keycodes, modifiers will probably not work as expected!") self.keynames_for_mod = {} #if the client does not provide a full keymap, #try to preserve the initial server keycodes #(used by non X11 clients like osx,win32 or Android) preserve_server_keycodes = not self.xkbmap_print and not self.xkbmap_query self.keycode_translation = set_all_keycodes(self.xkbmap_x11_keycodes, self.xkbmap_keycodes, preserve_server_keycodes, self.keynames_for_mod) self.add_gtk_keynames() #now set the new modifier mappings: clean_keyboard_state() log("going to set modifiers, xkbmap_mod_meanings=%s, len(xkbmap_keycodes)=%s", self.xkbmap_mod_meanings, len(self.xkbmap_keycodes or [])) if self.keynames_for_mod: set_modifiers(self.keynames_for_mod) log("keynames_for_mod=%s", self.keynames_for_mod) self.compute_modifier_keynames() else: self.keycode_translation = {} log("keyboard raw mode, keycode translation left empty") log("keycode mappings=%s", X11Keyboard.get_keycode_mappings()) mod_mappings = X11Keyboard.get_modifier_mappings() self.xkbmap_mod_meanings = {} for mod, mod_defs in mod_mappings.items(): for mod_def in mod_defs: for v in mod_def: if type(v)==int: l = self.keycodes_for_modifier_keynames.setdefault(mod, []) else: self.xkbmap_mod_meanings[v] = mod l = self.keynames_for_mod.setdefault(mod, []) if v not in l: l.append(v) log("keynames_for_mod=%s", self.keynames_for_mod) log("keycodes_for_modifier_keynames=%s", self.keycodes_for_modifier_keynames) log("mod_meanings=%s", self.xkbmap_mod_meanings) self.compute_client_modifier_keycodes() log("keyname_for_mod=%s", self.keynames_for_mod) clean_keyboard_state() except: log.error("error setting xmodmap", exc_info=True)
def logstdin(): if not stdin or len(stdin)<500: return nonl(stdin) return nonl(stdin[:500])+".."
def print_dict(d): for k in sorted(d.keys()): v = d[k] print("* %s : %s" % (k.ljust(32), nonl(pver(v))))