def do_control_file_command(self, command_type, client_uuids, filename, source_flag_name, send_file_args): #find the clients: sources = self._control_get_sources(client_uuids) if not sources: raise ControlError("no clients found matching: %s" % client_uuids) #find the file and load it: actual_filename = os.path.abspath(os.path.expanduser(filename)) try: stat = os.stat(actual_filename) log("os.stat(%s)=%s", actual_filename, stat) except os.error: log("os.stat(%s)", actual_filename, exc_info=True) if not os.path.exists(actual_filename): raise ControlError("file '%s' does not exist" % filename) data = load_binary_file(actual_filename) #verify size: file_size = len(data) file_size_MB = file_size//1024//1024 if file_size_MB>self.file_transfer.file_size_limit: raise ControlError("file '%s' is too large: %iMB (limit is %iMB)" % ( filename, file_size_MB, self.file_transfer.file_size_limit)) #send it to each client: for ss in sources: #ie: ServerSource.file_transfer (found in FileTransferAttributes) if not getattr(ss, source_flag_name): log.warn("Warning: cannot %s '%s'", command_type, filename) log.warn(" client %s does not support this feature", ss) elif file_size_MB>ss.file_size_limit: log.warn("Warning: cannot %s '%s'", command_type, filename) log.warn(" client %s file size limit is %iMB (file is %iMB)", ss, ss.file_size_limit, file_size_MB) else: ss.send_file(filename, "", data, file_size, *send_file_args) return "%s of '%s' to %s initiated" % (command_type, filename, client_uuids)
def control_command_key(self, keycode_str, press=True): if self.readonly: return try: if keycode_str.startswith("0x"): keycode = int(keycode_str, 16) else: keycode = int(keycode_str) except ValueError: raise ControlError( "invalid keycode specified: '%s' (not a number)" % keycode_str) from None if keycode <= 0 or keycode >= 255: raise ControlError( "invalid keycode value: '%s' (must be between 1 and 255)" % keycode_str) if press is not True: if press in ("1", "press"): press = True elif press in ("0", "unpress"): press = False else: raise ControlError( "if present, the press argument must be one of: %s" % csv( ("1", "press", "0", "unpress"))) self.fake_key(keycode, press)
def do_control_command_start(self, ignore, *args): if not self.start_new_commands: raise ControlError("this feature is currently disabled") proc = self.start_command(" ".join(args), args, ignore, shell=True) if not proc: raise ControlError("failed to start new child command %s" % str(args)) return "new %scommand started with pid=%s" % (["child ", ""][ignore], proc.pid)
def control_command_workspace(self, wid, workspace): window = self._id_to_window.get(wid) if not window: raise ControlError("window %s does not exist", wid) if "workspace" not in window.get_property_names(): raise ControlError("cannot set workspace on window %s", window) if workspace<0: raise ControlError("invalid workspace value: %s", workspace) window.set_property("workspace", workspace) return "window %s moved to workspace %s" % (wid, workspace)
def do_control_file_command(self, command_type, client_uuids, filename, source_flag_name, send_file_args): #find the clients: sources = self._control_get_sources(client_uuids) if not sources: raise ControlError("no clients found matching: %s" % client_uuids) def checksize(file_size): if file_size > self.file_transfer.file_size_limit: raise ControlError( "file '%s' is too large: %sB (limit is %sB)" % (filename, std_unit(file_size), std_unit(self.file_transfer.file_size_limit))) #find the file and load it: actual_filename = os.path.abspath(os.path.expanduser(filename)) try: stat = os.stat(actual_filename) log("os.stat(%s)=%s", actual_filename, stat) except os.error: log("os.stat(%s)", actual_filename, exc_info=True) else: checksize(stat.st_size) if not os.path.exists(actual_filename): raise ControlError("file '%s' does not exist" % filename) data = load_binary_file(actual_filename) if data is None: raise ControlError("failed to load '%s'" % actual_filename) #verify size: file_size = len(data) checksize(file_size) #send it to each client: for ss in sources: #ie: ServerSource.file_transfer (found in FileTransferAttributes) if not getattr(ss, source_flag_name, False): #skip the warning if the client is not interactive #(for now just check for 'top' client): if ss.client_type == "top": l = log else: l = log.warn l("Warning: cannot %s '%s' to %s client", command_type, filename, ss.client_type) l(" client %s does not support this feature", ss.uuid) elif file_size > ss.file_size_limit: log.warn("Warning: cannot %s '%s'", command_type, filename) log.warn(" client %s file size limit is %sB (file is %sB)", ss, std_unit(ss.file_size_limit), std_unit(file_size)) else: ss.send_file(filename, "", data, file_size, *send_file_args) return "%s of '%s' to %s initiated" % (command_type, filename, client_uuids)
def checksize(file_size): file_size_MB = file_size // 1024 // 1024 if file_size_MB > self.file_transfer.file_size_limit: raise ControlError( "file '%s' is too large: %iMB (limit is %iMB)" % (filename, file_size_MB, self.file_transfer.file_size_limit))
def _control_windowsources_from_args(self, *args): #converts the args to valid window ids, #then returns all the window sources for those wids if len(args)==0 or len(args)==1 and args[0]=="*": #default to all if unspecified: wids = tuple(self._id_to_window.keys()) else: wids = [] for x in args: try: wid = int(x) except: raise ControlError("invalid window id: %s" % x) if wid in self._id_to_window: wids.append(wid) else: log("window id %s does not exist", wid) wss = {} for csource in tuple(self._server_sources.values()): for wid in wids: ws = csource.window_sources.get(wid) window = self._id_to_window.get(wid) if window and ws: wss[ws] = window return wss
def parse_boolean_value(v): if str(v).lower() in TRUE_OPTIONS: return True elif str(v).lower() in FALSE_OPTIONS: return False else: raise ControlError("a boolean is required, not %s" % v)
def control_command_key(self, keycode_str, press = True): if self.readonly: return try: if keycode_str.startswith("0x"): keycode = int(keycode_str, 16) else: keycode = int(keycode_str) assert keycode>0 and keycode<=255 except: raise ControlError("invalid keycode specified: '%s' (must be a number between 1 and 255)" % keycode_str) if press is not True: if press in ("1", "press"): press = True elif press in ("0", "unpress"): press = False else: raise ControlError("if present, the press argument must be one of: %s", ("1", "press", "0", "unpress")) self.fake_key(keycode, press)
def control_command_encoder(self, encoder): e = encoder.lower() from xpra.net import packet_encoding opts = packet_encoding.get_enabled_encoders() #ie: [rencode, bencode, yaml] if e not in opts: raise ControlError("encoder argument must be one of: %s" % csv(opts)) for cproto in tuple(self._server_sources.keys()): cproto.enable_encoder(e) self.all_send_client_command("enable_%s" % e) return "encoders set to %s" % encoder
def control_command_compression(self, compression): c = compression.lower() from xpra.net import compression opts = compression.get_enabled_compressors() #ie: [lz4, lzo, zlib] if c not in opts: raise ControlError("compressor argument must be one of: %s" % csv(opts)) for cproto in tuple(self._server_sources.keys()): cproto.enable_compressor(c) self.all_send_client_command("enable_%s" % c) return "compressors set to %s" % compression
def control_command_open_url(self, url, client_uuids="*"): #find the clients: sources = self._control_get_sources(client_uuids) if not sources: raise ControlError("no clients found matching: %s" % client_uuids) clients = 0 for ss in sources: if ss.send_open_url(url): clients += 1 return "url sent to %i clients" % clients
def handle_stop_command(self, *args): display = args[0] log("stop command: will try to find proxy process for display %s", display) for process, v in self.processes.items(): disp,mq = v if disp==display: pid = process.pid log.info("stop command: found process %s with pid %s for display %s, sending it 'stop' request", process, pid, display) mq.put("stop") return "stopped proxy process with pid %s" % pid raise ControlError("no proxy found for display %s" % display)
def control_command_moveresize(self, wid, x, y, w, h): window = self._id_to_window.get(wid) if not window: raise ControlError("window %s does not exist" % wid) count = 0 for source in tuple(self._server_sources.values()): move_resize_window = getattr(source, "move_resize_window", None) if move_resize_window: move_resize_window(wid, window, x, y, w, h) count += 1 return "window %s moved to %i,%i and resized to %ix%i for %i clients" % (wid, x, y, w, h, count)
def _control_video_subregions_from_wid(self, wid): if wid not in self._id_to_window: raise ControlError("invalid window %i" % wid) video_subregions = [] for ws in self._control_windowsources_from_args(wid).keys(): vs = getattr(ws, "video_subregion", None) if not vs: log.warn("Warning: cannot set video region enabled flag on window %i:", wid) log.warn(" no video subregion attribute found in %s", type(ws)) continue video_subregions.append(vs) #log("_control_video_subregions_from_wid(%s)=%s", wid, video_subregions) return video_subregions
def handle_stop_command(self, *args): display = args[0] log("stop command: will try to find proxy process for display %s", display) for instance, v in dict(self.instances).items(): _, disp, _ = v if disp == display: log.info( "stop command: found matching process %s with pid %i for display %s", instance, instance.pid, display) self.stop_proxy(instance) return "stopped proxy instance for display %s" % display raise ControlError("no proxy found for display %s" % display)
def control_command_delete(self, wid): window = self._id_to_window.get(wid) if not window: raise ControlError("window %s does not exist" % wid) window.send_delete() return "requested window %s deleted" % window
def checksize(file_size): if file_size>self.file_transfer.file_size_limit: raise ControlError("file '%s' is too large: %sB (limit is %sB)" % ( filename, std_unit(file_size), std_unit(self.file_transfer.file_size_limit)))