1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
import socket
from time import sleep
import struct
import json
import shelve
try:
from tqdm import tqdm
TQDM = True
except ImportError:
print('Для вывода прогресса загрузки файлов установите библиотеку tqdm')
TQDM = False
def pack_data(data):
encoded = data.encode()
return struct.pack('I', len(encoded)) + encoded
def handle_input(data):
cmd, args = data.split(' ', maxsplit=1)
if cmd == 'get':
make_get_request(args)
elif cmd == 'cp':
paths = args.split()
if len(paths) != 2:
raise ValueError('Неверное количество путей в параметрах.')
src, dest = paths
# Если файл не присутствует в БД, то предварительно его загружаем
status = 0
if src not in db:
status = make_get_request(src)
if status == 0:
with open(dest, 'wb') as f:
f.write(db[src])
else:
raise ValueError('Команда не распознана')
def make_get_request(path):
packet = pack_data(json.dumps({'method': 'get', 'path': path}))
sock.sendall(packet)
response = get_response()
return handle_response(response)
def parse_response(data):
return json.loads(data.decode())
def get_response():
buffer = b''
while len(buffer) < DATATYPE_SIZE:
data = sock.recv(DATATYPE_SIZE - len(buffer))
if not data:
raise ConnectionError('Connection was closed')
buffer += data
size_packed, buffer = buffer[:DATATYPE_SIZE], buffer[DATATYPE_SIZE:]
if not size_packed:
raise ConnectionError('Connection was closed')
(size,) = struct.unpack('I', size_packed)
data = sock.recv(size - len(buffer))
return parse_response(buffer + data)
def download_file(filesize):
data = b''
if TQDM:
for count in tqdm(range(0, filesize, CHUNK_SIZE)):
(size,) = struct.unpack('I', sock.recv(DATATYPE_SIZE))
data += sock.recv(size)
else:
count = 0
while count < filesize:
(size,) = struct.unpack('I', sock.recv(DATATYPE_SIZE))
data += sock.recv(size)
count += size
return data
def handle_response(data):
if data['status'] == 0:
print(f'Загружаем файл размером {data["size"]} байт...')
file_data = download_file(data['size'])
db[data['path']] = file_data
print('Загрузка завершена')
elif data['status'] == 1:
print(data['reason'])
elif data['status'] == 2:
print('Неизвестная ошибка:')
print(data['reason'])
return data['status']
def try_connect():
cnt = 0
sock = socket.socket()
while cnt < 10:
try:
cnt += 1
sock.connect(ADDR)
except ConnectionRefusedError:
print('Не удалось подключиться к серверу. Следующая попытка через 3 секунды...')
sleep(3)
else:
return sock
else:
print('Не удалось подключиться к серверу через 10 попыток.\nОстанавливаемся...')
sock.close()
return
HOST, PORT = ADDR = 'localhost', 6000
DATATYPE_SIZE = 4 # int
CHUNK_SIZE = 4096000
sock = try_connect()
if sock is None:
quit()
db = shelve.open('backdoor.db')
while True:
try:
data = input('Введите команду:\n')
handle_input(data)
except KeyboardInterrupt:
break
sock.close()
|