示例#1
0
 def send_data_request(self,
                       action,
                       dtype,
                       url,
                       mimetype="",
                       data="",
                       filesize=0,
                       printit=False,
                       openit=True,
                       options=None):
     send_id = uuid.uuid4().hex
     if len(self.pending_send_data) >= MAX_CONCURRENT_FILES:
         filelog.warn("Warning: %s dropped", action)
         filelog.warn(" %i transfer%s already waiting for a response",
                      len(self.pending_send_data),
                      engs(self.pending_send_data))
         return None
     self.pending_send_data[send_id] = (dtype, url, mimetype, data,
                                        filesize, printit, openit, options
                                        or {})
     delay = self.remote_file_ask_timeout * 1000
     self.pending_send_data_timers[send_id] = self.timeout_add(
         delay, self.send_data_ask_timeout, send_id)
     filelog("sending data request for %s '%s' with send-id=%s", u(dtype),
             u(url), send_id)
     self.send("send-data-request", dtype, send_id, url, mimetype, filesize,
               printit, openit, options or {})
     return send_id
示例#2
0
 def do_send_file(self,
                  filename,
                  mimetype,
                  data,
                  filesize=0,
                  printit=False,
                  openit=False,
                  options=None,
                  send_id=""):
     if printit:
         action = "print"
         l = printlog
     else:
         action = "upload"
         l = filelog
     l("do_send_file%s", (u(filename), mimetype, type(data),
                          "%i bytes" % filesize, printit, openit, options))
     if not self.check_file_size(action, filename, filesize):
         return False
     h = hashlib.sha256()
     h.update(data)
     absfile = os.path.abspath(filename)
     filelog("sha256 digest('%s')=%s", u(absfile), h.hexdigest())
     options = options or {}
     options["sha256"] = h.hexdigest()
     chunk_size = min(self.file_chunks, self.remote_file_chunks)
     if 0 < chunk_size < filesize:
         if len(self.send_chunks_in_progress) >= MAX_CONCURRENT_FILES:
             raise Exception("too many file transfers in progress: %i" %
                             len(self.send_chunks_in_progress))
         #chunking is supported and the file is big enough
         chunk_id = uuid.uuid4().hex
         options["file-chunk-id"] = chunk_id
         #timer to check that the other end is requesting more chunks:
         timer = self.timeout_add(CHUNK_TIMEOUT, self._check_chunk_sending,
                                  chunk_id, 0)
         chunk_state = [monotonic(), data, chunk_size, timer, 0]
         self.send_chunks_in_progress[chunk_id] = chunk_state
         cdata = ""
         filelog(
             "using chunks, sending initial file-chunk-id=%s, for chunk size=%s",
             chunk_id, chunk_size)
     else:
         #send everything now:
         cdata = self.compressed_wrapper("file-data", data)
         assert len(
             cdata) <= filesize  #compressed wrapper ensures this is true
         filelog("sending full file: %i bytes (chunk size=%i)", filesize,
                 chunk_size)
     basefilename = os.path.basename(filename)
     self.send("send-file", basefilename, mimetype, printit, openit,
               filesize, cdata, options, send_id)
     return True
示例#3
0
def client_upgrade(read, write, host, port, path=""):
    request = "GET /%s HTTP/1.1" % path
    log("client_upgrade: http request: %s", request)
    lines = [request.encode("latin1")]
    key = b64encode(uuid.uuid4().bytes)
    headers = get_headers(host, port)
    headers[b"Sec-WebSocket-Key"] = key
    for k, v in headers.items():
        lines.append(b"%s: %s" % (k, v))
    lines.append(b"")
    lines.append(b"")
    http_request = b"\r\n".join(lines)
    log("client_upgrade: sending http headers: %s", headers)
    now = monotonic()
    while http_request and monotonic() - now < MAX_WRITE_TIME:
        w = write(http_request)
        http_request = http_request[w:]

    now = monotonic()
    response = b""
    while ("sec-websocket-protocol"
           not in u(response).lower()) and monotonic() - now < MAX_READ_TIME:
        response += read(READ_CHUNK_SIZE)
    headers = parse_response_header(response)
    verify_response_headers(headers, key)
    log("client_upgrade: done")
示例#4
0
def get_wm_name():
    wm_name = os.environ.get("XDG_CURRENT_DESKTOP", "") or os.environ.get(
        "XDG_SESSION_DESKTOP") or os.environ.get("DESKTOP_SESSION")
    if os.environ.get("XDG_SESSION_TYPE") == "wayland" or os.environ.get(
            "GDK_BACKEND") == "wayland":
        if wm_name:
            wm_name += " on wayland"
        else:
            wm_name = "wayland"
    elif is_X11():
        try:
            wm_check = _get_X11_root_property("_NET_SUPPORTING_WM_CHECK",
                                              "WINDOW")
            if wm_check:
                xid = struct.unpack(b"@L", wm_check)[0]
                traylog("_NET_SUPPORTING_WM_CHECK window=%#x", xid)
                wm_name = _get_X11_window_property(xid, "_NET_WM_NAME",
                                                   "UTF8_STRING")
                traylog("_NET_WM_NAME=%s", wm_name)
                if wm_name:
                    return u(wm_name)
        except Exception as e:
            traylog("get_wm_name()", exc_info=True)
            traylog.error("Error accessing window manager information:")
            traylog.error(" %s", e)
    return wm_name
示例#5
0
 def cancel_download(self, send_id, message="Cancelled"):
     filelog("cancel_download(%s, %s)", send_id, message)
     for chunk_id, chunk_state in dict(self.receive_chunks_in_progress).items():
         if chunk_state[-3]==send_id:
             self.cancel_file(chunk_id, message)
             return
     filelog.error("Error: cannot cancel download %s, entry not found!", u(send_id))
示例#6
0
 def _process_request_file(self, proto, packet):
     ss = self.get_server_source(proto)
     if not ss:
         printlog.warn("Warning: invalid client source for send-data-response packet")
         return
     argf = u(packet[1])
     openit = packet[2]
     filename = os.path.abspath(osexpand(argf))
     if not os.path.exists(filename):
         filelog.warn("Warning: the file requested does not exist:")
         filelog.warn(" %s", filename)
         ss.may_notify(XPRA_FILETRANSFER_NOTIFICATION_ID,
                       "File not found", "The file requested does not exist:\n%s" % filename,
                        icon_name="file")
         return
     try:
         stat = os.stat(filename)
         filelog("os.stat(%s)=%s", filename, stat)
     except os.error:
         filelog("os.stat(%s)", filename, exc_info=True)
     else:
         file_size = stat.st_size
         if file_size>self.file_transfer.file_size_limit or file_size>ss.file_size_limit:
             ss.may_notify(XPRA_FILETRANSFER_NOTIFICATION_ID,
                           "File too large",
                           "The file requested is too large to send:\n%s\nis %s" % (argf, std_unit(file_size)),
                            icon_name="file")
             return
     data = load_binary_file(filename)
     ss.send_file(filename, "", data, len(data), openit=openit, options={"request-file" : (argf, openit)})
示例#7
0
 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
示例#8
0
 def action_button(self, action_id, action_text):
     button = Gtk.Button(u(action_text))
     button.set_relief(Gtk.ReliefStyle.NORMAL)
     def popup_cb_clicked(*args):
         self.hide_notification()
         log("popup_cb_clicked%s for action_id=%s, action_text=%s", args, action_id, action_text)
         self.action_cb(self.nid, action_id)
     button.connect("clicked", popup_cb_clicked)
     return button
示例#9
0
 def _process_start_command(self, proto, packet):
     log("start new command: %s", packet)
     if not self.start_new_commands:
         log.warn("Warning: received start-command request,")
         log.warn(" but the feature is currently disabled")
         return
     name, command, ignore = packet[1:4]
     if isinstance(command, (list, tuple)):
         cmd = command
     else:
         cmd = u(command)
     proc = self.start_command(u(name), cmd, ignore)
     if len(packet)>=5:
         shared = packet[4]
         if proc and not shared:
             ss = self.get_server_source(proto)
             assert ss
             log("adding filter: pid=%s for %s", proc.pid, proto)
             ss.add_window_filter("window", "pid", "=", proc.pid)
     log("process_start_command: proc=%s", proc)
示例#10
0
    def get_window_info(self, wi):
        #version info:
        geom = wi.inttupleget("geometry")
        g_str = "%ix%i at %i,%i" % (geom[2], geom[3], geom[0], geom[1])
        sc = wi.dictget("size-constraints")
        if sc:

            def sc_str(k, v):
                k = bytestostr(k)
                if k == "gravity":
                    v = GRAVITY_STR.get(v, v)
                return "%s=%s" % (k, str(v))

            g_str += " - %s" % csv(sc_str(k, v) for k, v in sc.items())
        line1 = ""
        pid = wi.intget("pid", 0)
        if pid:
            line1 = "pid %i: " % pid
        title = wi.get("title", "")
        if not isinstance(title, str):
            title = u(strtobytes(title))
        if title:
            line1 += ' "%s"' % title
        attrs = [
            x for x in (
                "above",
                "below",
                "bypass-compositor",
                "focused",
                "fullscreen",
                "grabbed",
                "iconic",
                "maximized",
                "modal",
                "override-redirect",
                "shaded",
                "skip-pager",
                "skip-taskbar",
                "sticky",
                "tray",
            ) if wi.boolget(x)
        ]
        if not wi.boolget("shown"):
            attrs.insert(0, "hidden")
        wtype = wi.strtupleget("window-type", ("NORMAL", ))
        tinfo = " - ".join(csv(x) for x in (wtype, attrs) if x)
        info = []
        if line1:
            info.append(line1)
        info += [g_str, tinfo]
        return tuple((x, WHITE) for x in info if x)
示例#11
0
    def do_process_send_data_request(self, dtype, send_id, url, _, filesize,
                                     printit, openit, options):
        filelog(
            "do_process_send_data_request: send_id=%s, url=%s, printit=%s, openit=%s, options=%s",
            u(send_id), url, printit, openit, options)

        def cb_answer(accept):
            filelog("accept%s=%s", (url, printit, openit), accept)
            self.send("send-data-response", send_id, accept)

        #could be a request we made:
        #(in which case we can just accept it without prompt)
        rf = options.tupleget("request-file")
        if rf and len(rf) >= 2:
            argf, openit = rf[:2]
            openit = self.files_requested.pop(bytestostr(argf), None)
            if openit is not None:
                self.files_accepted[send_id] = openit
                cb_answer(True)
                return
        if dtype == "file":
            if not self.file_transfer:
                cb_answer(False)
                return
            url = os.path.basename(url)
            if printit:
                ask = self.printing_ask
            elif openit:
                ask = self.file_transfer_ask or self.open_files_ask
            else:
                ask = self.file_transfer_ask
        elif dtype == "url":
            if not self.open_url:
                cb_answer(False)
                return
            ask = self.open_url_ask
        else:
            filelog.warn("Warning: unknown data request type '%s'", dtype)
            cb_answer(False)
            return
        if not ask:
            filelog.warn("Warning: received a send-data request for a %s,",
                         dtype)
            filelog.warn(" but authorization is not required by the client")
            #fail it because if we responded with True,
            #it would fail later when we don't find this send_id in our accepted list
            cb_answer(False)
        else:
            self.ask_data_request(cb_answer, send_id, dtype, url, filesize,
                                  printit, openit)
示例#12
0
def get_x11_wm_name():
    if not is_X11():
        return None
    try:
        wm_check = _get_X11_root_property("_NET_SUPPORTING_WM_CHECK", "WINDOW")
        if wm_check:
            xid = struct.unpack(b"@L", wm_check)[0]
            traylog("_NET_SUPPORTING_WM_CHECK window=%#x", xid)
            wm_name = _get_X11_window_property(xid, "_NET_WM_NAME",
                                               "UTF8_STRING")
            traylog("_NET_WM_NAME=%s", wm_name)
            if wm_name:
                return u(wm_name)
    except Exception as e:
        screenlog("get_x11_wm_name()", exc_info=True)
        screenlog.error("Error accessing window manager information:")
        screenlog.error(" %s", e)
    return None
示例#13
0
    def _process_print(self, _proto, packet):
        #ie: from the xpraforwarder we call this command:
        #command = ["xpra", "print", "socket:/path/tosocket",
        #           filename, mimetype, source, title, printer, no_copies, print_options]
        assert self.file_transfer.printing
        #printlog("_process_print(%s, %s)", proto, packet)
        if len(packet)<3:
            printlog.error("Error: invalid print packet, only %i arguments", len(packet))
            printlog.error(" %s", [repr_ellipsized(x) for x in packet])
            return
        filename = u(packet[1])
        file_data = packet[2]
        mimetype, source_uuid, title, printer, no_copies, print_options = "", "*", "unnamed document", "", 1, ""
        if len(packet)>=4:
            mimetype = bytestostr(packet[3])
        if len(packet)>=5:
            source_uuid = bytestostr(packet[4])
        if len(packet)>=6:
            title = u(packet[5])
        if len(packet)>=7:
            printer = bytestostr(packet[6])
        if len(packet)>=8:
            no_copies = int(packet[7])
        if len(packet)>=9:
            print_options = packet[8]
        #parse and validate:
        if len(mimetype)>=128:
            printlog.error("Error: invalid mimetype in print packet:")
            printlog.error(" %s", repr_ellipsized(mimetype))
            return
        if not isinstance(print_options, dict):
            s = bytestostr(print_options)
            print_options = {}
            for x in s.split(" "):
                parts = x.split("=", 1)
                if len(parts)==2:
                    print_options[parts[0]] = parts[1]
        printlog("process_print: %s", (filename, mimetype, "%s bytes" % len(file_data),
                                       source_uuid, title, printer, no_copies, print_options))
        printlog("process_print: got %s bytes for file %s", len(file_data), filename)
        #parse the print options:
        hu = hashlib.sha256()
        hu.update(file_data)
        printlog("sha1 digest: %s", hu.hexdigest())
        options = {
            "printer"    : printer,
            "title"      : title,
            "copies"     : no_copies,
            "options"    : print_options,
            "sha256"     : hu.hexdigest(),
            }
        printlog("parsed printer options: %s", options)
        if SAVE_PRINT_JOBS:
            self._save_print_job(filename, file_data)

        sent = 0
        sources = tuple(self._server_sources.values())
        printlog("will try to send to %i clients: %s", len(sources), sources)
        for ss in sources:
            if source_uuid not in ("*", ss.uuid):
                printlog("not sending to %s (uuid=%s, wanted uuid=%s)", ss, ss.uuid, source_uuid)
                continue
            if not ss.printing:
                if source_uuid!='*':
                    printlog.warn("Warning: printing is not enabled for:")
                    printlog.warn(" %s", ss)
                else:
                    printlog("printing is not enabled for %s", ss)
                continue
            if not ss.printers:
                printlog.warn("Warning: client %s does not have any printers", ss.uuid)
                continue
            if printer not in ss.printers:
                printlog.warn("Warning: client %s does not have a '%s' printer", ss.uuid, printer)
                continue
            printlog("'%s' sent to %s for printing on '%s'", bytestostr(title or filename), ss, printer)
            if ss.send_file(filename, mimetype, file_data, len(file_data), True, True, options):
                sent += 1
        #warn if not sent:
        if sent==0:
            l = printlog.warn
        else:
            l = printlog.info
        unit_str, v = to_std_unit(len(file_data), unit=1024)
        l("'%s' (%i%sB) sent to %i client%s for printing", title or filename, v, unit_str, sent, engs(sent))