1
0
forked from crony/UpFast

Add the upload only option.

This commit is contained in:
CronyAkatsuki 2023-11-01 16:32:47 +01:00
parent 47ac321d62
commit d85637afcb
4 changed files with 103 additions and 50 deletions

46
main.py
View File

@ -6,6 +6,14 @@ from fastapi import FastAPI, Request, UploadFile, File, Header
from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse from fastapi.responses import HTMLResponse, PlainTextResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from pydantic_settings import BaseSettings, SettingsConfigDict
# Settings
class Settings(BaseSettings):
upload_only: bool = True
model_config = SettingsConfigDict(env_file=".env")
# file class # file class
@ -43,6 +51,8 @@ def file_list_generator(path: str, file_list: list[str]):
templates = Jinja2Templates(directory="templates") templates = Jinja2Templates(directory="templates")
# Create settings
settings = Settings()
# Create fastapi template # Create fastapi template
app = FastAPI() app = FastAPI()
@ -63,7 +73,11 @@ async def index(
if re.search("^curl/.*", str(user_agent)): if re.search("^curl/.*", str(user_agent)):
return PlainTextResponse("It fucking works!\n") return PlainTextResponse("It fucking works!\n")
else: else:
context = {"request": request, "user_agent": user_agent} context = {
"request": request,
"user_agent": user_agent,
"upload_only": settings.upload_only,
}
return templates.TemplateResponse("index.html", context) return templates.TemplateResponse("index.html", context)
@ -98,12 +112,12 @@ async def files(
path = f"{dirname(abspath(__file__))}/upload/" path = f"{dirname(abspath(__file__))}/upload/"
file_list = listdir(path) file_list = listdir(path)
files = file_list_generator(path, file_list) files = file_list_generator(path, file_list)
context = {"request": request, "files": files} context = {"request": request, "files": files, "upload_only": settings.upload_only}
if re.search("^curl/.*", str(user_agent)): if re.search("^curl/.*", str(user_agent)):
context = "" response = ""
for file in files: for file in files:
context += f"{request.url._url}/{file.name}\n" response += f"{request.url._url}/{file.name}\n"
return PlainTextResponse(f"{context}") return PlainTextResponse(f"{response}")
else: else:
return templates.TemplateResponse("files.html", context) return templates.TemplateResponse("files.html", context)
@ -115,14 +129,20 @@ async def delete(
file: str, file: str,
user_agent: Annotated[Union[str, None], Header()] = None, user_agent: Annotated[Union[str, None], Header()] = None,
): ):
file_path = f"{dirname(abspath(__file__))}/upload/{file}" if settings.upload_only:
if exists(file_path): return PlainTextResponse(
remove(file_path) "This api endpoint is not available on upload only instance. \
If you wan't to delete a file ask the hoster of the instance!!"
)
else:
file_path = f"{dirname(abspath(__file__))}/upload/{file}"
if exists(file_path):
remove(file_path)
if re.search("^curl/.*", str(user_agent)):
return PlainTextResponse(f"file {file} deleted from the server\n")
else:
return RedirectResponse(request.url_for("files"))
if re.search("^curl/.*", str(user_agent)): if re.search("^curl/.*", str(user_agent)):
return PlainTextResponse(f"file {file} deleted from the server\n") return PlainTextResponse(f"file {file} doesn't exist on the server\n")
else: else:
return RedirectResponse(request.url_for("files")) return RedirectResponse(request.url_for("files"))
if re.search("^curl/.*", str(user_agent)):
return PlainTextResponse(f"file {file} doesn't exist on the server\n")
else:
return RedirectResponse(request.url_for("files"))

View File

@ -7,7 +7,9 @@ idna==3.4
Jinja2==3.1.2 Jinja2==3.1.2
MarkupSafe==2.1.3 MarkupSafe==2.1.3
pydantic==2.4.2 pydantic==2.4.2
pydantic-settings==2.0.3
pydantic_core==2.10.1 pydantic_core==2.10.1
python-dotenv==1.0.0
python-magic==0.4.27 python-magic==0.4.27
python-multipart==0.0.6 python-multipart==0.0.6
sniffio==1.3.0 sniffio==1.3.0

View File

@ -1,31 +1,35 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="{{ url_for('static', path='/css/files.css') }}" rel="stylesheet"> <link href="{{ url_for('static', path='/css/files.css') }}" rel="stylesheet" />
<title>UpFast: File List</title> <title>UpFast: File List</title>
</head> </head>
<body> <body>
<h1>File List</h1> <h1>File List</h1>
{% for file in files %}
<hr>
<div class="file">
{% if file.fileType == "image" %}
<img src="/files/{{ file.name }}">
{% elif file.fileType == "video" %}
<video controls src="/files/{{ file.name }}"></video>
{% elif file.fileType == "text" %}
<pre>{{ file.content }}</pre>
{% endif %}
<div class="info">
<a href="/files/{{ file.name }}" download>{{ file.name }}</a>
<a href="/delete/{{ file.name }}" onclick="return confirm('Are you sure?')">delete!</a>
</div>
</div>
{% endfor %}
{% for file in files %}
<hr />
<div class="file">
{% if file.fileType == "image" %}
<img src="/files/{{ file.name }}" />
{% elif file.fileType == "video" %}
<video controls src="/files/{{ file.name }}"></video>
{% elif file.fileType == "text" %}
<pre>{{ file.content }}</pre>
{% endif %}
<div class="info">
<a href="/files/{{ file.name }}" download>{{ file.name }}</a>
{% if not upload_only %}
<a href="/delete/{{ file.name }}" onclick="return confirm('Are you sure?')">delete!</a>
{% endif %}
</div>
</div>
{% endfor %}
</body> </body>
</html> </html>

View File

@ -1,26 +1,53 @@
<!DOCTYPE html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="{{ url_for('static', path='/css/style.css') }}" rel="stylesheet"> <link href="{{ url_for('static', path='/css/style.css') }}" rel="stylesheet" />
<title>UpFast</title> <title>UpFast</title>
</head> </head>
<body> <body>
<h1>UpFast: Minimal file upload and sharing tool</h1> <h1>UpFast: Minimal file upload and sharing tool</h1>
<p><a href="https://0x0.st">0x0.st</a> Influenced file upload and sharing tool</p> <p>
<a href="https://0x0.st">0x0.st</a> Influenced file upload and sharing
tool
</p>
<p>To upload files use curl: <code>curl -F "file=@/path/to/file" "{{ request.url }}"</code></p> <p>
To upload files use curl:
<code>curl -F "file=@/path/to/file" "{{ request.url }}"</code>
</p>
<p>To delete a file using curl: <code>curl "{{ request.url }}delete/file_name"</code></p> <p>
To delete a file using curl:
<code>curl "{{ request.url }}delete/file_name"</code>
</p>
<p>To get of all files hosted on the instance check <a href="/files">files</a></p> {% if upload_only %}
<p>
NOTE: This is an upload only instance, if you wan't a file on the instance
deleted ask the hoster to delete the file.
</p>
{% endif %}
<p>Created and maintained by <a href="https://cronyakatsuki.xyz">Crony Akatsuki</a></p> <p>
To get of all files hosted on the instance check
<a href="/files">files</a>
</p>
<p>Code is hosted on <a href="https://code.cronyakatsuki.xyz/crony/upfast">https://code.cronyakatsuki.xyz/crony/upfast</a></p> <p>
Created and maintained by
<a href="https://cronyakatsuki.xyz">Crony Akatsuki</a>
</p>
<p>
Code is hosted on
<a href="https://code.cronyakatsuki.xyz/crony/upfast">https://code.cronyakatsuki.xyz/crony/upfast</a>
</p>
</body> </body>
</html> </html>