| Server IP : 107.13.46.68 / Your IP : 216.73.216.232 Web Server : Apache/2.4.58 (Ubuntu) System : Linux mariOS 6.8.0-51-generic #52-Ubuntu SMP PREEMPT_DYNAMIC Thu Dec 5 13:09:44 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /proc/thread-self/root/bin/ |
Upload File : |
#!/usr/bin/python3
import signal
import argparse
import gettext
import setproctitle
import json
import os
from pathlib import Path
import sys
import locale
import functools
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gio, Gtk, Gdk, GdkX11
src = "/usr/libexec/warpinator"
sys.path.insert(0, src)
import config
import dbus_service
import util
signal.signal(signal.SIGINT, signal.SIG_DFL)
# i18n
locale.bindtextdomain(config.PACKAGE, config.localedir)
gettext.bindtextdomain(config.PACKAGE, config.localedir)
gettext.textdomain(config.PACKAGE)
_ = gettext.gettext
setproctitle.setproctitle("warpinator-send")
class WarpinatorSender:
def __init__(self):
self.proxy = None
self.ecode = 0
parser = argparse.ArgumentParser(description='warpinator-send')
parser.add_argument("--list-remotes", dest="list_remotes", action='store_true',
help="List online remotes as JSON (any other arguments are ignored)")
parser.add_argument('--remote-ident', dest="ident", action='store', default="",
help="Destination remote's UUID/identity, as retrieved by --list-remotes. If omitted, you will be prompted for a destination.")
parser.add_argument("--xid", dest="parent_window", action='store',
help="Window ID of the calling application (optional)")
parser.add_argument("uris", type=str, nargs="*", metavar="URIs/paths",
help="List of file URIs and/or paths to be sent (required unless '--list-remotes' is called).")
args = parser.parse_args()
if not args.list_remotes and len(args.uris) == 0:
print("Must have at least 1 uri if --get-live-remotes is not set", file=sys.stderr)
parser.print_help()
self.quit(1)
self.ident = args.ident
self.files = self.parse_uris(args.uris)
self.list_remotes = args.list_remotes
if args.parent_window:
self.parent_window = int(args.parent_window, 0) # maybe hex, detect the base
else:
self.parent_window = None
self.popup = None
Gio.DBusProxy.new_for_bus(
Gio.BusType.SESSION,
Gio.DBusProxyFlags.DO_NOT_AUTO_START,
dbus_service.interface_node_info.interfaces[0],
"org.x.Warpinator",
"/org/x/Warpinator",
"org.x.Warpinator",
None,
self._on_proxy_ready
)
def parse_uris(self, uris):
files = []
for uri in uris:
file = Gio.File.new_for_uri(uri)
if file.get_uri_scheme() is None:
p = Path(uri).expanduser()
if not uri.startswith("/"):
p = Path.cwd() / p
file = Gio.File.new_for_path(str(p))
if not file.query_exists():
print("File does not exist: %s" % file.get_uri(), file=sys.stderr)
self.quit(1)
files.append(file)
return files
def _on_proxy_ready(self, object, result, data=None):
try:
self.proxy = Gio.DBusProxy.new_for_bus_finish(result);
if self.proxy.get_name_owner() is None:
print("Can connect to Warpinator - is it running?")
self.quit(1)
except GLib.Error as e:
print("Can't create warpinator proxy (%d): %s" % (e.code, e.message), file=sys.stderr)
self.quit(1)
self.handle_command()
def handle_command(self):
if self.list_remotes:
self.proxy.call(
"ListRemotes",
None,
Gio.DBusCallFlags.NO_AUTO_START,
-1,
None,
self.list_remotes_command_finished
)
elif self.ident != "":
self.send_files_to(self.ident)
else:
self.proxy.call(
"ListRemotes",
None,
Gio.DBusCallFlags.NO_AUTO_START,
-1,
None,
self.list_remotes_for_send_finished
)
def send_files_command_finished(self, source, res, data=None):
try:
var = source.call_finish(res)
except GLib.Error as e:
print("Could not send files: %s" % str(e), file=sys.stderr)
self.quit(1)
self.quit()
def list_remotes_command_finished(self, source, res, data=None):
try:
var = source.call_finish(res)
remote_list = var[0]
dump = json.dumps(remote_list, indent=2)
print(dump, file=sys.stdout)
except GLib.Error as e:
print("Could not list remotes: %s" % str(e), file=sys.stderr)
self.quit(1)
self.quit()
def list_remotes_for_send_finished(self, source, res, data=None):
try:
var = source.call_finish(res)
remote_list = var[0]
if len(remote_list) == 0:
print("No remotes available to send to", file=sys.stderr)
self.quit(1)
return
except GLib.Error as e:
print("Could not list remotes to ask user: %s" % str(e), file=sys.stderr)
self.quit(1)
return
popup = Gtk.Window(type_hint=Gdk.WindowTypeHint.POPUP_MENU,
destroy_with_parent=True,
resizable=False)
if self.parent_window is None:
popup.set_keep_above(True)
hb = Gtk.HeaderBar(title="Warpinator",
subtitle=_("Choose a recipient..."),
show_close_button=True)
popup.set_titlebar(hb)
seat = Gdk.Display.get_default().get_default_seat()
pointer = seat.get_pointer()
screen, x, y = pointer.get_position()
popup.move(x + 5, y + 5)
remote_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, margin=4)
popup.add(remote_box)
button_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=4, homogeneous=True)
remote_box.pack_start(button_box, True, True, 0)
class RemoteInfo:
def __init__(self, remote):
self.uuid = remote["uuid"]
self.display_name = remote["display-name"]
self.username = remote["username"]
self.hostname = remote["hostname"]
self.favorite = remote["favorite"]
self.recent_time = remote["recent-time"]
infos = []
for remote in remote_list:
infos.append(RemoteInfo(remote))
sorted_remotes = sorted(infos, key=functools.cmp_to_key(util.sort_remote_machines))
for info in sorted_remotes:
label = "<b>%s</b> %s@%s" % (info.display_name, info.username, info.hostname)
button = Gtk.Button(always_show_image=True, image_position=Gtk.PositionType.RIGHT)
if info.favorite:
image = Gtk.Image.new_from_icon_name("starred-symbolic", Gtk.IconSize.BUTTON)
elif info.recent_time > 0:
image = Gtk.Image.new_from_icon_name("document-open-recent-symbolic", Gtk.IconSize.BUTTON)
else:
image = None
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
box.pack_start(Gtk.Label(label=label, use_markup=True), True, True, 6)
if image is not None:
box.pack_end(image, False, False, 6)
box.show_all()
button.set_image(box)
button_box.add(button)
button.connect("clicked", self.remote_selected, info.uuid)
self.popup = popup
self.popup.connect("delete-event", self.on_delete_popup)
self.popup.connect("realize", self.on_popup_realize)
self.popup.show_all()
self.popup.present()
def on_popup_realize(self, window):
if self.parent_window:
parent = GdkX11.X11Window.foreign_new_for_display(Gdk.Display.get_default(), self.parent_window)
if parent is not None:
window.get_window().set_transient_for(parent)
def on_delete_popup(self, window, event, data=None):
self.quit(1)
return Gdk.EVENT_PROPAGATE
def remote_selected(self, button, ident):
self.popup.destroy()
self.send_files_to(ident)
def send_files_to(self, ident):
files_var = GLib.Variant.new_array(None, [GLib.Variant.new_string(file.get_uri()) for file in self.files])
full_var = GLib.Variant("(sas)", [ident, files_var])
self.proxy.call(
"SendFiles",
full_var,
Gio.DBusCallFlags.NO_AUTO_START,
-1,
None,
self.send_files_command_finished
)
def quit(self, code=0):
if Gtk.main_level() == 0:
sys.exit(code)
else:
self.ecode = code
Gtk.main_quit()
if __name__ == "__main__":
sender = WarpinatorSender()
Gtk.main()
sys.exit(sender.ecode)