2 # -*- coding: utf-8 -*-
3 ##changing: - Add fusermount -z option
4 # - Add killall -KILL sshfs after fusermount to kill sshfs process when connection if turned off. unexpectedly (make file manager froze).
5 # - Removed mount point in home folder as the unique choice, we can choose whatever folder.
6 # - Empty fields as default (expect port)
7 # - "Open directory" box unchecked as default
8 # - Force mounting in a none empty folder (-o nonempty)
9 #To do: - Check/uncheck as default delete mount point when disconnect
10 # - Create a button to save profile
14 # by ADcomp <david.madbox@gmail.com>
15 # http://www.ad-comp.be/
17 # This program is distributed under the terms of the GNU General Public License
18 # For more info see http://www.gnu.org/licenses/gpl.txt
26 ## print debug info ( True / False )
32 ## preremplissage des champs
34 #self.user = os.getenv('USER')
44 home
= os
.environ
['HOME']
45 file_src
= "%s/.config/pysshfs/%s.profil" % (home
, file)
46 if os
.access(file_src
, os
.F_OK|os
.R_OK
):
47 f
= open(file_src
,'r')
49 if line
== '\n' or line
[0]=='#':
52 line
= line
.strip('\n')
53 key
, value
= line
.split('=',1)
65 elif key
== 'mountpoint':
66 self
.mountpoint
= value
72 print "can't access profil: %s" % profil
78 self
.window
= gtk
.Window(gtk
.WINDOW_TOPLEVEL
)
79 self
.window
.set_title("Mount sshFS")
80 self
.window
.set_position(gtk
.WIN_POS_CENTER
)
81 self
.window
.connect("destroy", self
.quit
)
83 if os
.access('pysshfs.png', os
.F_OK|os
.R_OK
):
84 self
.window
.set_icon_from_file('pysshfs.png')
86 self
.window
.set_icon_from_file('/usr/share/pixmaps/pysshfs.png')
89 BoxBase
= gtk
.VBox(False, 0)
90 BoxBase
.set_spacing(10)
91 BoxBase
.set_border_width(10)
94 BoxMain
.set_spacing(5)
95 BoxMain
.set_border_width(5)
97 BoxControls
= gtk
.HButtonBox()
98 #~ BoxControls.set_spacing(2)
99 BoxControls
.set_layout(gtk
.BUTTONBOX_END
)
102 button_exit
= gtk
.Button(stock
=gtk
.STOCK_CLOSE
)
103 button_exit
.connect("clicked", self
.quit
)
104 BoxControls
.pack_end(button_exit
, False, False)
107 table
.set_row_spacings(5)
108 table
.set_col_spacings(5)
111 self
.profil_combo
= gtk
.combo_box_new_text()
112 self
.profil_combo
.append_text('New Connection')
114 home
= os
.environ
['HOME']
116 if os
.path
.exists("%s/.config/pysshfs" % home
):
117 listdir
= os
.listdir("%s/.config/pysshfs" % home
)
118 for profil
in listdir
:
119 if '.profil' in profil
:
120 self
.profil_combo
.append_text(profil
[:-7])
122 self
.profil_combo
.set_active(0)
123 self
.profil_combo
.connect('changed', self
.changed_profil
)
125 table
.attach(self
.profil_combo
, 0, 2, 0, 1)
128 self
.User_entry
= gtk
.Entry()
130 label
= gtk
.Label('User :')
131 label
.set_alignment(0, 1)
132 table
.attach(label
, 0, 1, 1, 2)
133 table
.attach(self
.User_entry
, 1, 2, 1, 2)
136 self
.Password_entry
= gtk
.Entry()
137 self
.Password_entry
.set_visibility(False)
138 label
= gtk
.Label('Password :')
139 label
.set_alignment(0, 1)
140 table
.attach(label
, 0, 1, 2, 3)
141 table
.attach(self
.Password_entry
, 1, 2, 2, 3)
144 self
.Host_entry
= gtk
.Entry()
145 label
= gtk
.Label('Host :')
146 label
.set_alignment(0, 1)
147 table
.attach(label
, 0, 1, 3, 4)
148 table
.attach(self
.Host_entry
, 1, 2, 3, 4)
151 self
.Dir_entry
= gtk
.Entry()
152 label
= gtk
.Label('Dir :')
153 label
.set_alignment(0, 1)
154 table
.attach(label
, 0, 1, 4, 5)
155 table
.attach(self
.Dir_entry
, 1, 2, 4, 5)
158 self
.Mountpoint_entry
= gtk
.Entry()
159 label
= gtk
.Label('Mountpoint :')
160 label
.set_alignment(0, 1)
161 table
.attach(label
, 0, 1, 5, 6)
162 table
.attach(self
.Mountpoint_entry
, 1, 2, 5, 6)
165 self
.Port_entry
= gtk
.Entry()
166 label
= gtk
.Label('Port :')
167 label
.set_alignment(0, 1)
168 table
.attach(label
, 0, 1, 6, 7)
169 table
.attach(self
.Port_entry
, 1, 2, 6, 7)
172 self
.OpenDir_checkbox
= gtk
.CheckButton('Open directory')
173 ## cocher/decocher par defaut l'ouverture du dossier
174 self
.OpenDir_checkbox
.set_active(False)
175 table
.attach(self
.OpenDir_checkbox
, 0, 1, 7, 8)
178 self
.Connect_Bt
= gtk
.Button(stock
=gtk
.STOCK_CONNECT
)
179 self
.Connect_Bt
.connect("clicked", self
.mount_sshfs
)
180 table
.attach(self
.Connect_Bt
, 1, 2, 7, 8)
183 table
.attach(gtk
.HSeparator(), 0, 2, 8, 9)
187 label
.set_markup("<b>Mountpoint</b>")
188 label
.set_alignment(0, 1)
189 table
.attach(label
, 0, 2, 9, 10)
192 self
.Mounted_fs_combo
= gtk
.combo_box_new_text()
193 table
.attach(self
.Mounted_fs_combo
, 0, 2, 10, 11)
196 self
.Open_Bt
= gtk
.Button(stock
=gtk
.STOCK_OPEN
)
197 self
.Open_Bt
.connect("clicked", self
.open_mountpoint
)
198 table
.attach(self
.Open_Bt
, 0, 1, 11, 12)
200 self
.Umount_Bt
= gtk
.Button(stock
=gtk
.STOCK_DISCONNECT
)
201 self
.Umount_Bt
.connect("clicked", self
.umount_sshfs
)
202 table
.attach(self
.Umount_Bt
, 1, 2, 11, 12)
204 ## creation du bouton de sauvegarde de profil
205 #self.Umount_Bt = gtk.Button(stock=gtk.STOCK_SAVE)
206 #Self.Umount_Bt.connect("clicked", self.save_profile)
207 #table.attach(self.Umount_Bt, 0, 2, 16, 17)
210 self
.check_remove
= gtk
.CheckButton('delete mountpoint when disconnect')
211 table
.attach(self
.check_remove
, 0, 2, 12, 13)
214 table
.attach(gtk
.HSeparator(), 0, 2, 13, 14)
216 #~ BoxMain.add(table)
217 BoxBase
.pack_start(table
, True)
218 BoxBase
.pack_end(BoxControls
, False)
220 self
.window
.add(BoxBase
)
221 #turn off auto mountpoint
222 #self.User_entry.connect("changed", self.auto_mountpoint)
223 #self.Host_entry.connect("changed", self.auto_mountpoint)
225 self
.update_mountedfs()
227 self
.profil
= Profil()
228 self
.init_entry(self
.profil
)
230 #Show main window frame and all content
231 self
.window
.show_all()
233 def init_entry(self
, profil
):
234 self
.User_entry
.set_text(profil
.user
)
235 self
.Password_entry
.set_text(profil
.pwd
)
236 self
.Host_entry
.set_text(profil
.host
)
237 self
.Dir_entry
.set_text(profil
.dir)
238 self
.Mountpoint_entry
.set_text(profil
.mountpoint
)
239 self
.Port_entry
.set_text(profil
.port
)
241 def changed_profil(self
, combobox
):
242 model
= combobox
.get_model()
243 index
= combobox
.get_active()
247 self
.init_entry(self
.profil
)
249 self
.profil
.open(model
[index
][0])
250 self
.init_entry(self
.profil
)
254 def open_profil(self
, profil
):
255 print 'open_profil: %s' % profil
256 #desactive la creation auto du point de montage
257 # def auto_mountpoint(self, widget):
258 # User = self.User_entry.get_text()
259 # Host = self.Host_entry.get_text()
260 # self.Mountpoint_entry.set_text('%s@%s' % (User, Host))
262 def open_mountpoint(self
, widget
):
263 mount_point
= self
.Mounted_fs_combo
.get_active()
264 if mount_point
== 0 or mount_point
== -1:
267 os
.system('xdg-open %s' % self
.Mounted_fs_combo
.get_active_text())
269 def umount_sshfs(self
, widget
):
270 mount_point
= self
.Mounted_fs_combo
.get_active()
271 if mount_point
== 0 or mount_point
== -1:
274 os
.system('fusermount -u -z %s && killall -KILL sshfs' % self
.Mounted_fs_combo
.get_active_text())
275 if self
.check_remove
.get_active():
276 os
.rmdir(self
.Mounted_fs_combo
.get_active_text())
277 self
.update_mountedfs()
278 ## button ton save profile
279 #def save_profile(self, widget):
281 def update_mountedfs(self
):
282 self
.mounted_fs_tab
= get_mounted_fs()
283 self
.Mounted_fs_combo
.get_model().clear()
284 self
.Mounted_fs_combo
.insert_text(0, 'Choose')
287 for mounted_fs
in self
.mounted_fs_tab
:
288 self
.Mounted_fs_combo
.insert_text(ind
, mounted_fs
[1])
290 self
.Mounted_fs_combo
.set_active(0)
292 def mount_sshfs(self
, widget
):
293 User
= self
.User_entry
.get_text()
294 Password
= self
.Password_entry
.get_text()
295 Host
= self
.Host_entry
.get_text()
296 Dir
= self
.Dir_entry
.get_text()
298 Mountpoint
= self
.Mountpoint_entry
.get_text()
299 #Mountpoint = os.getenv('HOME') + '/' + self.Mountpoint_entry.get_text()
301 if not os
.path
.exists(Mountpoint
):
304 Port
= self
.Port_entry
.get_text()
306 if User
== '' or Password
== '' or Host
== '' or Mountpoint
=='' or Port
=='':
308 debug_info('Error : please check your config')
309 show_msg('Error : please check your config')
313 ret
= sshfs
.mount(User
, Password
, Host
, Dir
, Mountpoint
, Port
)
314 self
.update_mountedfs()
317 if self
.OpenDir_checkbox
.get_active():
318 os
.system('xdg-open %s' % Mountpoint
)
325 def quit(self
, widget
=None, data
=None):
328 ## Initialize the module.
331 ## Three responses we might expect.
332 self
.Initial_Responses
= ['Are you sure you want to continue connecting (yes/no)?',
333 'password:', pexpect
.EOF
]
335 def mount(self
, User
="", Password
="", Host
="", Dir
="", Mountpoint
="", Port
=22, Timeout
=120):
337 Command
= "sshfs -o allow_other -o nonempty -p %s %s@%s:%s %s" % (Port
, User
, Host
, Dir
, Mountpoint
)
338 debug_info("Command : %s" % Command
)
340 child
= pexpect
.spawn(Command
)
342 ## Get the first response.
343 ret
= child
.expect (self
.Initial_Responses
, Timeout
)
344 ## The first reponse is to accept the key.
346 debug_info("The first reponse is to accept the key.")
347 #~ T = child.read(100)
348 child
.sendline("yes")
349 child
.expect('password:', Timeout
)
350 child
.sendline(Password
)
351 ## The second response sends the password.
353 debug_info("The second response sends the password.")
354 child
.sendline(Password
)
355 ## Otherwise, there is an error.
357 debug_info("Otherwise, there is an error.")
358 return (-3, 'ERROR: Unknown: ' + str(child
.before
))
360 ## Get the next response.
361 Possible_Responses
= ['password:', pexpect
.EOF
]
362 ret
= child
.expect (Possible_Responses
, Timeout
)
364 ## If it asks for a password, error.
366 debug_info("If it asks for a password, error.")
367 return (-4, 'ERROR: Incorrect password.')
369 debug_info("Otherwise we are okay.")
370 return (0, str(child
.after
))
371 ## Otherwise we are okay.
373 debug_info("Otherwise, there is an error.")
374 return (-3, 'ERROR: Unknown: ' + str(child
.before
))
376 def show_msg(msg
=' .. '):
378 message
= gtk
.MessageDialog(None, gtk
.DIALOG_MODAL
, gtk
.MESSAGE_INFO
, gtk
.BUTTONS_OK
, msg
)
382 def get_mounted_fs():
383 """ get_mounted_fs() -> reads mtab and returns a list of mounted sshfs filesystems. """
386 lines
= [line
.strip("\n").split(" ") for line
in open ("/etc/mtab", "r").readlines()]
388 if line
[2] == "fuse.sshfs" and "user=%s" % os
.getenv('USER') in line
[3]:
389 mounted_fs
.append((line
[0], line
[1]))
392 debug_info("Could not read mtab")
393 show_msg("Could not read mtab .. :(")
399 if __name__
== "__main__":