Compare commits
	
		
			3 Commits
		
	
	
		
			d40befddd1
			...
			427342a47a
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 427342a47a | ||
|   | f25d49b0e7 | ||
|   | d4bbeb043f | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,6 @@ | ||||
| data.db | ||||
| uploads/ | ||||
|  | ||||
| # ---> Python | ||||
| # Byte-compiled / optimized / DLL files | ||||
| __pycache__/ | ||||
|   | ||||
							
								
								
									
										8
									
								
								config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								config.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| { | ||||
|     "upload_folder": "./uploads", | ||||
|     "max_file_size": 104857600, | ||||
|     "expiration_time": 604800, | ||||
|     "data_file": "data.db", | ||||
|     "base_url": "http://localhost:5000/", | ||||
|     "name": "up.x1b.dev" | ||||
| } | ||||
							
								
								
									
										49
									
								
								landing.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								landing.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| <!DOCTYPE html> | ||||
| <html lang="en"> | ||||
| <head> | ||||
|     <meta charset="UTF-8"> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||||
|     <title>{name}</title> | ||||
| </head> | ||||
| <body> | ||||
| <pre style="font-size: 1.5em;"> | ||||
| {name} File Upload and URL Shortener | ||||
|  | ||||
| Welcome to the {name} file upload and URL shortening service. | ||||
| This service allows you to easily upload files or shorten URLs for quick access. | ||||
| Files are stored for {expiration_days} days, and URLs are shortened for convenient sharing. | ||||
|  | ||||
| Usage: | ||||
|  | ||||
| Upload a file: | ||||
| curl -F file=@yourfile.ext {base_url}/ | ||||
|  | ||||
| Shorten a URL: | ||||
| curl -d "url=https://example.com" {base_url}/shorten | ||||
|  | ||||
| Details: | ||||
|  | ||||
| Files uploaded to this service are stored for {expiration_days} days or until they are automatically cleaned up. | ||||
| The maximum file size is {max_file_size}MB. | ||||
| URLs shortened with this service will redirect to the original URL for the same period. | ||||
|  | ||||
| Examples: | ||||
|  | ||||
| File upload: | ||||
| curl -F file=@document.pdf {base_url}/ | ||||
| Response: | ||||
| {base_url}/abcdef | ||||
|  | ||||
| URL shortening: | ||||
| curl -d "url=https://example.com" {base_url}/shorten | ||||
| Response: | ||||
| {base_url}/ghijkl | ||||
|  | ||||
| Disclaimer: | ||||
|  | ||||
| This service is provided as-is with no guarantees. | ||||
| Uploaded files and shortened URLs are not private and can be accessed by anyone with the link. | ||||
| Use at your own risk. | ||||
| </pre> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										97
									
								
								main.py
									
									
									
									
									
								
							
							
						
						
									
										97
									
								
								main.py
									
									
									
									
									
								
							| @@ -1,67 +1,73 @@ | ||||
| import os | ||||
| import uuid | ||||
| import time | ||||
| import json | ||||
| import threading | ||||
| from flask import Flask, request, redirect, send_from_directory, abort | ||||
| import os, uuid, time, json, sqlite3, threading | ||||
| from flask import Flask, request, redirect, send_from_directory, abort, render_template_string | ||||
|  | ||||
| app = Flask(__name__) | ||||
|  | ||||
| # config | ||||
| UPLOAD_FOLDER = './uploads' | ||||
| MAX_FILE_SIZE = 1024 * 1024 * 100  # last number = megabytes | ||||
| EXPIRATION_TIME = 60 * 60 * 24 * 7  # last number = days | ||||
| DATA_FILE = 'data.json' | ||||
| URL_PREFIX = 'http://localhost:5000/' | ||||
| with open('config.json') as f: | ||||
|     config = json.load(f) | ||||
|  | ||||
| if not os.path.exists(UPLOAD_FOLDER): | ||||
|     os.makedirs(UPLOAD_FOLDER) | ||||
| UPLOAD_FOLDER = config['upload_folder'] | ||||
| MAX_FILE_SIZE = config['max_file_size'] | ||||
| EXPIRATION_TIME = config['expiration_time'] | ||||
| DATA_FILE = config['data_file'] | ||||
| URL_PREFIX = config['base_url'] | ||||
| NAME = config['name'] | ||||
|  | ||||
| os.makedirs(UPLOAD_FOLDER, exist_ok=True) | ||||
|  | ||||
| def init_db(): | ||||
|     with sqlite3.connect(DATA_FILE) as conn: | ||||
|         conn.execute('CREATE TABLE IF NOT EXISTS files (key TEXT PRIMARY KEY, type TEXT NOT NULL, path TEXT, url TEXT, expiry REAL)') | ||||
|  | ||||
| init_db() | ||||
|  | ||||
| def load_data(): | ||||
|     if os.path.exists(DATA_FILE): | ||||
|         with open(DATA_FILE, 'r') as f: | ||||
|             return json.load(f) | ||||
|     return {} | ||||
|     with sqlite3.connect(DATA_FILE) as conn: | ||||
|         return {row[0]: {'type': row[1], 'path': row[2], 'url': row[3], 'expiry': row[4]} for row in conn.execute('SELECT * FROM files')} | ||||
|  | ||||
| def save_data(): | ||||
|     with sqlite3.connect(DATA_FILE) as conn: | ||||
|         conn.execute('DELETE FROM files') | ||||
|         conn.executemany('INSERT INTO files VALUES (?, ?, ?, ?, ?)', | ||||
|                          [(k, v['type'], v.get('path'), v.get('url'), v['expiry']) for k, v in data.items()]) | ||||
|  | ||||
| data = load_data() | ||||
|  | ||||
| def save_data(): | ||||
|     with open(DATA_FILE, 'w') as f: | ||||
|         json.dump(data, f) | ||||
|  | ||||
| def cleanup_files(): | ||||
|     while True: | ||||
|         time.sleep(60 * 60) | ||||
|         time.sleep(3600) | ||||
|         now = time.time() | ||||
|         for key, item in list(data.items()): | ||||
|             if 'expiry' in item and now > item['expiry']: | ||||
|                 try: | ||||
|                     os.remove(item['path']) | ||||
|                 except Exception as e: | ||||
|                     print(f"Error removing file {item['path']}: {e}") | ||||
|                 del data[key] | ||||
|         expired_keys = [k for k, v in data.items() if v['expiry'] < now] | ||||
|         for k in expired_keys: | ||||
|             if data[k]['type'] == 'file': | ||||
|                 os.remove(data[k]['path']) | ||||
|             data.pop(k) | ||||
|         save_data() | ||||
|  | ||||
| threading.Thread(target=cleanup_files, daemon=True).start() | ||||
|  | ||||
| @app.route('/', methods=['GET']) | ||||
| def landing_page(): | ||||
|     with open('landing.html') as f: | ||||
|         html = f.read().format( | ||||
|             name=NAME, | ||||
|             base_url=URL_PREFIX.rstrip('/'), | ||||
|             expiration_days=EXPIRATION_TIME // 86400, | ||||
|             max_file_size=MAX_FILE_SIZE // 1048576 | ||||
|         ) | ||||
|     return render_template_string(html) | ||||
|  | ||||
| @app.route('/', methods=['POST']) | ||||
| def upload_file(): | ||||
|     file = request.files.get('file') | ||||
|     if not file: | ||||
|         return "No file uploaded\n", 400 | ||||
|     if file.content_length > MAX_FILE_SIZE: | ||||
|         return "File too large\n", 400 | ||||
|     if not file or file.content_length > MAX_FILE_SIZE: | ||||
|         return "No file uploaded or file too large\n", 400 | ||||
|      | ||||
|     filename = file.filename | ||||
|     key = uuid.uuid4().hex[:6] | ||||
|     filepath = os.path.join(UPLOAD_FOLDER, f"{key}_{filename}") | ||||
|     filepath = os.path.join(UPLOAD_FOLDER, f"{key}_{file.filename}") | ||||
|     file.save(filepath) | ||||
|      | ||||
|     data[key] = { | ||||
|         'type': 'file', | ||||
|         'path': filepath, | ||||
|         'expiry': time.time() + EXPIRATION_TIME | ||||
|     } | ||||
|     data[key] = {'type': 'file', 'path': filepath, 'expiry': time.time() + EXPIRATION_TIME} | ||||
|     save_data() | ||||
|     return f"{URL_PREFIX}{key}\n" | ||||
|  | ||||
| @@ -72,11 +78,7 @@ def shorten_url(): | ||||
|         return "No URL provided\n", 400 | ||||
|      | ||||
|     key = uuid.uuid4().hex[:6] | ||||
|     data[key] = { | ||||
|         'type': 'url', | ||||
|         'url': url, | ||||
|         'expiry': time.time() + EXPIRATION_TIME | ||||
|     } | ||||
|     data[key] = {'type': 'url', 'url': url, 'expiry': time.time() + EXPIRATION_TIME} | ||||
|     save_data() | ||||
|     return f"{URL_PREFIX}{key}\n" | ||||
|  | ||||
| @@ -88,9 +90,8 @@ def get_content(key): | ||||
|      | ||||
|     if item['type'] == 'file': | ||||
|         return send_from_directory(UPLOAD_FOLDER, os.path.basename(item['path'])) | ||||
|     elif item['type'] == 'url': | ||||
|     if item['type'] == 'url': | ||||
|         return redirect(item['url']) | ||||
|     else: | ||||
|     abort(404) | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|   | ||||
		Reference in New Issue
	
	Block a user