110 lines
3.7 KiB
Python
110 lines
3.7 KiB
Python
|
'''
|
||
|
HTTP storage server - server for storing files.
|
||
|
Copyright (C) 2023 Dymik739
|
||
|
Email: user@109.86.70.81
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
'''
|
||
|
|
||
|
import socket
|
||
|
import datetime
|
||
|
import os
|
||
|
|
||
|
# storage setup
|
||
|
if not os.path.exists("storage/"):
|
||
|
os.mkdir("storage/")
|
||
|
|
||
|
|
||
|
# constant definitions
|
||
|
UNDEFINED_LENGTH = -1
|
||
|
|
||
|
|
||
|
# function definitions
|
||
|
def get_filename_from_type(file_type, file_id):
|
||
|
pass
|
||
|
|
||
|
|
||
|
# main code
|
||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||
|
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||
|
s.bind(('', 5555))
|
||
|
s.listen(1000)
|
||
|
|
||
|
while True:
|
||
|
conn, addr = s.accept()
|
||
|
conn.settimeout(15)
|
||
|
|
||
|
print(f"Received connection from {addr[0]}:{addr[1]}")
|
||
|
|
||
|
left_to_read = UNDEFINED_LENGTH
|
||
|
last_read_length = 0
|
||
|
data_buffer = bytes()
|
||
|
|
||
|
request_head = {"method": None, "path": None, "headers": {}}
|
||
|
request_body = bytes()
|
||
|
|
||
|
initial_header_processed = False
|
||
|
reading_headers = True
|
||
|
|
||
|
while left_to_read:
|
||
|
if left_to_read == UNDEFINED_LENGTH:
|
||
|
data_buffer += conn.recv(1024)
|
||
|
else:
|
||
|
data_buffer += conn.recv(left_to_read)
|
||
|
|
||
|
raw_headers = data_buffer.split("\r\n".encode("UTF-8"))
|
||
|
|
||
|
if reading_headers:
|
||
|
for item in raw_headers[:-1]:
|
||
|
data_buffer = data_buffer[len(item) + 2:]
|
||
|
i = item.decode("UTF-8", errors = "ignore")
|
||
|
|
||
|
if i == "":
|
||
|
reading_headers = False
|
||
|
left_to_read = int(request_head['headers']['content-length'])
|
||
|
print("Switch!")
|
||
|
break
|
||
|
|
||
|
if initial_header_processed:
|
||
|
print(i, f"len = {len(i)}")
|
||
|
header = i.split(": ")
|
||
|
request_head['headers'].update({header[0].lower(): header[1]})
|
||
|
else:
|
||
|
header = i.split(" ")
|
||
|
request_head['method'] = i[0]
|
||
|
request_head['path'] = i[1]
|
||
|
|
||
|
initial_header_processed = True
|
||
|
else:
|
||
|
left_to_read -= len(data_buffer)
|
||
|
request_body += data_buffer
|
||
|
print(data_buffer)
|
||
|
data_buffer = bytes()
|
||
|
|
||
|
|
||
|
raw_items = request_body.split(("--" + request_head['headers']['content-type'].split("; ")[1].split("=")[1]).encode("UTF-8"))
|
||
|
|
||
|
new_folder = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||
|
os.mkdir(f"storage/{new_folder}/")
|
||
|
|
||
|
for number, raw_i in enumerate(raw_items):
|
||
|
print("New file")
|
||
|
split_item = raw_i.split("\r\n\r\n".encode("UTF-8"))
|
||
|
|
||
|
if len(split_item) < 2:
|
||
|
continue
|
||
|
|
||
|
current_headers = {k.lower(): v for (k, v) in [x.split(": ") for x in split_item[0].decode("UTF-8").split("\r\n") if x != ""]}
|
||
|
|
||
|
if "content-disposition" in current_headers and "upload" in current_headers["content-disposition"]:
|
||
|
filename = dict([x.split("=") for x in current_headers["content-disposition"].split("; ") if "=" in x])["filename"][1:-1]
|
||
|
#filename = get_filename_from_type(current_headers["content-type"])
|
||
|
with open(f"storage/{new_folder}/{filename}", "wb") as f:
|
||
|
f.write(split_item[1])
|
||
|
|
||
|
conn.close()
|