2023-12-14 12:39:23 +01:00
|
|
|
from config import disallowedMimeTypes, Errors, Config
|
2023-12-26 20:16:58 +01:00
|
|
|
from app.models import User
|
|
|
|
from app import bcrypt
|
2023-12-14 12:39:23 +01:00
|
|
|
import secrets
|
|
|
|
import datetime
|
|
|
|
import random
|
2024-01-28 11:27:26 +01:00
|
|
|
import magic
|
2023-12-14 12:39:23 +01:00
|
|
|
import os
|
|
|
|
|
|
|
|
def uploadFile(file, ip, userid, filename, id, retention):
|
|
|
|
|
|
|
|
# Is the MIME and file size good?
|
2024-01-28 11:38:04 +01:00
|
|
|
file_content = file.read()
|
|
|
|
if magic.from_buffer(file_content, mime=True) not in disallowedMimeTypes:
|
2023-12-14 12:39:23 +01:00
|
|
|
if file.content_length <= Config.maxFileSize:
|
|
|
|
# We're going to check whether the id variable has been filled
|
|
|
|
|
|
|
|
while True: # Loop to find an available file ID
|
|
|
|
id = randomHex() # Prevent conflicts if 2 of the same get made
|
|
|
|
if Config.files.find_one({'id': id}) is None:
|
2023-12-29 20:47:28 +01:00
|
|
|
filename=id
|
2023-12-14 12:39:23 +01:00
|
|
|
break
|
|
|
|
|
|
|
|
if userid == None:
|
|
|
|
userid = 0
|
|
|
|
elif Config.users.find_one({'userid': userid}) == None:
|
|
|
|
userid = 0
|
|
|
|
|
|
|
|
# Calculate retention before the file is written, we'll grab the filesize here as it's needed for the equation.
|
2024-01-03 09:51:31 +01:00
|
|
|
file.seek(0, os.SEEK_END)
|
2024-01-05 12:17:46 +01:00
|
|
|
fileSize = round(float(file.tell()) / (1024 * 1024), 2)
|
2024-01-04 19:58:42 +01:00
|
|
|
|
|
|
|
# Set the position back to 0
|
|
|
|
file.seek(0)
|
2023-12-14 12:39:23 +01:00
|
|
|
|
|
|
|
if retention == None:
|
|
|
|
retention = (Config.minretention+(-Config.maxretention + Config.minretention)*pow((fileSize / Config.maxFileSize -1), 3))
|
|
|
|
elif retention > (Config.minretention+(-Config.maxretention + Config.minretention)*pow((fileSize / Config.maxFileSize -1), 3)):
|
|
|
|
retention = (Config.minretention+(-Config.maxretention + Config.minretention)*pow((fileSize / Config.maxFileSize -1), 3))
|
2023-12-29 20:47:28 +01:00
|
|
|
else:
|
|
|
|
retention = retention
|
2023-12-14 12:39:23 +01:00
|
|
|
|
2023-12-21 17:19:22 +01:00
|
|
|
|
2023-12-14 12:39:23 +01:00
|
|
|
# Create the file
|
|
|
|
with open(f"{os.path.abspath(Config.fileDir)}/{filename}", "wb") as f:
|
|
|
|
f.write(file.read())
|
|
|
|
|
2024-01-05 15:18:55 +01:00
|
|
|
timestamp = datetime.datetime.now()
|
|
|
|
timestamp = timestamp.timestamp()
|
2023-12-14 12:39:23 +01:00
|
|
|
|
|
|
|
# Create the dictionary that we'll insert into the db
|
|
|
|
data = {
|
|
|
|
'id': id,
|
|
|
|
'filename': filename,
|
|
|
|
'filesize': fileSize,
|
2024-01-28 11:38:04 +01:00
|
|
|
'mimetype': magic.from_buffer(file_content, mime=True) if magic.from_buffer(file_content, mime=True) != None else "text/plain",
|
2024-01-05 12:17:46 +01:00
|
|
|
'retention': retention,
|
2023-12-14 12:39:23 +01:00
|
|
|
'userid': userid,
|
|
|
|
'ip': ip,
|
2024-01-05 15:18:55 +01:00
|
|
|
'date': timestamp,
|
|
|
|
'expiry': timestamp + retention
|
2023-12-14 12:39:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
# Add the data and verify its there.
|
|
|
|
Config.files.insert_one(data)
|
|
|
|
print(Config.files.find_one({"id": id}))
|
|
|
|
|
2024-01-04 19:58:42 +01:00
|
|
|
return f"https://xygt.cc/{id}", 200
|
2023-12-14 12:39:23 +01:00
|
|
|
else:
|
|
|
|
return random.choice(Errors.fileTooLarge), 400
|
|
|
|
else:
|
|
|
|
return random.choice(Errors.fileTypeNotAllowed), 400
|
|
|
|
|
|
|
|
def shortenURL(url, ip, userid, id, retention):
|
|
|
|
# We're going to check whether the id variable has been filled
|
|
|
|
# If not then we'll generate one. (The ID variable will be the same as the filename if not rejected earlier.)
|
|
|
|
if id == None:
|
|
|
|
while True: # Loop to find an available file ID
|
|
|
|
id = randomHex() # Prevent conflicts if 2 of the same get made
|
|
|
|
if Config.files.find_one({'id': id}) is None:
|
|
|
|
break
|
|
|
|
|
|
|
|
if userid == None:
|
|
|
|
userid = 0
|
|
|
|
elif Config.users.find_one({'userid': userid}) == None:
|
|
|
|
userid = 0
|
|
|
|
|
|
|
|
if retention == None:
|
2024-01-05 12:17:46 +01:00
|
|
|
retention = 604800
|
|
|
|
elif retention > 31540000:
|
|
|
|
retention = 31540000
|
2024-01-05 15:18:55 +01:00
|
|
|
|
|
|
|
timestamp = datetime.datetime.now()
|
|
|
|
timestamp = timestamp.timestamp()
|
|
|
|
|
2023-12-14 12:39:23 +01:00
|
|
|
data = {
|
2024-01-05 15:18:55 +01:00
|
|
|
'id': id,
|
|
|
|
'url': url,
|
|
|
|
'retention': retention,
|
|
|
|
'userid': userid,
|
|
|
|
'ip': ip,
|
|
|
|
'date': timestamp,
|
|
|
|
'expiry': timestamp + retention
|
2023-12-14 12:39:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Config.url.insert_one(data)
|
|
|
|
print(Config.url.find_one({"id": data["id"]}))
|
|
|
|
|
2024-01-04 19:58:42 +01:00
|
|
|
return f"https://xygt.cc/{id}", 200
|
2023-12-14 12:39:23 +01:00
|
|
|
|
|
|
|
def idInfo(id):
|
|
|
|
# Check files and url for the ID
|
|
|
|
if Config.files.find_one({"id": id}) is not None:
|
2023-12-22 22:16:10 +01:00
|
|
|
check = Config.files.find_one({"id": id}, {'_id': False, "ip": False})
|
2023-12-14 12:39:23 +01:00
|
|
|
# "ip": False removes the IP from the returned data.
|
|
|
|
# If it's not there then check url
|
|
|
|
elif Config.url.find_one({"id": id}) is not None:
|
2023-12-22 22:16:10 +01:00
|
|
|
check = Config.url.find_one({"id": id}, {'_id': False, "ip": False})
|
2023-12-14 12:39:23 +01:00
|
|
|
|
2024-02-26 20:59:36 +01:00
|
|
|
else:
|
|
|
|
check = {"Error": "File Not Found"}
|
|
|
|
|
|
|
|
# Return the mongodb info about the file
|
2023-12-14 12:39:23 +01:00
|
|
|
return check
|
|
|
|
|
2024-02-26 20:59:36 +01:00
|
|
|
def userInfo(id):
|
|
|
|
# Grab user entry from userID
|
|
|
|
user = Config.users.find_one({"userid": id})
|
|
|
|
|
|
|
|
username = user['username']
|
|
|
|
userid = id
|
|
|
|
|
|
|
|
# Search for all files from that userID
|
|
|
|
files = Config.files.find({"userid": userid}, {"_id": False, "ip": False})
|
|
|
|
list = {}
|
|
|
|
|
|
|
|
# Create file listing
|
|
|
|
for file in files:
|
|
|
|
list.update({
|
|
|
|
file["id"]: {
|
|
|
|
"filename": file["filename"],
|
|
|
|
"mimetype": file["mimetype"],
|
|
|
|
"filesize": file["filesize"],
|
|
|
|
"retention": file["retention"],
|
|
|
|
"creation": file["date"],
|
|
|
|
"expiry": file["expiry"]
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
# Search for all URL's from that userID
|
|
|
|
url = Config.url.find({"userid": userid})
|
|
|
|
|
|
|
|
# Format all into one JSON
|
|
|
|
return {
|
|
|
|
"user": {
|
|
|
|
"username": username,
|
|
|
|
"userid": userid
|
|
|
|
},
|
|
|
|
"files": {
|
|
|
|
"count": len(files),
|
|
|
|
"list": list
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-14 12:39:23 +01:00
|
|
|
def randomHex():
|
|
|
|
hexRand = ''.join(secrets.choice('0123456789abcdef') for _ in range(6))
|
|
|
|
return hexRand
|
2023-12-26 20:16:58 +01:00
|
|
|
|
2024-01-05 12:17:46 +01:00
|
|
|
def genIDPass():
|
|
|
|
idpass = ''.join(secrets.choice('0123456789abcdef') for _ in range(16))
|
|
|
|
return idpass
|
|
|
|
|
2023-12-26 20:16:58 +01:00
|
|
|
def registerUser(username, password):
|
|
|
|
# Initialise some values
|
|
|
|
try:
|
|
|
|
level = 1
|
2024-01-04 19:58:42 +01:00
|
|
|
while True:
|
|
|
|
userid = randomHex()
|
|
|
|
if Config.users.find_one({"userid": userid}) is None:
|
|
|
|
break
|
|
|
|
idpass = bcrypt.generate_password_hash(randomHex()).decode("utf-8") # The user will not know this, they'll need to generate a new one.
|
2023-12-26 20:16:58 +01:00
|
|
|
password = bcrypt.generate_password_hash(password).decode("utf-8")
|
|
|
|
user = User(username, userid, password, idpass, level)
|
|
|
|
Config.users.insert_one(user.__dict__)
|
|
|
|
|
|
|
|
return True
|
2024-01-04 19:58:42 +01:00
|
|
|
except:
|
|
|
|
return False
|
|
|
|
|
|
|
|
def resetIDPass(userid):
|
|
|
|
try:
|
2024-01-05 12:17:46 +01:00
|
|
|
idpass = genIDPass()
|
2024-01-04 19:58:42 +01:00
|
|
|
hashedPass = bcrypt.generate_password_hash(idpass).decode("utf-8")
|
|
|
|
Config.users.update_one({"userid": userid}, {"$set": {"idpass": hashedPass}})
|
|
|
|
return idpass
|
2023-12-26 20:16:58 +01:00
|
|
|
except:
|
2024-02-26 20:59:36 +01:00
|
|
|
return False
|