ftp-client 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #!/usr/bin/python
  2. # SPDX-License-Identifier: LGPL-2.1-or-later
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. from optparse import OptionParser
  5. import os.path
  6. import sys
  7. import dbus
  8. import dbus.service
  9. import dbus.mainloop.glib
  10. try:
  11. from gi.repository import GObject
  12. except ImportError:
  13. import gobject as GObject
  14. BUS_NAME='org.bluez.obex'
  15. PATH = '/org/bluez/obex'
  16. CLIENT_INTERFACE='org.bluez.obex.Client1'
  17. SESSION_INTERFACE='org.bluez.obex.Session1'
  18. FILE_TRASNFER_INTERFACE='org.bluez.obex.FileTransfer1'
  19. TRANSFER_INTERFACE='org.bluez.obex.Transfer1'
  20. def parse_options():
  21. parser.add_option("-d", "--device", dest="device",
  22. help="Device to connect", metavar="DEVICE")
  23. parser.add_option("-c", "--chdir", dest="new_dir",
  24. help="Change current directory to DIR", metavar="DIR")
  25. parser.add_option("-l", "--list", action="store_true", dest="list_dir",
  26. help="List the current directory")
  27. parser.add_option("-g", "--get", dest="get_file",
  28. help="Get FILE", metavar="FILE")
  29. parser.add_option("-p", "--put", dest="put_file",
  30. help="Put FILE", metavar="FILE")
  31. parser.add_option("-y", "--copy", dest="copy_file",
  32. help="Copy FILE", metavar="FILE")
  33. parser.add_option("-m", "--move", dest="move_file",
  34. help="Move FILE", metavar="FILE")
  35. parser.add_option("-n", "--destname", dest="dest_file",
  36. help="Destination FILE", metavar="FILE")
  37. parser.add_option("-r", "--remove", dest="remove_file",
  38. help="Remove FILE", metavar="FILE")
  39. parser.add_option("-v", "--verbose", action="store_true",
  40. dest="verbose")
  41. return parser.parse_args()
  42. class FtpClient:
  43. def __init__(self, session_path, verbose=False):
  44. self.transferred = 0
  45. self.transfer_path = None
  46. self.transfer_size = 0
  47. self.verbose = verbose
  48. bus = dbus.SessionBus()
  49. obj = bus.get_object(BUS_NAME, session_path)
  50. self.session = dbus.Interface(obj, SESSION_INTERFACE)
  51. self.ftp = dbus.Interface(obj, FILE_TRASNFER_INTERFACE)
  52. bus.add_signal_receiver(self.properties_changed,
  53. dbus_interface="org.freedesktop.DBus.Properties",
  54. signal_name="PropertiesChanged",
  55. path_keyword="path")
  56. def create_transfer_reply(self, path, properties):
  57. self.transfer_path = path
  58. self.transfer_size = properties["Size"]
  59. if self.verbose:
  60. print("Transfer created: %s" % path)
  61. def generic_reply(self):
  62. if self.verbose:
  63. print("Operation succeeded")
  64. def error(self, err):
  65. print(err)
  66. mainloop.quit()
  67. def properties_changed(self, interface, properties, invalidated, path):
  68. if path != self.transfer_path:
  69. return
  70. if "Status" in properties and \
  71. (properties['Status'] == 'complete' or \
  72. properties['Status'] == 'error'):
  73. if self.verbose:
  74. print("Transfer %s" % properties['Status'])
  75. mainloop.quit()
  76. return
  77. if "Transferred" not in properties:
  78. return
  79. value = properties["Transferred"]
  80. speed = (value - self.transferred) / 1000
  81. print("Transfer progress %d/%d at %d kBps" % (value,
  82. self.transfer_size,
  83. speed))
  84. self.transferred = value
  85. def change_folder(self, new_dir):
  86. for node in new_dir.split("/"):
  87. self.ftp.ChangeFolder(node)
  88. def list_folder(self):
  89. for i in self.ftp.ListFolder():
  90. if i["Type"] == "folder":
  91. print("%s/" % (i["Name"]))
  92. else:
  93. print("%s" % (i["Name"]))
  94. def put_file(self, filename):
  95. self.ftp.PutFile(os.path.abspath(filename),
  96. os.path.basename(filename),
  97. reply_handler=self.create_transfer_reply,
  98. error_handler=self.error)
  99. def get_file(self, filename):
  100. self.ftp.GetFile(os.path.abspath(filename),
  101. os.path.basename(filename),
  102. reply_handler=self.create_transfer_reply,
  103. error_handler=self.error)
  104. def remove_file(self, filename):
  105. self.ftp.Delete(filename,
  106. reply_handler=self.generic_reply,
  107. error_handler=self.error)
  108. def move_file(self, filename, destname):
  109. self.ftp.MoveFile(filename, destname,
  110. reply_handler=self.generic_reply,
  111. error_handler=self.error)
  112. def copy_file(self, filename, destname):
  113. self.ftp.CopyFile(filename, destname,
  114. reply_handler=self.generic_reply,
  115. error_handler=self.error)
  116. if __name__ == '__main__':
  117. dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
  118. parser = OptionParser()
  119. (options, args) = parse_options()
  120. if not options.device:
  121. parser.print_help()
  122. sys.exit(0)
  123. bus = dbus.SessionBus()
  124. mainloop = GObject.MainLoop()
  125. client = dbus.Interface(bus.get_object(BUS_NAME, PATH,),
  126. CLIENT_INTERFACE)
  127. print("Creating Session")
  128. path = client.CreateSession(options.device, { "Target": "ftp" })
  129. ftp_client = FtpClient(path, options.verbose)
  130. if options.new_dir:
  131. ftp_client.change_folder(options.new_dir)
  132. if options.list_dir:
  133. ftp_client.list_folder()
  134. if options.get_file:
  135. ftp_client.get_file(options.get_file)
  136. if options.put_file:
  137. ftp_client.put_file(options.put_file)
  138. if options.move_file:
  139. ftp_client.move_file(options.move_file, options.dest_file)
  140. if options.copy_file:
  141. ftp_client.copy_file(options.copy_file, options.dest_file)
  142. if options.remove_file:
  143. ftp_client.remove_file(options.remove_file)
  144. mainloop.run()