├── image000.jpg ├── README.md ├── license.txt ├── select.pyui ├── popover.pyui ├── SMBclient.pyui └── SMBclient.py /image000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/humberry/SMBclient/HEAD/image000.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Access Samba/Windows-Shares 2 | =========================== 3 | 4 | ![alt text](https://img.shields.io/badge/iOS-11.x-lightgrey.svg?style=plastic "iOS 11.x") 5 | ![alt text](https://img.shields.io/badge/Pythonista-3.2-green.svg?style=plastic "Pythonista 3.2") 6 | ![alt text](https://img.shields.io/badge/Python-2.7-blue.svg?style=plastic "Python 2.7") 7 | 8 | Small ui example: upload/download/rename/delete files or make/remove directories. Use at your own risk, this worked with my mini wifi router usb share. I'm not responsible for data loses (please always backup your data:). 9 | 10 | First you need to download the impacket python module: impacket-0.9.12.tar.gz 11 | Then extract \impacket-0.9.12\impacket\ to the side-packages directory. 12 | And you also need a copy of ntpath.py in your side-package directory. 13 | 14 | ![](https://raw.githubusercontent.com/humberry/SMBclient/master/image000.jpg) 15 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2017] [humberry] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | Commercial use is not allowed. -------------------------------------------------------------------------------- /select.pyui: -------------------------------------------------------------------------------- 1 | [{"class":"View","attributes":{"name":"","tint_color":"RGBA(0.000000,0.478000,1.000000,1.000000)","background_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","enabled":true,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":""},"frame":"{{0, 0}, {640, 258}}","nodes":[{"class":"SegmentedControl","attributes":{"name":"sc_range","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","uuid":"BDCC38A2-8422-4ACE-BB24-351453EF9EB3","enabled":true,"segments":"Selected File|All Files|Filter","flex":"LR"},"frame":"{{6, 55}, {628, 60}}","nodes":[]},{"class":"TextField","attributes":{"font_size":17,"enabled":true,"text":"","flex":"","name":"tf_name","border_style":3,"text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","uuid":"06F7ADD5-4018-492A-B1C6-CBA5EC951665"},"frame":"{{6, 6.5}, {628, 40.5}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"","font_bold":false,"name":"bt_okay","uuid":"11745D14-C20F-42F0-9CF9-EACBEA6211D5","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","title":"Okay"},"frame":"{{6, 191.5}, {310, 60}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"","font_bold":false,"name":"bt_cancel","uuid":"12ED6182-05AA-4A93-8805-80C3295052F9","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","title":"Cancel"},"frame":"{{324, 191.5}, {310, 60}}","nodes":[]},{"class":"TextField","attributes":{"font_size":17,"enabled":true,"text":"*.jpg","flex":"","name":"tf_filter","border_style":3,"text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","uuid":"27E30854-1424-40A3-BF0B-4B3662D0257A"},"frame":"{{497, 123}, {137, 40.5}}","nodes":[]},{"class":"Label","attributes":{"font_size":17,"enabled":true,"text":"Filter: ","flex":"","name":"lb_filter","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"right","uuid":"3DA0DFAC-1B1B-403A-A914-F297A7563BA9"},"frame":"{{358, 123}, {131, 40.5}}","nodes":[]}]}] 2 | -------------------------------------------------------------------------------- /popover.pyui: -------------------------------------------------------------------------------- 1 | [{"class":"View","attributes":{"name":"","background_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","tint_color":"RGBA(0.000000,0.478000,1.000000,1.000000)","enabled":true,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":""},"frame":"{{0, 0}, {640, 153}}","nodes":[{"class":"Label","attributes":{"font_size":17,"enabled":true,"text":"Old Name:","flex":"","name":"lb_on","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","uuid":"70424133-4A7A-4820-8F58-0BEBA1687CF1"},"frame":"{{6, 6}, {95, 32}}","nodes":[]},{"class":"Label","attributes":{"font_size":17,"enabled":true,"text":"","flex":"","name":"lb_old_name","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","uuid":"53CE4840-B044-47AF-9E74-A2D712A06FFB"},"frame":"{{109, 6}, {525, 32}}","nodes":[]},{"class":"Label","attributes":{"font_size":17,"enabled":true,"text":"New Name:","flex":"","name":"lb_nn","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","uuid":"592564C0-1D08-48E4-8E52-BEBD91EF9506"},"frame":"{{6, 46}, {95, 32}}","nodes":[]},{"class":"TextField","attributes":{"font_size":17,"enabled":true,"flex":"","name":"tf_new_name","border_style":3,"text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","uuid":"CAB7C874-97FE-4BB0-86F6-27FDAAD85AF0"},"frame":"{{109, 46}, {525, 32}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"","font_bold":false,"name":"bt_okay","uuid":"510629AA-2FC6-4DE7-9F12-58ABC4839379","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","title":"Okay"},"frame":"{{6, 86}, {310, 60.5}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"","font_bold":false,"name":"bt_cancel","uuid":"5AAB1D83-3EEE-4725-B4A7-ECD7B349A537","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","title":"Cancel"},"frame":"{{324, 86.5}, {310, 60.5}}","nodes":[]}]}] 2 | -------------------------------------------------------------------------------- /SMBclient.pyui: -------------------------------------------------------------------------------- 1 | [{"class":"View","attributes":{"name":"SMBclient","tint_color":"RGBA(0.000000,0.478000,1.000000,1.000000)","background_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","enabled":true,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","flex":""},"frame":"{{0, 0}, {768, 960}}","nodes":[{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"","font_bold":true,"name":"bt_connect","corner_radius":5,"border_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","border_width":3,"uuid":"7AD78AAF-EF1C-4410-9CF1-2A83BC87251A","title":"Connect"},"frame":"{{24.5, 13.5}, {90, 58.5}}","nodes":[]},{"class":"TextField","attributes":{"font_size":17,"enabled":true,"text":"10.10.10.254\/USBDisk1_Volume1","flex":"","name":"tf_host","border_style":3,"text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","uuid":"C4FD6A71-F693-45A8-B1C3-CF731E159B85"},"frame":"{{138.5, 40}, {301.5, 32}}","nodes":[]},{"class":"TextField","attributes":{"font_size":17,"enabled":true,"text":"admin","flex":"","name":"tf_user","border_style":3,"text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","uuid":"BF6E2370-EF2D-4D26-B367-012BE0EE7685"},"frame":"{{452, 40}, {150, 32}}","nodes":[]},{"class":"TextField","attributes":{"font_size":17,"enabled":true,"text":"","secure":true,"name":"tf_password","flex":"","border_style":3,"text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","uuid":"D15A9796-AF00-497D-95D3-18CAA0BCED4D"},"frame":"{{610, 40}, {150, 32}}","nodes":[]},{"class":"Label","attributes":{"font_size":17,"enabled":true,"text":"Host\/Share","flex":"","name":"label1","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","uuid":"A6BDC61C-CA2B-4E3D-A3AF-70D081A1DAC6"},"frame":"{{140, 0}, {150, 32}}","nodes":[]},{"class":"Label","attributes":{"font_size":17,"enabled":true,"text":"User:","flex":"","name":"label2","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","uuid":"21FD6F8B-F724-4E64-958D-A5B539E59DF1"},"frame":"{{452, 0}, {150, 32}}","nodes":[]},{"class":"Label","attributes":{"font_size":17,"enabled":true,"text":"Password:","flex":"","name":"label3","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","alignment":"left","uuid":"605CFCB0-4A29-49B1-9573-A7ACD93EB0D8"},"frame":"{{610, 0}, {150, 32}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"WLRT","font_bold":true,"name":"bt_upload","corner_radius":5,"border_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","border_width":3,"uuid":"567B1FFA-A6DB-4734-8AC0-929BCDA84F21","title":"Upload >"},"frame":"{{6, 811}, {85, 58.5}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"WLRT","font_bold":true,"name":"bt_download","corner_radius":5,"border_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","border_width":3,"uuid":"4D264473-411D-4404-85FA-42437F1171DE","title":"< Download"},"frame":"{{398, 811.5}, {85, 58.5}}","nodes":[]},{"class":"TableView","attributes":{"enabled":true,"data_source_font_size":14,"data_source_number_of_lines":1,"flex":"WHR","name":"tv_local","data_source_delete_enabled":true,"row_height":36,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","data_source_items":"","background_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","uuid":"71E89D06-BE72-421A-9F60-8650768FF7A9"},"frame":"{{6, 120}, {367, 683.5}}","nodes":[]},{"class":"Label","attributes":{"alignment":"center","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","font_size":20,"font_name":"","enabled":true,"flex":"WRB","numberOfLines":1,"text":"Local","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","name":"lb_local","border_width":0,"uuid":"11B3F14C-97C3-4AE8-8AEE-446B5A4D3786"},"frame":"{{6, 80}, {367, 32}}","nodes":[]},{"class":"Label","attributes":{"alignment":"center","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","font_size":20,"font_name":"","enabled":true,"flex":"WLB","numberOfLines":1,"text":"Remote","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","name":"lb_remote","border_width":0,"uuid":"F133687C-1C01-4A6A-99E2-6CA8AABB6E97"},"frame":"{{393, 80}, {367, 32}}","nodes":[]},{"class":"TableView","attributes":{"enabled":true,"data_source_font_size":14,"data_source_number_of_lines":1,"flex":"WHL","name":"tv_remote","data_source_delete_enabled":true,"row_height":36,"border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","data_source_items":"","background_color":"RGBA(1.000000,1.000000,1.000000,1.000000)","uuid":"550BF0F0-64D2-4472-982E-328A5D6C9BFD"},"frame":"{{393, 120}, {367, 683.5}}","nodes":[]},{"class":"TextView","attributes":{"alignment":"left","border_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","font_size":14,"font_name":"Courier","enabled":true,"flex":"WLRT","text_color":"RGBA(0.000000,0.000000,0.000000,1.000000)","name":"tv_info","corner_radius":5,"editable":true,"border_width":1,"uuid":"74C22F00-C602-4DCF-9E57-18F1CF3C13DE"},"frame":"{{6, 878}, {663, 76}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"WLRT","font_bold":true,"name":"bt_remote_rename","corner_radius":5,"border_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","border_width":3,"uuid":"9DD69F5D-F8A5-4521-B797-751C204FAEFF","title":"Rename"},"frame":"{{491, 811.5}, {85, 58.5}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"WLRT","font_bold":true,"name":"bt_remote_delete","corner_radius":5,"border_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","border_width":3,"uuid":"D674A938-2E08-42AA-AB73-D71FF4D5A053","title":"Delete"},"frame":"{{584, 811.5}, {85, 58.5}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"WLRT","font_bold":true,"name":"bt_remote_mkdir","corner_radius":5,"border_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","border_width":3,"uuid":"D09862EC-6486-4B0D-BE94-A84E27100CD7","title":"MkDir"},"frame":"{{677, 811.5}, {85, 58.5}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"WLRT","font_bold":true,"name":"bt_local_rename","corner_radius":5,"border_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","border_width":3,"uuid":"CAF410F9-0A83-48C6-A50A-F56BC86942C1","title":"Rename"},"frame":"{{99, 811.5}, {85, 58.5}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"WLRT","font_bold":true,"name":"bt_local_delete","corner_radius":5,"border_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","border_width":3,"uuid":"F5BC87E5-631A-4BEB-9C08-DDF02512FDF5","title":"Delete"},"frame":"{{192, 811}, {85, 58.5}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"WLRT","font_bold":true,"name":"bt_local_mkdir","corner_radius":5,"border_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","border_width":3,"uuid":"E271F792-2280-4A44-B1A2-7608B601EE6E","title":"MkDir"},"frame":"{{285, 811}, {85, 58.5}}","nodes":[]},{"class":"Button","attributes":{"font_size":15,"enabled":true,"flex":"WLRT","font_bold":true,"name":"bt_remote_rmdir","corner_radius":5,"border_color":"RGBA(0.000000,0.000000,1.000000,1.000000)","border_width":3,"uuid":"9F4A37F0-F026-4D7E-89DB-8466A99D73CD","title":"RmDir"},"frame":"{{677, 878}, {85, 58.5}}","nodes":[]}]}] 2 | -------------------------------------------------------------------------------- /SMBclient.py: -------------------------------------------------------------------------------- 1 | #! python2 2 | 3 | # You need the impacket python module (http://corelabs.coresecurity.com) 4 | # Extract the impacket directory to site-packages (https://pypi.python.org/packages/source/i/impacket/) 5 | # and you also need a copy of ntpath.py in your site-package directory 6 | 7 | import os, string, sys, time, ui 8 | from impacket import smb, version, smb3, nt_errors 9 | from impacket.dcerpc.v5 import samr, transport, srvs 10 | from impacket.dcerpc.v5.dtypes import NULL 11 | from impacket.smbconnection import * 12 | 13 | class SMBclient(ui.View): 14 | 15 | def __init__(self): 16 | self.fileName = '' 17 | self.localFile = '' 18 | self.remoteFile = '' 19 | self.smb = None 20 | self.pwd = '' 21 | self.share = None 22 | self.loggedIn = False 23 | self.password = None 24 | self.username = None 25 | self.host = None 26 | self.root = os.path.expanduser('~') 27 | self.path = os.getcwd() 28 | self.view = ui.load_view('SMBclient') 29 | self.view['bt_connect'].action = self.bt_connect 30 | self.view['bt_upload'].action = self.bt_upload 31 | self.view['bt_download'].action = self.bt_download 32 | self.view['bt_local_rename'].action = self.bt_local_rename 33 | self.view['bt_local_delete'].action = self.bt_local_delete 34 | self.view['bt_local_mkdir'].action = self.bt_local_mkdir 35 | self.view['bt_remote_rename'].action = self.bt_remote_rename 36 | self.view['bt_remote_delete'].action = self.bt_remote_delete 37 | self.view['bt_remote_mkdir'].action = self.bt_remote_mkdir 38 | self.view['bt_remote_rmdir'].action = self.bt_remote_rmdir 39 | self.root_len = len(self.root) 40 | self.view['lb_local'].text = self.path[self.root_len:] 41 | self.tv_local = self.view['tv_local'] 42 | self.tv_remote = self.view['tv_remote'] 43 | self.tv_info = self.view['tv_info'] 44 | all = self.get_dir() 45 | self.lst_local = ui.ListDataSource(all) 46 | self.tv_local.data_source = self.lst_local 47 | self.tv_local.delegate = self.lst_local 48 | self.tv_local.editing = False 49 | self.lst_local.font = ('Courier',14) 50 | self.lst_local.action = self.table_local_tapped 51 | self.lst_local.delete_enabled = False 52 | self.lst_remote = ui.ListDataSource(['']) 53 | self.tv_remote.data_source = self.lst_remote 54 | self.tv_remote.delegate = self.lst_remote 55 | self.tv_remote.editing = False 56 | self.lst_remote.font = ('Courier',14) 57 | self.lst_remote.action = self.table_remote_tapped 58 | self.lst_remote.delete_enabled = False 59 | self.view.present('fullscreen') 60 | 61 | def is_root(self, path): 62 | return path in ('/', '\\') 63 | 64 | def open_popover_view(self, view_name, view_title): 65 | self.view_po = ui.load_view(view_name) 66 | self.view_po.name = view_title 67 | self.view_po.present('popover',popover_location=(self.view.width/2,self.view.height/2)) 68 | self.view_po['bt_cancel'].action = self.bt_cancel 69 | 70 | def bt_local_rename(self, sender): 71 | self.open_popover_view('popover', 'Rename local file?') 72 | pos = self.localFile.rfind('/') 73 | self.fileName = self.localFile[pos+1:] 74 | self.view_po['lb_old_name'].text = self.fileName 75 | self.view_po['tf_new_name'].text = self.fileName 76 | self.view_po['bt_okay'].action = self.bt_local_rename_okay 77 | 78 | def bt_local_rename_okay(self, sender): 79 | os.rename(self.fileName, self.view_po['tf_new_name'].text) 80 | self.view_po.close() 81 | all = self.get_dir() 82 | self.refresh_table(self.tv_local,self.lst_local,all) 83 | 84 | def bt_cancel(self, sender): 85 | self.view_po.close() 86 | 87 | def bt_local_delete(self, sender): 88 | self.open_popover_view('select', 'Delete local file(s)?') 89 | if len(self.localFile) > 0: 90 | pos = self.localFile.rfind('/') 91 | self.fileName = self.localFile[pos+1:] 92 | else: 93 | self.fileName = self.path[self.root_len:] 94 | self.view_po['sc_range'].selected_index = 2 95 | self.view_po['tf_name'].text = self.fileName 96 | self.view_po['tf_name'].enabled = False 97 | self.view_po['bt_okay'].action = self.bt_select_okay_local_delete 98 | 99 | def get_files(self, filter=None, local=True): 100 | files = [] 101 | if filter == None: 102 | if local and self.localFile != '' or not local and self.remoteFile != '': 103 | files = [self.view_po['tf_name'].text] 104 | else: 105 | self.tv_info.text += "\nNo file selected to delete." 106 | else: 107 | #check filter 108 | if filter[0] != '*' and filter[1] != '.': 109 | self.tv_info.text += "\nFilter not valid! It has to start with *." 110 | return files 111 | if not local: 112 | entries = self.smb.listPath(self.share, self.pwd + '\\' + filter) 113 | filter = filter[1:] 114 | for e in entries: 115 | if e.is_directory() == 0: 116 | entry = str(e.get_longname()) 117 | if filter == '.*': # all files 118 | files.append(entry) 119 | else: # filtered files 120 | filter_len = len(filter) 121 | entry_len = len(entry) 122 | if entry.find(filter) == entry_len-filter_len: 123 | files.append(entry) 124 | else: 125 | filter = filter[1:] 126 | for entry in sorted(os.listdir(self.path)): 127 | if os.path.isfile(self.path + '/' + entry): 128 | if filter == '.*': # all files 129 | files.append(entry) 130 | else: # filtered files 131 | filter_len = len(filter) 132 | entry_len = len(entry) 133 | if entry.find(filter) == entry_len-filter_len: 134 | files.append(entry) 135 | return files 136 | 137 | def bt_select_okay_local_delete(self, sender): 138 | rang = self.view_po['sc_range'].selected_index 139 | if rang == 0: # selected file 140 | files = self.get_files() 141 | elif rang == 1: # all files 142 | files = self.get_files(filter='*.*') 143 | elif rang == 2: # filter 144 | files = self.get_files(filter=self.view_po['tf_filter'].text) 145 | if len(files) > 0: 146 | for file in files: 147 | try: 148 | os.remove(self.path + '/' + file) 149 | self.localFile = '' 150 | except Exception, e: 151 | self.tv_info.text += '\n' + str(e) 152 | all = self.get_dir() 153 | self.refresh_table(self.tv_local,self.lst_local,all) 154 | self.view_po.close() 155 | 156 | def bt_local_mkdir(self, sender): 157 | self.open_popover_view('popover', 'Make local directory?') 158 | self.view_po['lb_old_name'].text = self.path[self.root_len:] + '/' 159 | self.view_po['lb_on'].text = 'Path:' 160 | self.view_po['lb_nn'].text = 'New Dir:' 161 | self.view_po['bt_okay'].action = self.bt_local_mkdir_okay 162 | 163 | def bt_local_mkdir_okay(self, sender): 164 | directory = self.view_po['tf_new_name'].text 165 | os.mkdir(self.path + '/' + directory) 166 | self.view_po.close() 167 | all = self.get_dir() 168 | self.refresh_table(self.tv_local,self.lst_local,all) 169 | 170 | def bt_remote_rename(self, sender): 171 | if self.loggedIn: 172 | self.open_popover_view('popover', 'Rename remote file?') 173 | pos = self.remoteFile.rfind('\\') 174 | self.fileName = self.remoteFile[pos+1:] 175 | self.view_po['lb_old_name'].text = self.fileName 176 | self.view_po['tf_new_name'].text = self.fileName 177 | self.view_po['bt_okay'].action = self.bt_remote_rename_okay 178 | 179 | def bt_remote_rename_okay(self, sender): 180 | self.smb.rename(self.share, self.remoteFile, self.pwd + '\\' + self.view_po['tf_new_name'].text) 181 | self.view_po.close() 182 | all = self.get_remote_dir() 183 | self.refresh_table(self.tv_remote,self.lst_remote,all) 184 | 185 | def bt_remote_delete(self, sender): 186 | if self.loggedIn: 187 | self.open_popover_view('select', 'Delete remote file(s)?') 188 | if len(self.remoteFile) > 0: 189 | pos = self.remoteFile.rfind('\\') 190 | self.fileName = self.remoteFile[pos+1:] 191 | else: 192 | self.fileName = self.pwd 193 | self.view_po['sc_range'].selected_index = 2 194 | self.view_po['tf_name'].text = self.fileName 195 | self.view_po['tf_name'].enabled = False 196 | self.view_po['bt_okay'].action = self.bt_select_okay_remote_delete 197 | 198 | def bt_select_okay_remote_delete(self, sender): 199 | rang = self.view_po['sc_range'].selected_index 200 | if rang == 0: # selected file 201 | files = self.get_files(local=False) 202 | elif rang == 1: # all files 203 | files = self.get_files(filter='*.*', local=False) 204 | elif rang == 2: # filter 205 | files = self.get_files(filter=self.view_po['tf_filter'].text, local=False) 206 | if len(files) > 0: 207 | for file in files: 208 | try: 209 | self.smb.deleteFile(self.share, self.pwd + '\\' + file) 210 | self.remoteFile = '' 211 | except Exception, e: 212 | self.tv_info.text += '\n' + str(e) 213 | all = self.get_remote_dir() 214 | self.refresh_table(self.tv_remote,self.lst_remote,all) 215 | self.view_po.close() 216 | 217 | def bt_remote_rmdir(self, sender): 218 | if self.loggedIn: 219 | self.open_popover_view('popover', 'Remove remote directory?') 220 | if self.is_root(self.pwd): 221 | self.view_po['lb_old_name'].text = self.pwd 222 | else: 223 | self.view_po['lb_old_name'].text = self.pwd + '\\' 224 | self.view_po['lb_on'].text = 'Path:' 225 | self.view_po['lb_nn'].text = 'Remove Dir:' 226 | self.view_po['bt_okay'].action = self.bt_remote_rmdir_okay 227 | 228 | def bt_remote_rmdir_okay(self, sender): 229 | directory = self.view_po['tf_new_name'].text 230 | if self.is_root(self.pwd) and directory == '': 231 | self.tv_info.text += "\nSorry, root directory is not removable." 232 | else: 233 | try: 234 | self.smb.deleteDirectory(self.share,self.pwd + '\\' + directory) 235 | except Exception, e: 236 | self.tv_info.text += '\n' + str(e) 237 | self.view_po.close() 238 | all = self.get_remote_dir() 239 | self.refresh_table(self.tv_remote,self.lst_remote,all) 240 | 241 | def bt_remote_mkdir(self, sender): 242 | if self.loggedIn: 243 | self.open_popover_view('popover', 'Make remote directory?') 244 | if self.is_root(self.pwd): 245 | self.view_po['lb_old_name'].text = self.pwd 246 | else: 247 | self.view_po['lb_old_name'].text = self.pwd + '\\' 248 | self.view_po['lb_on'].text = 'Path:' 249 | self.view_po['lb_nn'].text = 'New Dir:' 250 | self.view_po['bt_okay'].action = self.bt_remote_mkdir_okay 251 | 252 | def bt_remote_mkdir_okay(self, sender): 253 | directory = self.view_po['tf_new_name'].text 254 | if self.is_root(self.pwd): 255 | self.smb.createDirectory(self.share,self.pwd + directory) 256 | else: 257 | self.smb.createDirectory(self.share,self.pwd + '\\' + directory) 258 | self.view_po.close() 259 | all = self.get_remote_dir() 260 | self.refresh_table(self.tv_remote,self.lst_remote,all) 261 | 262 | def bt_connect(self, sender): 263 | hostshare = self.view['tf_host'].text 264 | if hostshare.find('/') > 0: 265 | self.host, self.share = hostshare.split('/') 266 | self.username = self.view['tf_user'].text 267 | self.password = self.view['tf_password'].text 268 | 269 | if self.loggedIn is False: 270 | try: 271 | self.smb = SMBConnection('*SMBSERVER', self.host, sess_port=139) 272 | dialect = self.smb.getDialect() 273 | if dialect == SMB_DIALECT: 274 | self.tv_info.text = "SMBv1 dialect used" 275 | elif dialect == SMB2_DIALECT_002: 276 | self.tv_info.text = "SMBv2.0 dialect used" 277 | elif dialect == SMB2_DIALECT_21: 278 | self.tv_info.text = "SMBv2.1 dialect used" 279 | else: 280 | self.tv_info.text = "SMBv3.0 dialect used" 281 | if self.smb is None: 282 | self.tv_info.text = "No connection open" 283 | return 284 | self.smb.login(self.username, self.password, domain='') 285 | if self.smb.isGuestSession() > 0: 286 | self.tv_info.text += "\nGUEST Session Granted" 287 | else: 288 | self.tv_info.text += "\nUSER Session Granted" 289 | self.loggedIn = True 290 | self.smb.connectTree(self.share) 291 | self.pwd = '\\' 292 | all = self.get_remote_dir() 293 | self.refresh_table(self.tv_remote,self.lst_remote,all) 294 | self.view['lb_remote'].text = self.pwd 295 | sender.title = 'Disconnect' 296 | except Exception, e: 297 | self.tv_info.text += '\n' + str(e) 298 | self.loggedIn = False 299 | else: 300 | if self.smb is not None: 301 | del(self.smb); 302 | self.share = None 303 | self.pwd = '' 304 | self.loggedIn = False 305 | self.password = None 306 | self.username = None 307 | sender.title = 'Connect' 308 | self.tv_info.text += "\nConnection closed" 309 | all = [] 310 | self.view['lb_remote'].text = '' 311 | self.refresh_table(self.view['tv_remote'], self.lst_remote, all) 312 | 313 | def bt_upload(self, sender): #put 314 | if self.loggedIn: 315 | self.open_popover_view('select', 'Upload local file(s)?') 316 | if len(self.localFile) > 0: 317 | pos = self.localFile.rfind('/') 318 | self.fileName = self.localFile[pos+1:] 319 | else: 320 | self.fileName = self.path[self.root_len:] 321 | self.view_po['sc_range'].selected_index = 1 322 | self.view_po['tf_name'].text = self.fileName 323 | self.view_po['tf_name'].enabled = False 324 | self.view_po['bt_okay'].action = self.bt_select_okay_put 325 | 326 | def bt_select_okay_put(self, sender): 327 | rang = self.view_po['sc_range'].selected_index 328 | if rang == 0: # selected file 329 | files = self.get_files() 330 | elif rang == 1: # all files 331 | files = self.get_files(filter='*.*') 332 | elif rang == 2: # filter 333 | files = self.get_files(filter=self.view_po['tf_filter'].text) 334 | if len(files) > 0: 335 | for file in files: 336 | fh = open(self.path + '/' + file, 'rb') 337 | if self.is_root(self.pwd): 338 | self.smb.putFile(self.share, self.pwd + file, fh.read) 339 | else: 340 | self.smb.putFile(self.share, self.pwd + '\\' + file, fh.read) 341 | fh.close() 342 | all = self.get_remote_dir() 343 | self.refresh_table(self.tv_remote,self.lst_remote,all) 344 | self.view_po.close() 345 | 346 | def bt_download(self, sender): #get 347 | if self.loggedIn: 348 | self.open_popover_view('select', 'Download remote file(s)?') 349 | pos = self.remoteFile.rfind('\\') 350 | fileName = self.remoteFile[pos+1:] 351 | self.view_po['tf_name'].text = fileName 352 | self.view_po['tf_name'].enabled = False 353 | self.view_po['bt_okay'].action = self.bt_select_okay_get 354 | 355 | def bt_select_okay_get(self, sender): 356 | rang = self.view_po['sc_range'].selected_index 357 | if rang == 0: # selected file 358 | files = self.get_files(local=False) 359 | elif rang == 1: # all files 360 | files = self.get_files(filter='*.*', local=False) 361 | elif rang == 2: # filter 362 | files = self.get_files(filter=self.view_po['tf_filter'].text, local=False) 363 | if len(files) > 0: 364 | for file in files: 365 | fh = open(self.path + '/' + file,'wb') 366 | try: 367 | self.smb.getFile(self.share, self.pwd + '\\' + file, fh.write) 368 | except: 369 | fh.close() 370 | os.remove(self.path + '/' + file) 371 | fh.close() 372 | all = self.get_dir() 373 | self.refresh_table(self.tv_local,self.lst_local,all) 374 | self.view_po.close() 375 | 376 | def table_local_tapped(self, sender): 377 | rowtext = sender.items[sender.selected_row] 378 | filename_tapped = rowtext 379 | if rowtext[0] == '/': 380 | if filename_tapped == '/..': 381 | pos = self.path.rfind('/') 382 | self.path = self.path[:pos] 383 | else: 384 | self.path = self.path + filename_tapped 385 | self.localFile = '' 386 | all = self.get_dir() 387 | root_len = len(self.root) 388 | self.view['lb_local'].text = self.path[root_len:] 389 | self.refresh_table(self.view['tv_local'],self.lst_local,all) 390 | else: 391 | self.localFile = self.path + '/' + filename_tapped 392 | 393 | def table_remote_tapped(self, sender): 394 | rowtext = sender.items[sender.selected_row] 395 | filename_tapped = rowtext 396 | if rowtext[0] == '\\': #directory 397 | if filename_tapped == '\\..': # up 398 | pos = self.pwd.rfind('\\') 399 | self.pwd = self.pwd[:pos] 400 | if self.pwd == '': 401 | self.pwd = '\\' 402 | else: 403 | if self.is_root(self.pwd): 404 | self.pwd = filename_tapped 405 | else: 406 | self.pwd += filename_tapped 407 | self.remoteFile = '' 408 | all = self.get_remote_dir() 409 | self.refresh_table(self.tv_remote,self.lst_remote,all) 410 | self.view['lb_remote'].text = self.pwd 411 | else: # file 412 | self.remoteFile = self.pwd + '\\' + filename_tapped 413 | 414 | def refresh_table(self, table, lst, data): 415 | lst = ui.ListDataSource(data) 416 | table.data_source = lst 417 | table.delegate = lst 418 | table.editing = False 419 | lst.font = ('Courier',14) 420 | if table.name == 'tv_local': 421 | lst.action = self.table_local_tapped 422 | else: 423 | lst.action = self.table_remote_tapped 424 | lst.delete_enabled = False 425 | table.reload_data() 426 | return 427 | 428 | def get_dir(self): 429 | dirs = [] if self.path == self.root else ['..'] 430 | files = [] 431 | for entry in sorted(os.listdir(self.path)): 432 | if os.path.isdir(self.path + '/' + entry): 433 | dirs.append(entry) 434 | else: 435 | files.append(entry) 436 | all = ['/' + dir for dir in dirs] 437 | for file in files: 438 | full_pathname = self.path + '/' + file 439 | all.append('{}'.format(file)) 440 | return all 441 | 442 | def get_remote_dir(self): 443 | if self.loggedIn: 444 | remoteDir = [] if self.pwd == '\\' else ['\\..'] 445 | files = [] 446 | entries = self.smb.listPath(self.share, self.pwd + '\\*') 447 | for e in entries: 448 | if e.is_directory() > 0: 449 | if str(e.get_longname()) != '.' and str(e.get_longname()) != '..': 450 | remoteDir.append('\\' + str(e.get_longname())) 451 | else: 452 | files.append(str(e.get_longname())) 453 | all = sorted(remoteDir) 454 | for file in sorted(files): 455 | all.append('{}'.format(file)) 456 | return all 457 | else: 458 | self.pwd = '' 459 | return [] 460 | 461 | #e.get_filesize() 462 | #time.ctime(float(e.get_mtime_epoch())) 463 | 464 | SMBclient() 465 | --------------------------------------------------------------------------------