From 3e72ecab2043b4ef5f58f23aa7cfe505c2b3e4c7 Mon Sep 17 00:00:00 2001 From: retoor Date: Tue, 26 Nov 2024 04:34:46 +0100 Subject: [PATCH] Initial commit --- .gitignore | 3 + Makefile | 12 ++ README.md | 17 ++ pyproject.toml | 3 + setup.cfg | 25 +++ src/rupload.egg-info/PKG-INFO | 29 ++++ src/rupload.egg-info/SOURCES.txt | 13 ++ src/rupload.egg-info/dependency_links.txt | 1 + src/rupload.egg-info/entry_points.txt | 2 + src/rupload.egg-info/requires.txt | 2 + src/rupload.egg-info/top_level.txt | 1 + src/rupload/__init__.py | 0 src/rupload/__main__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 150 bytes src/rupload/__pycache__/app.cpython-312.pyc | Bin 0 -> 4471 bytes src/rupload/__pycache__/cli.cpython-312.pyc | Bin 0 -> 1640 bytes src/rupload/app.py | 151 ++++++++++++++++++ src/rupload/cli.py | 36 +++++ 18 files changed, 295 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 pyproject.toml create mode 100644 setup.cfg create mode 100644 src/rupload.egg-info/PKG-INFO create mode 100644 src/rupload.egg-info/SOURCES.txt create mode 100644 src/rupload.egg-info/dependency_links.txt create mode 100644 src/rupload.egg-info/entry_points.txt create mode 100644 src/rupload.egg-info/requires.txt create mode 100644 src/rupload.egg-info/top_level.txt create mode 100644 src/rupload/__init__.py create mode 100644 src/rupload/__main__.py create mode 100644 src/rupload/__pycache__/__init__.cpython-312.pyc create mode 100644 src/rupload/__pycache__/app.cpython-312.pyc create mode 100644 src/rupload/__pycache__/cli.cpython-312.pyc create mode 100644 src/rupload/app.py create mode 100644 src/rupload/cli.py 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 0000000000000000000000000000000000000000..b40f013eb28c07a6fde1da95bc3c2f7e84f1cbdc GIT binary patch literal 150 zcmX@j%ge<81aa3~(n0iN5P=Rpvj9b=GgLBYGWxA#C}INgK7-W!GS$z>&rQ`YN-fFH zFVZh4%FjwoE-BV8DlN##PfXD-E=q>8q)`7M8~{7)sY&96Jq=ZR%JXLO^Y4Ks;7jqt$dgb8U|^o*C|3 z=S7ghE-FFV)q=X+@X?QcR8=eJOIoRXxBcr+D5;31R9dM&?H}48mGaed?~ETYUbgBa zzH{fEbIpLLVd%y6Z0pXaS{#>2%PIdrV|op;b3oSLWriZeZEb7qJ_18a5_w zRF-v9r?L#_K?fUU5&<%VncD4>Wz|p|N0uGNOp>JK=ecavs^cud)Urs{CRPor)X5T$ zQ`RABYp&S#ki9^dKP-O9*LSGNjxlhUsh%yPjopV>&Ano1qZvKy1-x}`Nh4cSe|^5uqNco5FWP5Lsc*f2mTfg~6sX0U_iY;J8E5yKdQofF^%oAg0H7 zYF5W{wnb=4QZ17L)A7`tuF>kahG%sZXZXiqiJh9R7#T-Z3_LzOlxvcrIyG?NBpkGK zk^5La>n(Yl9J&BtK4+XumbM^WX??P#GO*2*mAY;$j7bv&m>iZI#dI%U_Wyd5HRK{d0l49r; zGow>ncX}gKv0katF=;rLo2_o$TUSU$H^-!0d--atrNj{9tLP>sT~_F&S-D$#i)ff+ zh@$BY5bO=ROSh6WpK+>+X3YV6>4-hgP$W_*DX--YOaA}RaJnrSv%jrqnr>Fcq;KZB z2~s>yGu#-x&A@$wTj6V4X+rFKjx#15&21suVTE8x@kA) zCAwfkkg+_NdZ&wf%kaZnEW{|6_(_A7aDI+u=$dpuRn@KBJ)D*|Y!QRe=&SM+ezTyC_~?XCWK%vB+ddPzPenU>iT@_*>W6jmF=VJX43^cO>#5=beK z!q{1MDg{|(b?i7w1$UX+OBNYwfg`;bew`=y zLa=|4yAPEu3liH)7>>N)cAX4g2*4)8(b3UPTQSS$vwoV-XTAF;&+@!~*J%2z#P9X- zR4e)Umj~Zl9WHnmhxE49AQHPtfXs0F&dBq~Rd^tdr?TEPnUdgot6JK4>g<{G7g7>7 zRWH=)4TI`%ebOx3meCZdba3Mw4W)z)h!5fiW?`~wSq_#IiN&czEy?3Cmd|q3wkUi% z4{WI;uqE#%~yPnU*4=e?0t=h1?NfTyXgUTig&~SUTIlC&-zUF*Myz9#+pgu(7&Gi~9 zrMez1po#Z_&D#0=7h{Jyu}9JSm*IEmSK^$I4o|y5c24>&;J&!+JLW80bQ<>ncAP^{ zg@qle(1zm%**&eP-f>eDcic6I18hXbmzLFQUV|`~wLr8=G#7KyfFl)rL9a zia_5hn?tGr&g+I7rlA8M%-mj~ZfK4`;!Q{02=hbiP&drBLk%7(>)6o9UM><7l(Q1b zZXf&b%XQAhVP!M-S{Qge>n5v;sR5Q}1Tq2$HTXFchJW(vdT`gH!GjM54?Y|`^eA~~ z`Q*lzcdovE`}H4X9wqiIPkkCm+*rJ}c$2h4sg9FGNmGqDS%e~1Y%_70IZVW$@&v=tz=W?u!c=F@I{G~r&L?R?yg z#OcL8<{ms4(*g1d>~a%+bt$tTPmBEY$vy^&`zL*N;?xv$3x{EicMHCC6TWqIQ^WIQ z6ri^l#ts;`aUaL~nJIp9>9<$bD@iA3Tmh1tl3~LxA}7zR#98OC1~>Q z2~8cYvf%9z?6lcBqh7(Q1t{|i{xm6d?BES~6Yjk=k+y=lxuX(jhy79jy42t_n6K3h zJ{Pi!5kJ?bBVLCTgGyC~>YrlA3n;OIDYudvv@M5nZv=C}Rl0eFo}Ia*Qpo@Zt(`S$~PVc9C_F&!c&-FD;NM_+$?3`~Ze0 zq96!=L;Zh8J79$Wr{SQmdqw@wx@kQ{Fn!XGw(VL@ZlJ_+0CtU}=cdisWV4+)Q#CcW;-O zIqfYCL{JobQ4mxREIzd)Aov&f?n_RKcdp5kPril5r#|_e{n6ejh0bx`pY!?7_dEOj z&M$^hMzG|oZ*CvU2>m6Ld=)a`^eqs+Mi^nqLmPq@JjpL?6eJid@wqFMnFbw3Lvp{~@GYNfx0zE+cB`9rb^tlXr;;ly^ru$gU5m zkpKspuAMx!+yER)2ZjA?$1b{qc8WvJOvEx5F_VQATs%7=+;y(yIKmQ5OFZ3p=Ro9{mH@QQ($y>zSay?>pLN9Qz$q4;`&^p|& zjtOg0H{@>6j>?wR3K(xYK8eN_Uwoy$0Kdg(<{g0N4s$D@NxVFU94ovVlDLG)mecWg zth9(1Myh3n0p;$Oa|lIqB7#s&9+;bM8xKVQQ$3ontTZ)yEATL(aVb?9uHW&~%7xu@+vaAM6J}n{k~LjszPxbb zjat2?#+pO7Lx(aFk6)$R9iO!Mx=?9caWJ;Qo7iHRaT?2Ro5$s3yYMi$OEu9b6P;#0 zT4=NapEM}pK|mWJ4R)Xm)}U!&4Mv-f<)-J>!!E4?E+L{3*$+VW(2;SrZ_M|M`NPHa z2gcib*9JO-CaFwtUtv)ePmPz z)#-t;crupYi-4~T;nNM~z*rvHP&w1rXL|a~Z~E+^GJ6VHqLIlIvz1KdPaq6WX5N{* zhzozRU>36}%PoR~_3Jaz^jO1h!xS$H7)&YqKeoU>0x>fY*d7fOSID#PgtzwV?@t` zU4#<76U*RZqBzr}X9Pg;9k)$qLA(Heb_EFZf`0b%<-OIT^5osg{>7!<#igHL>aX1D zt=xK0es^!>NGW}K{iEw&$luI=Z+&as!#}$B-QSg0>2o5YX4@jBZ9~T5*@#Py8?-nN z(+u^jFYAyA6~&}wi3|i(JPEdaA0@Gp6d!5JetOst))~xi++`-|4_6~u0c~O&nMCT1(Q8^{{R30 literal 0 HcmV?d00001 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()