|
| 1 | +# ftp_client.py |
| 2 | +import os |
| 3 | +import wx |
| 4 | +from ftplib import FTP as ftplib_FTP, error_perm |
| 5 | +from pubsub import pub |
| 6 | + |
| 7 | +def send_status(message, topic='update_status'): |
| 8 | + """Durum güncellemelerini yayınlar.""" |
| 9 | + wx.CallAfter(pub.sendMessage, topic, message=message) |
| 10 | + |
| 11 | +class Path: |
| 12 | + """FTP sunucusundaki dosya veya dizinler için bir yol nesnesi.""" |
| 13 | + def __init__(self, ftype, size, filename, date): |
| 14 | + self.folder = 'd' in ftype |
| 15 | + self.size = size |
| 16 | + self.filename = filename |
| 17 | + self.last_modified = date |
| 18 | +class FTP: |
| 19 | + """FTP bağlantısını yöneten sınıf.""" |
| 20 | + |
| 21 | + def __init__(self, folder=None): |
| 22 | + self.folder = folder |
| 23 | + self.ftp = None |
| 24 | + |
| 25 | + def connect(self, host, port, username, password): |
| 26 | + """FTP sunucusuna bağlanır.""" |
| 27 | + try: |
| 28 | + self.ftp = ftplib_FTP() |
| 29 | + self.ftp.connect(host, port) |
| 30 | + self.ftp.login(username, password) |
| 31 | + welcome_message = "Connected to FTP server" |
| 32 | + send_status(welcome_message) |
| 33 | + send_status('Connected to server wthiout any errors.', topic='update_statusbar') |
| 34 | + self.get_dir_listing() |
| 35 | + except error_perm as e: |
| 36 | + send_status(f'Permission error: {e}', topic='update_statusbar') |
| 37 | + |
| 38 | + except Exception as e: |
| 39 | + if str(e).startswith('[Errno 11001]'): |
| 40 | + send_status(f'Disconnected: {str(e)}. Please check the hostname or IP address.', topic='update_statusbar') |
| 41 | + else: |
| 42 | + send_status(f'Disconnected: {str(e)}', topic='update_statusbar') |
| 43 | + |
| 44 | + |
| 45 | + def disconnect(self): |
| 46 | + """FTP sunucusundan bağlantıyı keser.""" |
| 47 | + if self.ftp: |
| 48 | + try: |
| 49 | + goodbye_message = "Disconnected from FTP server" |
| 50 | + send_status(goodbye_message) |
| 51 | + self.ftp.quit() |
| 52 | + send_status('Disconnected from server without any errors.', topic='update_statusbar') |
| 53 | + except Exception as e: |
| 54 | + send_status(f'Error during disconnect: {str(e)}', topic='update_statusbar') |
| 55 | + |
| 56 | + def change_directory(self, folder): |
| 57 | + """Sunucu üzerindeki dizini değiştirir.""" |
| 58 | + try: |
| 59 | + self.ftp.cwd(folder) |
| 60 | + self.get_dir_listing() |
| 61 | + current_directory = self.ftp.pwd() |
| 62 | + send_status(f'Changed directory to {current_directory}') |
| 63 | + except Exception as e: |
| 64 | + send_status(f'Error changing directory: {str(e)}') |
| 65 | + |
| 66 | + def prev_directory(self): |
| 67 | + try: |
| 68 | + self.ftp.cwd('..') |
| 69 | + self.get_dir_listing() |
| 70 | + current_directory = self.ftp.pwd() |
| 71 | + send_status(f'Changed directory to {current_directory}') |
| 72 | + except Exception as e: |
| 73 | + send_status(f'Error changing to previous directory: {str(e)}') |
| 74 | + def get_dir_listing(self): |
| 75 | + """Dizin listesini alır.""" |
| 76 | + if self.ftp: |
| 77 | + data = [] |
| 78 | + self.ftp.dir(data.append) |
| 79 | + self.parse_data(data) |
| 80 | + else: |
| 81 | + data = [] |
| 82 | + |
| 83 | + def parse_data(self, data): |
| 84 | + """Dizin verilerini analiz eder.""" |
| 85 | + paths = [] |
| 86 | + for item in data: |
| 87 | + parts = item.split() |
| 88 | + ftype = parts[0] |
| 89 | + size = int(int(parts[4])/1024) |
| 90 | + if size == 0: |
| 91 | + size = "0 KB" |
| 92 | + else: |
| 93 | + size = str(size).__add__(" KB") |
| 94 | + if len(parts) > 9: |
| 95 | + filename = ' '.join(parts[8:]) |
| 96 | + else: |
| 97 | + filename = parts[8] |
| 98 | + date = '{month} {day} {t}'.format( |
| 99 | + month=parts[5], day=parts[6], t=parts[7]) |
| 100 | + if filename == '.': |
| 101 | + continue |
| 102 | + paths.append(Path(ftype, size, filename, date)) |
| 103 | + |
| 104 | + wx.CallAfter(pub.sendMessage, 'update', paths=paths) |
| 105 | + |
| 106 | + def delete_file(self, filename): |
| 107 | + """Dosyayı siler.""" |
| 108 | + try: |
| 109 | + self.ftp.delete(filename) |
| 110 | + send_status(f'{filename} deleted successfully') |
| 111 | + self.get_dir_listing() |
| 112 | + except Exception as e: |
| 113 | + send_status(f'Unable to delete {filename}: {str(e)}') |
| 114 | + |
| 115 | + def rename(self, from_name, to_name): |
| 116 | + """Sunucudaki dosya veya dizini yeniden adlandırır.""" |
| 117 | + try: |
| 118 | + self.ftp.rename(from_name, to_name) |
| 119 | + send_status(f'{from_name} renamed to {to_name}') |
| 120 | + self.get_dir_listing() |
| 121 | + except Exception as e: |
| 122 | + send_status(f'Error renaming {from_name} to {to_name}: {str(e)}') |
| 123 | + |
| 124 | + def download_files(self, paths, local_folder): |
| 125 | + """Dosyaları indirir.""" |
| 126 | + for path in paths: |
| 127 | + try: |
| 128 | + full_path = os.path.join(local_folder, os.path.basename(path)) |
| 129 | + with open(full_path, 'wb') as local_file: |
| 130 | + self.ftp.retrbinary(f'RETR {path}', local_file.write) |
| 131 | + send_status(f'Downloaded: {path}') |
| 132 | + except Exception as e: |
| 133 | + send_status(f'Error downloading {path}: {str(e)}') |
| 134 | + |
| 135 | + |
| 136 | + def upload_files(self, local_path, remote_path): |
| 137 | + """Dosyayı FTP sunucusuna yükler.""" |
| 138 | + try: |
| 139 | + with open(local_path, 'rb') as file: |
| 140 | + self.ftp.storbinary(f'STOR {remote_path}', file) |
| 141 | + send_status(f"Uploaded {local_path} successfully.") |
| 142 | + self.get_dir_listing() |
| 143 | + except Exception as e: |
| 144 | + send_status(f"Failed to upload {local_path}: {str(e)}") |
| 145 | + |
| 146 | + def copy_file(self, src, dst): |
| 147 | + """Sunucuda dosyayı bir konumdan diğerine kopyalar.""" |
| 148 | + try: |
| 149 | + with open('tempfile', 'wb') as f: |
| 150 | + self.ftp.retrbinary(f'RETR {src}', f.write) |
| 151 | + with open('tempfile', 'rb') as f: |
| 152 | + self.ftp.storbinary(f'STOR {dst}', f) |
| 153 | + os.remove('tempfile') |
| 154 | + send_status(f'File copied from {src} to {dst}') |
| 155 | + self.get_dir_listing() |
| 156 | + except Exception as e: |
| 157 | + send_status(f'Error copying file from {src} to {dst}: {str(e)}') |
| 158 | + |
| 159 | + def copy_folder(self, src, dst): |
| 160 | + """Sunucuda klasörü bir konumdan diğerine kopyalar.""" |
| 161 | + try: |
| 162 | + if not self.path_exists(dst): |
| 163 | + self.ftp.mkd(dst) |
| 164 | + for item in self.ftp.nlst(src): |
| 165 | + item_name = os.path.basename(item) |
| 166 | + src_item = os.path.join(src, item_name) |
| 167 | + dst_item = os.path.join(dst, item_name) |
| 168 | + if self.is_directory(src_item): |
| 169 | + self.copy_folder(src_item, dst_item) |
| 170 | + else: |
| 171 | + self.copy_file(src_item, dst_item) |
| 172 | + send_status(f'Folder copied from {src} to {dst}') |
| 173 | + except Exception as e: |
| 174 | + send_status(f'Error copying folder from {src} to {dst}: {str(e)}') |
0 commit comments