Program to mount remote filesystems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

nemo.py 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #!/usr/bin/env python3
  2. # -*- coding: UTF-8 -*-
  3. #
  4. # generated by wxGlade 0.6.8 on Sun Mar 9 14:56:37 2014
  5. #
  6. application_name = u'NeMo'
  7. application_version = u'0.1.0'
  8. import json
  9. import os
  10. import subprocess
  11. import wx
  12. # begin wxGlade: dependencies
  13. import gettext
  14. # end wxGlade
  15. # begin wxGlade: extracode
  16. # end wxGlade
  17. class NeMo(wx.Frame):
  18. def __init__(self, *args, **kwds):
  19. # begin wxGlade: NeMo.__init__
  20. kwds["style"] = kwds.get("style", 0) | wx.DEFAULT_FRAME_STYLE
  21. wx.Frame.__init__(self, *args, **kwds)
  22. self.SetSize((900, 480))
  23. self.text_ctrl_stdout = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
  24. self.text_ctrl_stderr = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
  25. self.__set_properties()
  26. self.__do_layout()
  27. # end wxGlade
  28. def __set_properties(self):
  29. # begin wxGlade: NeMo.__set_properties
  30. self.SetTitle(_("NeMo"))
  31. self.text_ctrl_stdout.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
  32. self.text_ctrl_stderr.SetForegroundColour(wx.Colour(255, 0, 0))
  33. self.text_ctrl_stderr.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
  34. # end wxGlade
  35. self.SetTitle(_("%s - V%s" % (application_name, application_version)))
  36. def __do_layout(self):
  37. # begin wxGlade: NeMo.__do_layout
  38. main_sizer = wx.BoxSizer(wx.HORIZONTAL)
  39. output_sizer = wx.BoxSizer(wx.VERTICAL)
  40. stderr_sizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("stderr")), wx.HORIZONTAL)
  41. stdout_sizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("stdout")), wx.HORIZONTAL)
  42. action_sizer = wx.BoxSizer(wx.VERTICAL)
  43. action_sizer.Add((0, 0), 0, 0, 0)
  44. action_sizer.Add((0, 0), 0, 0, 0)
  45. main_sizer.Add(action_sizer, 1, wx.EXPAND, 0)
  46. stdout_sizer.Add(self.text_ctrl_stdout, 1, wx.EXPAND, 0)
  47. output_sizer.Add(stdout_sizer, 1, wx.EXPAND, 0)
  48. stderr_sizer.Add(self.text_ctrl_stderr, 1, wx.EXPAND, 0)
  49. output_sizer.Add(stderr_sizer, 1, wx.EXPAND, 0)
  50. main_sizer.Add(output_sizer, 3, wx.EXPAND, 0)
  51. self.SetSizer(main_sizer)
  52. self.Layout()
  53. self.Centre()
  54. # end wxGlade
  55. self.action_sizer = action_sizer
  56. def AddStaBu(self, stabu):
  57. self.action_sizer.Add(stabu, 0, wx.EXPAND, 0)
  58. self.Layout()
  59. # end of class NeMo
  60. class StaBu(wx.BoxSizer):
  61. SSH_FS = 'ssh'
  62. WEB_DAV = 'dav'
  63. FTP_FS = 'ftp'
  64. def __init__(self, wx_frame, stdout, stderr, **kwargs):
  65. self.wx_frame = wx_frame
  66. self.stdout = stdout
  67. self.stderr = stderr
  68. for key in ['name', 'prot', 'remote_host', 'remote_path', 'local_path', 'user', 'port']:
  69. setattr(self, key, kwargs[key])
  70. for key, value in [('password', None), ]:
  71. setattr(self, key, kwargs.get(key, value))
  72. wx.BoxSizer.__init__(self, wx.HORIZONTAL)
  73. self.button = wx.Button(wx_frame, wx.ID_ANY, _(self.name))
  74. self.panel = wx.Panel(wx_frame, wx.ID_ANY)
  75. if kwargs.get('hidden', False):
  76. self.button.Hide()
  77. self.panel.Hide()
  78. elif kwargs.get('disabled', False):
  79. self.button.Disable()
  80. self.Add(self.button, 3, 0, 0)
  81. self.Add(self.panel, 1, wx.EXPAND, 0)
  82. wx_frame.Bind(wx.EVT_BUTTON, self.mount_pressed, self.button)
  83. self.panel.Bind(wx.EVT_LEFT_UP, self.open_pressed)
  84. wx_frame.Bind(wx.EVT_IDLE, self.panel_update, None)
  85. wx_frame.AddStaBu(self)
  86. def set_password(self):
  87. if self.password == None:
  88. box = wx.PasswordEntryDialog(self.wx_frame, 'Please enter password for %(name)s:' % self.__dict__, 'Password')
  89. if box.ShowModal() == wx.ID_OK:
  90. self.password = box.GetValue()
  91. box.Destroy()
  92. def error_msg(self, msg):
  93. self.stderr.write('nemo-file (%s): ' % self.name)
  94. self.stderr.write(msg)
  95. def panel_update(self, event):
  96. if self.is_mounted():
  97. #self.button_open.SetBackgroundColour('green')
  98. self.panel.SetBackgroundColour('green')
  99. else:
  100. #self.button_open.SetBackgroundColour('red')
  101. self.panel.SetBackgroundColour('red')
  102. event.Skip()
  103. def mount_pressed(self, event):
  104. if self.is_mounted():
  105. self.umount()
  106. else:
  107. self.mount()
  108. event.Skip()
  109. def open_pressed(self, event):
  110. for prog in ['nautilus', 'dolphin', 'nemo', 'thunar']:
  111. try:
  112. subprocess.Popen([prog, self.local_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  113. except OSError:
  114. pass
  115. else:
  116. break
  117. event.Skip()
  118. def check_prot(self):
  119. test_cmd = self.mount_cmd(True)
  120. if test_cmd == None:
  121. self.__ok__ = False
  122. self.error_msg('Protocol not supported!\n')
  123. #TODO: try to execute test_cmd to get info that progs are installed
  124. def is_mounted(self):
  125. p = subprocess.Popen(["mount"], stdout=subprocess.PIPE)
  126. out, err = p.communicate()
  127. self.stderr.write(err or '')
  128. if self.local_path in out.decode('utf-8'):
  129. return True
  130. else:
  131. return False
  132. def umount(self):
  133. self.stdout.write('umounting %s\n' % (self.local_path))
  134. p = subprocess.Popen(['fusermount', '-u', self.local_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  135. out, err = p.communicate()
  136. if not self.is_mounted():
  137. self.stdout.write('SUCCESS.\n')
  138. else:
  139. self.stdout.write('FAILED.\n')
  140. self.stdout.write(out or '')
  141. self.stderr.write(err or '')
  142. def mount(self):
  143. cmd = self.mount_cmd()
  144. self.stdout.write('mounting %(name)s to %(local_path)s\n' % self.__dict__)
  145. if cmd != None:
  146. p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  147. out, err = p.communicate()
  148. out = out.decode('utf-8')
  149. err = err.decode('utf-8')
  150. if self.password != None:
  151. out = out.replace(self.password, u'*****')
  152. err = err.replace(self.password, u'*****')
  153. if self.is_mounted():
  154. self.stdout.write('SUCCESS.\n')
  155. else:
  156. self.stdout.write('FAILED.\n')
  157. self.password = None
  158. self.stdout.write(out or '')
  159. self.stderr.write(err or '')
  160. else:
  161. self.stdout.write('FAILED.\n')
  162. def mount_cmd(self, test_cmd=False):
  163. if self.prot == self.SSH_FS:
  164. if test_cmd:
  165. return ['sshfs', '--version']
  166. return ['sshfs', '%(user)s@%(remote_host)s:%(remote_path)s' % self.__dict__, self.local_path]
  167. elif self.prot == self.WEB_DAV:
  168. if test_cmd:
  169. return ['wdfs', '--version']
  170. self.set_password()
  171. return ['wdfs', '-o', 'accept_sslcert,username=%(user)s,password=%(password)s' % self.__dict__, self.remote_host + self.remote_path, self.local_path]
  172. elif self.prot == self.FTP_FS:
  173. if test_cmd:
  174. return ['curlftpfs', '--version']
  175. self.set_password()
  176. return ['curlftpfs', 'ftp://%(user)s:%(password)s@%(remote_host)s:%(port)s%(remote_path)s' % self.__dict__, self.local_path]
  177. else:
  178. return None
  179. if __name__ == "__main__":
  180. gettext.install("app") # replace with the appropriate catalog name
  181. app = wx.App(0)
  182. nemo_frame = NeMo(None, wx.ID_ANY, "")
  183. #
  184. with open(os.path.abspath(os.path.join(os.path.expanduser('~'), '.nemo.json')), 'r') as fh:
  185. config = json.load(fh)
  186. for entry in config:
  187. StaBu(nemo_frame, nemo_frame.text_ctrl_stdout, nemo_frame.text_ctrl_stderr, **entry)
  188. #
  189. app.SetTopWindow(nemo_frame)
  190. nemo_frame.Show()
  191. app.MainLoop()