Ticket #1026: file-transfer-refactoring.diff
File file-transfer-refactoring.diff, 29.6 KB (added by , 5 years ago) |
---|
-
xpra/client/client_base.py
135 135 self.speed = opts.speed 136 136 self.min_speed = opts.min_speed 137 137 #printing and file transfer: 138 FileTransferHandler.init (self, opts)138 FileTransferHandler.init_opts(self, opts) 139 139 140 140 if DETECT_LEAKS: 141 141 from xpra.util import detect_leaks … … 643 643 return False 644 644 self.parse_printing_capabilities() 645 645 self.parse_logging_capabilities() 646 self.parse_file_transfer_caps(self.server_capabilities) 646 647 netlog("server_connection_established() adding authenticated packet handlers") 647 648 self.init_authenticated_packet_handlers() 648 649 return True -
xpra/client/gtk_base/gtk_client_base.py
150 150 return self.start_new_command 151 151 152 152 def show_file_upload(self, *args): 153 filelog("show_file_upload%s can open=%s", args, self. server_open_files)153 filelog("show_file_upload%s can open=%s", args, self.remote_open_files) 154 154 buttons = [gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL] 155 if self. server_open_files:155 if self.remote_open_files: 156 156 buttons += [gtk.STOCK_OPEN, gtk.RESPONSE_ACCEPT] 157 157 buttons += [gtk.STOCK_OK, gtk.RESPONSE_OK] 158 158 dialog = gtk.FileChooserDialog("File to upload", parent=None, action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=tuple(buttons)) … … 167 167 data, filesize, entity = gfile.load_contents() 168 168 filelog("load_contents: filename=%s, %i bytes, entity=%s, response=%s", filename, filesize, entity, v) 169 169 dialog.destroy() 170 self.send_file(filename, data,filesize, openit=(v==gtk.RESPONSE_ACCEPT))170 self.send_file(filename, "", data, filesize=filesize, openit=(v==gtk.RESPONSE_ACCEPT)) 171 171 172 172 173 173 def show_about(self, *args): -
xpra/client/gtk_base/gtk_tray_menu_base.py
1091 1091 def make_uploadmenuitem(self): 1092 1092 self.upload = self.menuitem("Upload File", "upload.png", "Send a file to the server", self.client.show_file_upload) 1093 1093 def enable_upload(*args): 1094 log("enable_upload%s server_file_transfer=%s", args, self.client. server_file_transfer)1095 set_sensitive(self.upload, self.client. server_file_transfer)1096 if not self.client. server_file_transfer:1094 log("enable_upload%s server_file_transfer=%s", args, self.client.remote_file_transfer) 1095 set_sensitive(self.upload, self.client.remote_file_transfer) 1096 if not self.client.remote_file_transfer: 1097 1097 self.upload.set_tooltip_text("Not supported by the server") 1098 1098 self.client.after_handshake(enable_upload) 1099 1099 return self.upload -
xpra/client/ui_client_base.py
12 12 import datetime 13 13 import traceback 14 14 import logging 15 import hashlib16 15 from collections import deque 17 16 from threading import RLock 18 17 … … 254 253 self.server_is_shadow = False 255 254 self.server_supports_sharing = False 256 255 self.server_supports_window_filters = False 257 self.server_file_transfer = False258 self.server_file_size_limit = 10259 self.server_open_files = False260 256 #what we told the server about our encoding defaults: 261 257 self.encoding_defaults = {} 262 258 … … 1190 1186 log("send_start_command(%s, %s, %s, %s)", name, command, ignore, sharing) 1191 1187 self.send("start-command", name, command, ignore, sharing) 1192 1188 1193 def send_file(self, filename, data, filesize, openit):1194 if not self.file_transfer:1195 filelog.warn("Warning: file transfers are not enabled for %s", self)1196 return False1197 assert len(data)>=filesize1198 data = data[:filesize] #gio may null terminate it1199 filelog("send_file%s", (filename, "%i bytes" % filesize, openit))1200 absfile = os.path.abspath(filename)1201 basefilename = os.path.basename(filename)1202 cdata = self.compressed_wrapper("file-data", data)1203 assert len(cdata)<=filesize #compressed wrapper ensures this is true1204 if filesize>self.file_size_limit*1024*1024:1205 filelog.warn("Warning: cannot upload the file '%s'", basefilename)1206 filelog.warn(" this file is too large: %sB", std_unit(filesize, unit=1024))1207 filelog.warn(" the file size limit is %iMB", self.file_size_limit)1208 return False1209 if filesize>self.server_file_size_limit*1024*1024:1210 filelog.warn("Warning: cannot upload the file '%s'", basefilename)1211 filelog.warn(" this file is too large: %sB", std_unit(filesize, unit=1024))1212 filelog.warn(" the file size limit for %s is %iMB", self._protocol, self.server_file_size_limit)1213 return False1214 printit = False1215 mimetype = ""1216 u = hashlib.sha1()1217 u.update(data)1218 filelog("sha1 digest(%s)=%s", absfile, u.hexdigest())1219 options = {"sha1" : u.hexdigest()}1220 self.send("send-file", basefilename, mimetype, printit, openit, filesize, cdata, options)1221 return True1222 1189 1223 1224 1190 def send_focus(self, wid): 1225 1191 focuslog("send_focus(%s)", wid) 1226 1192 self.send("focus", wid, self.get_current_modifiers()) … … 1775 1741 default_rpc_types = [] 1776 1742 self.server_rpc_types = c.strlistget("rpc-types", default_rpc_types) 1777 1743 self.start_new_commands = c.boolget("start-new-commands") 1778 self.server_file_transfer = c.boolget("file-transfer")1779 self.server_file_size_limit = c.intget("file-size-limit", 10)1780 self.server_open_files = c.boolget("open-files")1781 1744 self.mmap_enabled = self.supports_mmap and self.mmap_enabled and c.boolget("mmap_enabled") 1782 1745 if self.mmap_enabled: 1783 1746 mmap_token = c.intget("mmap_token") -
xpra/net/file_transfer.py
1 1 # This file is part of Xpra. 2 # Copyright (C) 2010-201 5Antoine Martin <antoine@devloop.org.uk>2 # Copyright (C) 2010-2016 Antoine Martin <antoine@devloop.org.uk> 3 3 # Copyright (C) 2008, 2010 Nathaniel Smith <njs@pobox.com> 4 4 # Xpra is released under the terms of the GNU GPL v2, or, at your option, any 5 5 # later version. See the file COPYING for details. 6 6 7 7 import os 8 import time 9 import subprocess, shlex 10 import hashlib 8 11 9 12 from xpra.log import Logger 10 13 printlog = Logger("printing") … … 12 15 13 16 from xpra.child_reaper import getChildReaper 14 17 from xpra.util import typedict, csv 18 from xpra.simple_stats import std_unit 15 19 16 20 DELETE_PRINTER_FILE = os.environ.get("XPRA_DELETE_PRINTER_FILE", "1")=="1" 17 21 18 22 19 class FileTransferHandler(object): 20 """ Utility class for receiving files and optionally printing them, 21 used by both clients and server to share the common code and attributes 22 """ 23 class FileTransferAttributes(object): 24 def __init__(self, opts=None): 25 if opts: 26 self.init_opts(opts) 27 else: 28 self.init_attributes() 23 29 24 def __init__(self): 25 self.file_transfer = False 26 self.file_size_limit = 10 27 self.printing = False 28 self.open_files = False 29 self.open_command = None 30 def init_opts(self, opts): 31 #get the settings from a config object 32 self.init_attributes(opts.file_transfer, opts.file_size_limit, opts.printing, opts.open_files, opts.open_command) 30 33 31 def init (self, opts):34 def init_attributes(self, file_transfer=False, file_size_limit=10, printing=False, open_files=False, open_command=None): 32 35 #printing and file transfer: 33 self.file_transfer = opts.file_transfer34 self.file_size_limit = opts.file_size_limit35 self.printing = opts.printing36 self.open_ command = opts.open_command37 self.open_ files = opts.open_files36 self.file_transfer = file_transfer 37 self.file_size_limit = file_size_limit 38 self.printing = printing 39 self.open_files = open_files 40 self.open_command = open_command 38 41 39 40 42 def get_file_transfer_features(self): 43 #used in hello packets 41 44 return { 42 "file-transfer": self.file_transfer,43 "file-size-limit": self.file_size_limit,44 "open-files": self.open_files,45 "printing": self.printing,46 45 "file-transfer" : self.file_transfer, 46 "file-size-limit" : self.file_size_limit, 47 "open-files" : self.open_files, 48 "printing" : self.printing, 49 } 47 50 48 def get_ file_transfer_info(self):51 def get_info(self): 49 52 #slightly different from above... for legacy reasons 50 #this one is used in a proper "file." namespace from server_base.py53 #this one is used for get_info() in a proper "file." namespace from server_base.py 51 54 return { 52 "transfer": self.file_transfer,53 "size-limit": self.file_size_limit,54 "open": self.open_files,55 55 "enabled" : self.file_transfer, 56 "size-limit" : self.file_size_limit, 57 "open" : self.open_files, 58 } 56 59 57 60 61 class FileTransferHandler(FileTransferAttributes): 62 """ 63 Utility class for receiving files and optionally printing them, 64 used by both clients and server to share the common code and attributes 65 """ 66 67 def init_attributes(self, *args): 68 FileTransferAttributes.init_attributes(self, *args) 69 self.remote_file_transfer = False 70 self.remote_printing = False 71 self.remote_open_files = False 72 self.remote_file_size_limit = 0 73 74 def parse_file_transfer_caps(self, c): 75 self.remote_file_transfer = c.boolget("file-transfer") 76 self.remote_printing = c.boolget("printing") 77 self.remote_open_files = c.boolget("open-files") 78 self.remote_file_size_limit = c.boolget("file-size-limit") 79 80 def get_info(self): 81 info = FileTransferAttributes.get_info(self) 82 info["remote"] = { 83 "file-transfer" : self.remote_file_transfer, 84 "printing" : self.remote_printing, 85 "open-files" : self.remote_open_files, 86 "file-size-limit" : self.remote_file_size_limit, 87 } 88 return info 89 90 58 91 def _process_send_file(self, packet): 59 92 #send-file basefilename, printit, openit, filesize, 0, data) 60 93 from xpra.platform.paths import get_download_dir … … 78 111 l.error(" %iMB, the file size limit is %iMB", filesize//1024//1024, self.file_size_limit) 79 112 return 80 113 #check digest if present: 81 import hashlib82 114 def check_digest(algo="sha1", libfn=hashlib.sha1): 83 115 digest = options.get(algo) 84 116 if not digest: … … 125 157 finally: 126 158 os.close(fd) 127 159 l.info("downloaded %s bytes to %s file%s:", filesize, (mimetype or "unknown"), ["", " for printing"][int(printit)]) 128 l.info(" %s", filename)160 l.info(" '%s'", filename) 129 161 if printit: 130 162 printer = options.strget("printer") 131 163 title = options.strget("title") … … 141 173 self._open_file(filename) 142 174 143 175 def _print_file(self, filename, mimetype, printer, title, options): 144 import time145 176 from xpra.platform.printing import print_files, printing_finished, get_printers 146 177 printers = get_printers() 147 178 if printer not in printers: … … 183 214 filelog.warn(" ignoring uploaded file:") 184 215 filelog.warn(" '%s'", filename) 185 216 return 186 import subprocess, shlex187 217 command = shlex.split(self.open_command)+[filename] 188 218 proc = subprocess.Popen(command) 189 219 cr = getChildReaper() … … 194 224 filelog.warn("Warning: failed to open the downloaded file") 195 225 filelog.warn(" '%s %s' returned %s", self.open_command, filename, returncode) 196 226 cr.add_process(proc, "Open File %s" % filename, command, True, True, open_done) 227 228 def send_file(self, filename, mimetype, data, filesize=0, printit=False, openit=False, options={}): 229 if printit: 230 if not self.printing: 231 printlog.warn("Warning: printing is not enabled for %s", self) 232 return False 233 if not self.remote_printing: 234 printlog.warn("Warning: remote end does not support printing") 235 return False 236 action = "print" 237 l = printlog 238 else: 239 if not self.file_transfer: 240 filelog.warn("Warning: file transfers are not enabled for %s", self) 241 return False 242 if not self.remote_file_transfer: 243 printlog.warn("Warning: remote end does not support file transfers") 244 return False 245 action = "upload" 246 l = filelog 247 l("send_file%s", (filename, mimetype, "%s bytes" % len(data), printit, openit, options)) 248 if not printit and openit and not self.remote_open_files: 249 l.warn("Warning: opening the file after transfer is disabled on the remote end") 250 openit = False 251 assert len(data)>=filesize, "data is smaller then the given file size!" 252 data = data[:filesize] #gio may null terminate it 253 filelog("send_file%s", (filename, "%i bytes" % filesize, openit)) 254 absfile = os.path.abspath(filename) 255 basefilename = os.path.basename(filename) 256 cdata = self.compressed_wrapper("file-data", data) 257 assert len(cdata)<=filesize #compressed wrapper ensures this is true 258 if filesize>self.file_size_limit*1024*1024: 259 filelog.warn("Warning: cannot %s the file '%s'", action, basefilename) 260 filelog.warn(" this file is too large: %sB", std_unit(filesize, unit=1024)) 261 filelog.warn(" the file size limit is %iMB", self.file_size_limit) 262 return False 263 if filesize>self.remote_file_size_limit*1024*1024: 264 filelog.warn("Warning: cannot %s the file '%s'", action, basefilename) 265 filelog.warn(" this file is too large: %sB", std_unit(filesize, unit=1024)) 266 filelog.warn(" the remote file size limit is %iMB", self.remote_file_size_limit) 267 return False 268 mimetype = "" 269 u = hashlib.sha1() 270 u.update(data) 271 filelog("sha1 digest(%s)=%s", absfile, u.hexdigest()) 272 options = {"sha1" : u.hexdigest()} 273 self.send("send-file", basefilename, mimetype, printit, openit, filesize, cdata, options) 274 return True -
xpra/server/server_base.py
21 21 clientlog = Logger("client") 22 22 screenlog = Logger("screen") 23 23 printlog = Logger("printing") 24 filelog = Logger("file") 24 25 netlog = Logger("network") 25 26 metalog = Logger("metadata") 26 27 windowlog = Logger("window") … … 45 46 from xpra.scripts.main import sound_option 46 47 from xpra.codecs.loader import PREFERED_ENCODING_ORDER, PROBLEMATIC_ENCODINGS, load_codecs, codec_versions, has_codec, get_codec 47 48 from xpra.codecs.video_helper import getVideoHelper, ALL_VIDEO_ENCODER_OPTIONS, ALL_CSC_MODULE_OPTIONS 48 from xpra.net.file_transfer import FileTransfer Handler49 from xpra.net.file_transfer import FileTransferAttributes 49 50 if sys.version > '3': 50 51 unicode = str #@ReservedAssignment 51 52 … … 76 77 return d 77 78 78 79 79 class ServerBase(ServerCore , FileTransferHandler):80 class ServerBase(ServerCore): 80 81 """ 81 82 This is the base class for servers. 82 83 It provides all the generic functions but is not tied … … 86 87 87 88 def __init__(self): 88 89 ServerCore.__init__(self) 89 FileTransferHandler.__init__(self)90 90 log("ServerBase.__init__()") 91 91 self.init_uuid() 92 92 … … 132 132 self.dbus_server = None 133 133 self.lpadmin = "" 134 134 self.lpinfo = "" 135 self.file_transfer = FileTransferAttributes() 135 136 #starting child commands: 136 137 self.child_display = None 137 138 self.start_commands = [] … … 242 243 self.env = parse_env(opts.env) 243 244 self.send_pings = opts.pings 244 245 #printing and file transfer: 245 FileTransferHandler.init(self,opts)246 self.file_transfer.init_opts(opts) 246 247 self.lpadmin = opts.lpadmin 247 248 self.lpinfo = opts.lpinfo 248 249 self.av_sync = opts.av_sync … … 1054 1055 self.get_transient_for, self.get_focus, self.get_cursor_data, 1055 1056 get_window_id, 1056 1057 self.window_filters, 1057 self.printing, 1058 self.printing, self.file_transfer, 1058 1059 self.supports_mmap, self.av_sync, 1059 1060 self.core_encodings, self.encodings, self.default_encoding, self.scaling_control, 1060 1061 self.sound_properties, … … 1066 1067 log("process_hello serversource=%s", ss) 1067 1068 try: 1068 1069 ss.parse_hello(c, self.min_mmap_size) 1069 proto.max_packet_size = max(proto.max_packet_size, int(ss.file_transfer) * (1024 + ss.file_size_limit*1024*1024))1070 1070 except: 1071 1071 #close it already 1072 1072 ss.close() … … 1076 1076 send_ui = ui_client and not is_request 1077 1077 self.idle_add(self.parse_hello_ui, ss, c, auth_caps, send_ui, share_count) 1078 1078 1079 def accept_client(self, proto, c):1080 ServerCore.accept_client(self, proto, c)1081 #may need to bump file size limit for file transfers:1082 proto.max_packet_size = max(proto.max_packet_size, int(self.file_transfer) * (1024 + self.file_size_limit*1024*1024))1083 1079 1084 1085 1080 def get_server_source_class(self): 1086 1081 from xpra.server.source import ServerSource 1087 1082 return ServerSource … … 1295 1290 "webcam.encodings" : self.webcam_encodings, 1296 1291 "virtual-video-devices" : self.virtual_video_devices, 1297 1292 }) 1298 capabilities.update(self. get_file_transfer_features())1293 capabilities.update(self.file_transfer.get_file_transfer_features()) 1299 1294 capabilities.update(flatten_dict(self.get_server_features())) 1300 1295 #this is a feature, but we would need the hello request 1301 1296 #to know if it is really needed.. so always include it: … … 1435 1430 return sources 1436 1431 1437 1432 def control_command_send_file(self, filename, openit, client_uuids, maxbitrate=0): 1438 actual_filename = os.path.abspath(os.path.expanduser(filename))1439 if not os.path.exists(actual_filename):1440 raise ControlError("file '%s' does not exist" % filename)1441 1433 openit = str(openit).lower() in ("open", "true", "1") 1442 #find the client uuid specified: 1434 return self.do_control_file_command("send file", client_uuids, filename, "file_tranfer", (False, openit)) 1435 1436 def control_command_print(self, filename, printer, client_uuids, maxbitrate=0, title="", *options_strs): 1437 #parse options into a dict: 1438 options = {} 1439 for arg in options_strs: 1440 argp = arg.split("=", 1) 1441 if len(argp)==2 and len(argp[0])>0: 1442 options[argp[0]] = argp[1] 1443 return self.do_control_file_command("print", client_uuids, filename, "printing", (True, True, options)) 1444 1445 def do_control_file_command(self, command_type, client_uuids, filename, source_flag_name, send_file_args): 1446 #find the clients: 1443 1447 sources = self._control_get_sources(client_uuids) 1444 1448 if not sources: 1445 1449 raise ControlError("no clients found matching: %s" % client_uuids) 1446 data = load_binary_file(actual_filename) 1447 file_size_MB = len(data)//1024//1024 1448 if file_size_MB>self.file_size_limit: 1449 raise ControlError("file '%s' is too large: %iMB (limit is %iMB)" % (filename, file_size_MB, self.file_size_limit)) 1450 for ss in sources: 1451 if ss.file_transfer: 1452 ss.send_file(filename, "", data, False, openit) 1453 else: 1454 log.warn("cannot send file, client %s does not support file transfers!", ss) 1455 return "file transfer of '%s' to %s initiated" % (filename, client_uuids) 1456 1457 def control_command_print(self, filename, printer, client_uuids, maxbitrate=0, title="", *options_strs): 1450 #find the file and load it: 1458 1451 actual_filename = os.path.abspath(os.path.expanduser(filename)) 1459 1452 try: 1460 1453 stat = os.stat(actual_filename) 1461 printlog("os.stat(%s)=%s", actual_filename, stat)1454 filelog("os.stat(%s)=%s", actual_filename, stat) 1462 1455 except os.error: 1463 printlog("os.stat(%s)", actual_filename, exc_info=True)1456 filelog("os.stat(%s)", actual_filename, exc_info=True) 1464 1457 if not os.path.exists(actual_filename): 1465 1458 raise ControlError("file '%s' does not exist" % filename) 1466 sources = self._control_get_sources(client_uuids)1467 if not sources:1468 raise ControlError("no clients found matching: %s" % client_uuids)1469 #parse options into a dict:1470 options = {}1471 for arg in options_strs:1472 argp = arg.split("=", 1)1473 if len(argp)==2 and len(argp[0])>0:1474 options[argp[0]] = argp[1]1475 1459 data = load_binary_file(actual_filename) 1460 #verify size: 1476 1461 file_size_MB = len(data)//1024//1024 1477 1462 if file_size_MB>self.file_size_limit: 1478 1463 raise ControlError("file '%s' is too large: %iMB (limit is %iMB)" % (filename, file_size_MB, self.file_size_limit)) 1464 return sources, data 1465 #send it to each client: 1479 1466 for ss in sources: 1480 if ss.printing: 1481 ss.send_file(filename, "", data, True, True, options) 1467 if not getattr(ss, source_flag_name): #ie: ServerSource.file_transfer 1468 log.warn("Warning: cannot %s '%s'", command_type, filename) 1469 log.warn(" client %s does not support this feature", ss) 1470 elif file_size_MB>ss.file_size_limit: 1471 log.warn("Warning: cannot %s '%s'", command_type, filename) 1472 log.warn(" client %s file size limit is %iMB (file is %iMB)", ss, ss.file_size_limit, file_size_MB) 1482 1473 else: 1483 printlog.warn("client %s does not support printing!", ss)1484 return " printing to %s initiated" % client_uuids1474 ss.send_file(filename, "", data, *send_file_args) 1475 return "%s of '%s' to %s initiated" % (command_type, client_uuids) 1485 1476 1477 1486 1478 def control_command_compression(self, compression): 1487 1479 c = compression.lower() 1488 1480 from xpra.net import compression … … 1707 1699 1708 1700 1709 1701 def _process_send_file(self, proto, packet): 1710 #superclass does not take the protocol as argument: 1711 FileTransferHandler._process_send_file(self, packet) 1702 ss = self._server_sources.get(proto) 1703 if not ss: 1704 log.warn("Warning: invalid client source for file packet") 1705 return 1706 ss._process_send_file(packet) 1712 1707 1713 1708 def _process_print(self, proto, packet): 1714 1709 #ie: from the xpraforwarder we call this command: … … 1879 1874 "rpc-types" : self.rpc_handlers.keys(), 1880 1875 "clipboard" : self.supports_clipboard, 1881 1876 "idle_timeout" : self.idle_timeout, 1882 "file-size-limit" : self.file_size_limit,1883 1877 } 1884 1878 i.update(self.get_server_features()) 1885 1879 return i … … 1927 1921 def up(prefix, d): 1928 1922 info[prefix] = d 1929 1923 1924 up("file", self.file_transfer.get_info()) 1930 1925 up("webcam", self.get_webcam_info()) 1931 up("file", self.get_file_transfer_info())1932 1926 up("printing", self.get_printing_info()) 1933 1927 up("commands", self.get_commands_info()) 1934 1928 up("features", self.get_features_info()) -
xpra/server/source.py
38 38 from xpra.codecs.codec_constants import video_spec 39 39 from xpra.net import compression 40 40 from xpra.net.compression import compressed_wrapper, Compressed, Uncompressed 41 from xpra.net.file_transfer import FileTransferHandler 41 42 from xpra.make_thread import make_thread 42 43 from xpra.os_util import platform_name, Queue, get_machine_id, get_user_uuid, BytesIOClass 43 44 from xpra.server.background_worker import add_work_item … … 200 201 return not(WindowPropertyIn.evaluate(window_value)) 201 202 202 203 203 class ServerSource( object):204 class ServerSource(FileTransferHandler): 204 205 """ 205 206 A ServerSource represents a client connection. 206 207 It mediates between the server class (which only knows about actual window objects and display server events) … … 226 227 get_transient_for, get_focus, get_cursor_data_cb, 227 228 get_window_id, 228 229 window_filters, 229 printing, 230 printing, file_transfer, 230 231 supports_mmap, av_sync, 231 232 core_encodings, encodings, default_encoding, scaling_control, 232 233 sound_properties, … … 241 242 get_transient_for, get_focus, 242 243 get_window_id, 243 244 window_filters, 244 printing, 245 printing, file_transfer, 245 246 supports_mmap, av_sync, 246 247 core_encodings, encodings, default_encoding, scaling_control, 247 248 sound_properties, … … 250 251 speaker_codecs, microphone_codecs, 251 252 default_quality, default_min_quality, 252 253 default_speed, default_min_speed)) 254 FileTransferHandler.__init__(self, file_transfer) 253 255 global counter 254 256 self.counter = counter.increase() 255 257 self.close_event = Event() … … 416 418 self.metadata_supported = [] 417 419 self.show_desktop_allowed = False 418 420 self.supports_transparency = False 419 self.file_transfer = False420 self.file_size_limit = 10421 421 self.printers = {} 422 422 self.vrefresh = -1 423 423 self.double_click_time = -1 … … 680 680 self.client_revision = c.strget("build.revision") 681 681 self.client_proxy = c.boolget("proxy") 682 682 self.client_wm_name = c.strget("wm_name") 683 #file transfers and printing: 684 self.parse_file_transfer_caps(c) 683 685 #general features: 684 686 self.zlib = c.boolget("zlib", True) 685 687 self.lz4 = c.boolget("lz4", False) and compression.use_lz4 … … 698 700 self.clipboard_notifications = c.boolget("clipboard.notifications") 699 701 self.clipboard_set_enabled = c.boolget("clipboard.set_enabled") 700 702 self.share = c.boolget("share") 701 self.file_transfer = c.boolget("file-transfer")702 self.file_size_limit = c.intget("file-size-limit")703 self.printing = self.printing and c.boolget("printing")704 703 self.window_initiate_moveresize = c.boolget("window.initiate-moveresize") 705 704 self.system_tray = c.boolget("system_tray") 706 705 self.control_commands = c.strlistget("control_commands") … … 794 793 self.add_window_filter(object_name, property_name, operator, value) 795 794 except Exception as e: 796 795 log.error("Error parsing window-filters: %s", e) 796 #adjust max packet size if file transfers are enabled: 797 if self.file_transfer: 798 self.protocol.max_packet_size = max(self.protocol.max_packet_size, self.file_size_limit*1024*1024) 797 799 798 800 799 801 def parse_encoding_caps(self, c, min_mmap_size): … … 1464 1466 finfo[i] = str(f) 1465 1467 i += 1 1466 1468 info["window-filter"] = finfo 1467 info.update(self.get_sound_info()) 1469 info["file-transfers"] = FileTransferHandler.get_info(self) 1470 info["sound"] = self.get_sound_info() 1468 1471 info.update(self.get_features_info()) 1469 1472 info.update(self.get_screen_info()) 1470 1473 return info -
xpra/platform/darwin/osx_menu.py
223 223 def add_ah(*args): 224 224 if self.client.start_new_commands: 225 225 actions_menu.add(self.make_startnewcommandmenuitem()) 226 if self.client. server_file_transfer:226 if self.client.remote_file_transfer: 227 227 actions_menu.add(self.make_uploadmenuitem()) 228 228 self.client.after_handshake(add_ah) 229 229 menus.append(("Actions", actions_menu))