commit 3e72ecab2043b4ef5f58f23aa7cfe505c2b3e4c7 Author: retoor Date: Tue Nov 26 04:34:46 2024 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..64daf34 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.history +.venv +src/upload/__pycache__ \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..15dd724 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +all: ensure_env build serve + +ensure_env: + -@python3 -m venv .venv + +build: + ./.venv/bin/python -m pip install build + ./.venv/bin/python -m build . + ./.venv/bin/python -m pip install -e . + +serve: + ./.venv/bin/rupload.serve diff --git a/README.md b/README.md new file mode 100644 index 0000000..0cb4672 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# RUpload + +## About +Easiest way to upload files to a server. + +Since it doesn't have captcha or whatsoever, it's only usable with people you trust on a not listed domain. It's destined for public use, as long the domain isn't listed in a search engine. It has a limitation for file size, so it would never go terribly wrong. + +## Installation +``` +python3 -m venv .venv +./venv/bin/python -m pip install . +``` + +## Usage +``` +rupload.serve [host(127.0.0.1)] [port] [destination path for uploads] [max file size in bytes] +``` diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..07de284 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..8a83c01 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,25 @@ +[metadata] +name = rupload +version = 1.3.37 +description = upload tool +author = Retoor +author_email = retoor@molodetz.nl +license = MIT +long_description = file: README.md +long_description_content_type = text/markdown + +[options] +packages = find: +package_dir = + = src +python_requires = >=3.7 +install_requires = + aiohttp==3.10.10 + dataset==1.6.2 + +[options.packages.find] +where = src + +[options.entry_points] +console_scripts = + rupload.serve = rupload.cli:main diff --git a/src/rupload.egg-info/PKG-INFO b/src/rupload.egg-info/PKG-INFO new file mode 100644 index 0000000..193d726 --- /dev/null +++ b/src/rupload.egg-info/PKG-INFO @@ -0,0 +1,29 @@ +Metadata-Version: 2.1 +Name: rupload +Version: 1.3.37 +Summary: upload tool +Author: Retoor +Author-email: retoor@molodetz.nl +License: MIT +Requires-Python: >=3.7 +Description-Content-Type: text/markdown +Requires-Dist: aiohttp==3.10.10 +Requires-Dist: dataset==1.6.2 + +# RUpload + +## About +Easiest way to upload files to a server. + +Since it doesn't have captcha or whatsoever, it's only usable with people you trust on a not listed domain. It's destined for public use, as long the domain isn't listed in a search engine. It has a limitation for file size, so it would never go terribly wrong. + +## Installation +``` +python3 -m venv .venv +./venv/bin/python -m pip install . +``` + +## Usage +``` +rupload.serve [host(127.0.0.1)] [port] [destination path for uploads] [max file size in bytes] +``` diff --git a/src/rupload.egg-info/SOURCES.txt b/src/rupload.egg-info/SOURCES.txt new file mode 100644 index 0000000..386b9fa --- /dev/null +++ b/src/rupload.egg-info/SOURCES.txt @@ -0,0 +1,13 @@ +README.md +pyproject.toml +setup.cfg +src/rupload/__init__.py +src/rupload/__main__.py +src/rupload/app.py +src/rupload/cli.py +src/rupload.egg-info/PKG-INFO +src/rupload.egg-info/SOURCES.txt +src/rupload.egg-info/dependency_links.txt +src/rupload.egg-info/entry_points.txt +src/rupload.egg-info/requires.txt +src/rupload.egg-info/top_level.txt \ No newline at end of file diff --git a/src/rupload.egg-info/dependency_links.txt b/src/rupload.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/rupload.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/src/rupload.egg-info/entry_points.txt b/src/rupload.egg-info/entry_points.txt new file mode 100644 index 0000000..d115e42 --- /dev/null +++ b/src/rupload.egg-info/entry_points.txt @@ -0,0 +1,2 @@ +[console_scripts] +rupload.serve = rupload.cli:main diff --git a/src/rupload.egg-info/requires.txt b/src/rupload.egg-info/requires.txt new file mode 100644 index 0000000..15b74db --- /dev/null +++ b/src/rupload.egg-info/requires.txt @@ -0,0 +1,2 @@ +aiohttp==3.10.10 +dataset==1.6.2 diff --git a/src/rupload.egg-info/top_level.txt b/src/rupload.egg-info/top_level.txt new file mode 100644 index 0000000..3c7c411 --- /dev/null +++ b/src/rupload.egg-info/top_level.txt @@ -0,0 +1 @@ +rupload diff --git a/src/rupload/__init__.py b/src/rupload/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/rupload/__main__.py b/src/rupload/__main__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/rupload/__pycache__/__init__.cpython-312.pyc b/src/rupload/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..b40f013 Binary files /dev/null and b/src/rupload/__pycache__/__init__.cpython-312.pyc differ diff --git a/src/rupload/__pycache__/app.cpython-312.pyc b/src/rupload/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000..e8b797e Binary files /dev/null and b/src/rupload/__pycache__/app.cpython-312.pyc differ diff --git a/src/rupload/__pycache__/cli.cpython-312.pyc b/src/rupload/__pycache__/cli.cpython-312.pyc new file mode 100644 index 0000000..a87e8c1 Binary files /dev/null and b/src/rupload/__pycache__/cli.cpython-312.pyc differ diff --git a/src/rupload/app.py b/src/rupload/app.py new file mode 100644 index 0000000..449deb1 --- /dev/null +++ b/src/rupload/app.py @@ -0,0 +1,151 @@ +import aiohttp +from aiohttp import web +import asyncio +import pathlib + + +class Rupload(web.Application): + def __init__(self, upload_path, max_file_size): + self.upload_path = upload_path + self.max_file_size = max_file_size + super().__init__() + + +UPLOAD_FOLDER = "uploads" +pathlib.Path(UPLOAD_FOLDER).mkdir(parents=True, exist_ok=True) + +UPLOAD_PAGE = """ + + + + + + File Upload + + + +
+

Upload Your File

+
+ + + +
+
+ + +""" + + +async def handle_upload(request): + reader = await request.multipart() + field = await reader.next() + + if field.name == "file": + + filename = field.filename + print(filename) + if ".." or "/" in filename: + return web.Response(status=400, text="Invalid filename.") + + filepath = pathlib.Path(UPLOAD_FOLDER).joinpath(filename) + + if filepath.exists(): + return web.Response(status=400, text="File already exists.") + + with filepath.open("wb") as f: + file_size = 0 + while True: + chunk = await field.read_chunk() + if not chunk: + break + file_size += len(chunk) + if file_size > max_file_size: + f.close() + f.unlink() + return web.Response( + status=413, + text="File is too large. Maximum file size is {} bytes.".format( + max_file_size + ), + ) + f.write(chunk) + + return web.Response(text=f"File {filename} uploaded successfully!") + return web.Response(status=400, text="No file uploaded.") + + +async def handle_index(request): + return web.Response(text=UPLOAD_PAGE, content_type="text/html") + + +def create_app(upload_path="upload", max_file_size=1024 * 1024 * 50): + app = Rupload(upload_path=upload_path, max_file_size=max_file_size) + app.add_routes([web.get("/", handle_index), web.post("/upload", handle_upload)]) + return app diff --git a/src/rupload/cli.py b/src/rupload/cli.py new file mode 100644 index 0000000..cab2415 --- /dev/null +++ b/src/rupload/cli.py @@ -0,0 +1,36 @@ +import argparse +from aiohttp import web +from rupload.app import create_app + + +def parse_args(): + parser = argparse.ArgumentParser(description="Start the file upload server.") + parser.add_argument( + "--hostname", type=str, default="127.0.0.1", help="The hostname for the server." + ) + parser.add_argument( + "--port", type=int, default=8081, help="The port to bind the server to." + ) + parser.add_argument( + "--upload_folder", + type=str, + default="uploads", + help="Directory to store uploaded files.", + ) + parser.add_argument( + "--max_file_size", + type=int, + default=50 * 1024 * 1024, + help="Maximum file size in bytes (default is 50MB).", + ) + return parser.parse_args() + + +def main(): + args = parse_args() + app = create_app(upload_path=args.upload_folder, max_file_size=args.max_file_size) + web.run_app(app, host=args.hostname, port=args.port) + + +if __name__ == "__main__": + main()