xpra icon
Bug tracker and wiki

Ticket #2072: clipboard-size-v2.patch

File clipboard-size-v2.patch, 6.5 KB (added by Calvin Ko, 18 months ago)

patch with control command to set the size limits

  • xpra/clipboard/clipboard_base.py

     
    2828
    2929MIN_CLIPBOARD_COMPRESSION_SIZE = 512
    3030MAX_CLIPBOARD_PACKET_SIZE = 4*1024*1024
     31MAX_CLIPBOARD_RECEIVE_SIZE = envint("XPRA_MAX_CLIPBOARD_RECEIVE_SIZE", -1)
     32MAX_CLIPBOARD_SEND_SIZE = envint("XPRA_MAX_CLIPBOARD_SEND_SIZE", -1)
    3133
    3234from xpra.platform.features import CLIPBOARDS as PLATFORM_CLIPBOARDS
    3335ALL_CLIPBOARDS = [strtobytes(x) for x in PLATFORM_CLIPBOARDS]
     
    106108        self.progress_cb = progress_cb
    107109        self.can_send = d.boolget("can-send", True)
    108110        self.can_receive = d.boolget("can-receive", True)
    109         self.max_clipboard_packet_size = MAX_CLIPBOARD_PACKET_SIZE
     111        self.max_clipboard_packet_size = d.intget("max-packet-size", MAX_CLIPBOARD_PACKET_SIZE)
     112        self.max_clipboard_receive_size = d.intget("max-receive-size", MAX_CLIPBOARD_RECEIVE_SIZE)
     113        self.max_clipboard_send_size = d.intget("max-send-size", MAX_CLIPBOARD_SEND_SIZE)
    110114        self.disabled_by_loop = []
    111115        self.filter_res = []
    112116        filter_res = d.strlistget("filters")
     
    131135
    132136    def get_info(self):
    133137        info = {
    134                 "type"      : str(self).replace("ClipboardProtocolHelper", ""),
    135                 "max_size"  : self.max_clipboard_packet_size,
     138                "type"      :       str(self).replace("ClipboardProtocolHelper", ""),
     139                "max_size"  :       self.max_clipboard_packet_size,
     140                "max_recv_size":    self.max_clipboard_receive_size,
     141                "max_send_size":    self.max_clipboard_send_size,
    136142                "filters"   : [x.pattern for x in self.filter_res],
    137143                "requests"  : self._clipboard_request_counter,
    138144                "pending"   : tuple(self._clipboard_outstanding_requests.keys()),
     
    199205                        if selection not in self.disabled_by_loop:
    200206                            self.disabled_by_loop.append(selection)
    201207
    202     def set_direction(self, can_send, can_receive):
     208    def set_direction(self, can_send, can_receive, max_send_size=-1, max_receive_size=-1):
    203209        self.can_send = can_send
    204210        self.can_receive = can_receive
    205211        for proxy in self._clipboard_proxies.values():
    206212            proxy.set_direction(can_send, can_receive)
    207213
     214    def set_limits(self, max_send_size, max_receive_size):
     215        if max_send_size >= 0:
     216            self.max_clipboard_send_size = max_send_size
     217        if max_receive_size >= 0:
     218            self.max_clipboard_receive_size = max_receive_size
     219
    208220    def enable_selections(self, selections):
    209221        #when clients first connect or later through the "clipboard-enable-selections" packet,
    210222        #they can tell us which clipboard selections they want enabled
     
    435447
    436448    def _munge_wire_selection_to_raw(self, encoding, dtype, dformat, data):
    437449        log("wire selection to raw, encoding=%s, type=%s, format=%s, len(data)=%s", encoding, dtype, dformat, len(data or ""))
     450        max_recv_datalen = self.max_clipboard_receive_size * 8 // max(8, dformat)
     451        if len(data) > max_recv_datalen:
     452            olen = len(data)
     453            data = data[:max_recv_datalen]
     454            log.info("Data copied out truncated because of clipboard policy %d to %d", olen, max_recv_datalen)
    438455        if encoding == b"bytes":
    439456            return data
    440457        elif encoding == b"integers":
     
    490507            if dtype is None or data is None or (dformat==0 and data==b""):
    491508                no_contents()
    492509                return
     510            log("perform security checking - datasize - %d, %d", len(data), self.max_clipboard_send_size)
     511            max_send_datalen = self.max_clipboard_send_size * 8 // max(8, dformat)
     512            if len(data) > max_send_datalen:
     513                truncated = len(data) - max_send_datalen
     514                data = data[:max_send_datalen]
     515            else:
     516                truncated = 0
    493517            munged = self._munge_raw_selection_to_wire(target, dtype, dformat, data)
    494518            wire_encoding, wire_data = munged
    495519            log("clipboard raw -> wire: %r -> %r", (dtype, dformat, data), munged)
     
    499523            wire_data = self._may_compress(dtype, dformat, wire_data)
    500524            if wire_data is not None:
    501525                self.send("clipboard-contents", request_id, selection,
    502                        dtype, dformat, wire_encoding, wire_data)
     526                       dtype, dformat, wire_encoding, wire_data, truncated)
    503527        proxy.get_contents(target, got_contents)
    504528
    505529    def _may_compress(self, dtype, dformat, wire_data):
  • xpra/server/mixins/server_base_controlcommands.py

     
    7575            ArgsControlCommand("compression",           "sets the packet compressor",       min_args=1, max_args=1),
    7676            ArgsControlCommand("encoder",               "sets the packet encoder",          min_args=1, max_args=1),
    7777            ArgsControlCommand("clipboard-direction",   "restrict clipboard transfers",     min_args=1, max_args=1),
     78            ArgsControlCommand("clipboard-limits",      "restrict clipboard transfers size", min_args=2, max_args=2),
    7879            ArgsControlCommand("set-lock",              "modify the lock attribute",        min_args=1, max_args=1),
    7980            ArgsControlCommand("set-sharing",           "modify the sharing attribute",     min_args=1, max_args=1),
    8081            ArgsControlCommand("set-ui-driver",         "set the client connection driving the session", min_args=1, max_args=1),
     
    453454        self.setting_changed("clipboard_direction", direction)
    454455        return msg
    455456
     457    def control_command_clipboard_limits(self, max_send, max_recv, *_args):
     458        ch = self._clipboard_helper
     459        assert self.clipboard and ch
     460        self._clipboard_helper.set_limits(max_send, max_recv)
     461        msg = "clipboard send limit set to %d, recv limit set to %d (single copy/paste)" % (max_send, max_recv)
     462        log(msg)
     463        self.setting_changed("clipboard_limits", "max-send=%d,max-recv=%d" % (max_send, max_recv))
     464        return msg
     465
    456466    def _control_video_subregions_from_wid(self, wid):
    457467        if wid not in self._id_to_window:
    458468            raise ControlError("invalid window %i" % wid)