forked from spitkov/sxbin
too many changes for me to list but basically user suppport file lsiting uploading deleting renaming moving copying etc and toggle if index.html presnet shw it to acces ur page /username and then ASKDJAKLSDl this is a development why do i have to document everything
This commit is contained in:
parent
7c641df41e
commit
0f444b7606
428
app.py
428
app.py
@ -1,20 +1,19 @@
|
|||||||
from flask import Flask, request, jsonify, send_from_directory, render_template, url_for, redirect, send_file
|
from flask import Flask, request, jsonify, send_from_directory, render_template, url_for, redirect, send_file, session
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
import shortuuid
|
import shortuuid
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
import zipfile
|
import zipfile
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import shutil
|
import shutil
|
||||||
from datetime import timedelta
|
|
||||||
from pygments import highlight
|
from pygments import highlight
|
||||||
from pygments.lexers import get_lexer_by_name, guess_lexer
|
from pygments.lexers import get_lexer_by_name, guess_lexer
|
||||||
from pygments.formatters import HtmlFormatter
|
from pygments.formatters import HtmlFormatter
|
||||||
from pygments.util import ClassNotFound
|
from pygments.util import ClassNotFound
|
||||||
import json
|
import json
|
||||||
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
|
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user, login_remembered
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
@ -22,6 +21,7 @@ app.secret_key = 'your_secret_key_here' # Add this line
|
|||||||
UPLOAD_FOLDER = './uploads'
|
UPLOAD_FOLDER = './uploads'
|
||||||
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
|
||||||
DATABASE = 'data.db'
|
DATABASE = 'data.db'
|
||||||
|
app.config['REMEMBER_COOKIE_DURATION'] = timedelta(days=30) # Set cookie to expire after 30 days
|
||||||
|
|
||||||
if not os.path.exists(UPLOAD_FOLDER):
|
if not os.path.exists(UPLOAD_FOLDER):
|
||||||
os.makedirs(UPLOAD_FOLDER)
|
os.makedirs(UPLOAD_FOLDER)
|
||||||
@ -115,146 +115,82 @@ def load_user(user_id):
|
|||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template('index.html')
|
if current_user.is_authenticated:
|
||||||
|
return render_template('index.html', user=current_user)
|
||||||
|
return render_template('index.html', user=None)
|
||||||
|
|
||||||
@app.route('/content/<vanity>')
|
@app.route('/u/<username>')
|
||||||
def content(vanity):
|
@app.route('/u/<username>/')
|
||||||
|
@app.route('/u/<username>/<path:filename>')
|
||||||
|
def serve_user_page(username, filename=None):
|
||||||
|
print(f"Accessing user page: {username}, filename: {filename}") # Debug print
|
||||||
|
|
||||||
|
# Check if the username exists in the database
|
||||||
db = get_db()
|
db = get_db()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("SELECT * FROM content WHERE vanity = ?", (vanity,))
|
cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
|
||||||
target = cursor.fetchone()
|
user = cursor.fetchone()
|
||||||
|
if not user:
|
||||||
|
print(f"User {username} not found") # Debug print
|
||||||
|
return "User not found", 404
|
||||||
|
|
||||||
if target:
|
user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username)
|
||||||
content_type, content_data = target[1], target[2]
|
print(f"User folder path: {user_folder}") # Debug print
|
||||||
if content_type == 'pastebin':
|
|
||||||
try:
|
|
||||||
lexer = guess_lexer(content_data)
|
|
||||||
language = lexer.aliases[0]
|
|
||||||
except ClassNotFound:
|
|
||||||
language = 'text'
|
|
||||||
lexer = get_lexer_by_name(language)
|
|
||||||
|
|
||||||
formatter = HtmlFormatter(style='monokai', linenos=True, cssclass="source")
|
if not os.path.exists(user_folder):
|
||||||
highlighted_code = highlight(content_data, lexer, formatter)
|
print(f"User folder does not exist for {username}") # Debug print
|
||||||
css = formatter.get_style_defs('.source')
|
os.makedirs(user_folder) # Create the folder if it doesn't exist
|
||||||
return render_template('content.html',
|
|
||||||
highlighted_content=highlighted_code,
|
|
||||||
css=css,
|
|
||||||
raw_content=content_data,
|
|
||||||
created_at=target[3],
|
|
||||||
vanity=vanity,
|
|
||||||
language=language)
|
|
||||||
elif content_type == 'file':
|
|
||||||
file_path = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}_{content_data}')
|
|
||||||
file_info = {
|
|
||||||
'name': content_data,
|
|
||||||
'size': os.path.getsize(file_path),
|
|
||||||
'modified_at': datetime.fromtimestamp(os.path.getmtime(file_path)).strftime('%Y-%m-%d %H:%M:%S'),
|
|
||||||
'url': url_for('download_file', vanity=vanity)
|
|
||||||
}
|
|
||||||
return render_template('file.html', **file_info)
|
|
||||||
elif content_type == 'url':
|
|
||||||
return render_template('content.html', url=content_data)
|
|
||||||
return 'Not Found', 404
|
|
||||||
|
|
||||||
@app.route('/download/<vanity>', methods=['GET'])
|
current_path = os.path.join(user_folder, filename.rstrip('/') if filename else '')
|
||||||
def download_file(vanity):
|
if not os.path.exists(current_path):
|
||||||
db = get_db()
|
return "Folder or file not found", 404
|
||||||
cursor = db.cursor()
|
|
||||||
cursor.execute("SELECT * FROM content WHERE vanity = ? AND type = 'file'", (vanity,))
|
|
||||||
target = cursor.fetchone()
|
|
||||||
if target:
|
|
||||||
filename = f'{vanity}_{target[2]}'
|
|
||||||
return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)
|
|
||||||
return 'Not Found', 404
|
|
||||||
|
|
||||||
@app.route('/upload/pastebin', methods=['POST'])
|
if os.path.isfile(current_path):
|
||||||
def upload_pastebin():
|
return send_file(current_path)
|
||||||
content = request.form['content']
|
|
||||||
vanity = shortuuid.uuid()[:6]
|
|
||||||
created_at = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
|
|
||||||
db = get_db()
|
# Check if we should ignore index.html
|
||||||
cursor = db.cursor()
|
ignore_index = session.get(f'ignore_index_{username}', False)
|
||||||
cursor.execute("INSERT INTO content (vanity, type, data, created_at) VALUES (?, ?, ?, ?)",
|
|
||||||
(vanity, 'pastebin', content, created_at))
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
return jsonify({'vanity': vanity})
|
# Check for index.html
|
||||||
|
index_path = os.path.join(current_path, 'index.html')
|
||||||
|
if os.path.exists(index_path) and not ignore_index:
|
||||||
|
return send_file(index_path)
|
||||||
|
|
||||||
@app.route('/upload/file', methods=['POST'])
|
# Directory listing
|
||||||
def upload_file():
|
files = []
|
||||||
if 'file' not in request.files:
|
folders = []
|
||||||
return 'No file part', 400
|
for item in os.listdir(current_path):
|
||||||
file = request.files['file']
|
item_path = os.path.join(current_path, item)
|
||||||
if file.filename == '':
|
relative_path = os.path.relpath(item_path, user_folder)
|
||||||
return 'No selected file', 400
|
if os.path.isfile(item_path):
|
||||||
if file:
|
files.append({'name': item, 'path': relative_path})
|
||||||
vanity = shortuuid.uuid()[:6]
|
|
||||||
filename = secure_filename(file.filename)
|
|
||||||
filepath = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}_{filename}')
|
|
||||||
file.save(filepath)
|
|
||||||
|
|
||||||
db = get_db()
|
|
||||||
cursor = db.cursor()
|
|
||||||
cursor.execute("INSERT INTO content (vanity, type, data) VALUES (?, ?, ?)",
|
|
||||||
(vanity, 'file', filename))
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
return jsonify({'vanity': vanity})
|
|
||||||
|
|
||||||
def save_file(file, folder_path):
|
|
||||||
filename = secure_filename(file.filename)
|
|
||||||
file_path = os.path.join(folder_path, filename)
|
|
||||||
file.save(file_path)
|
|
||||||
|
|
||||||
def handle_uploaded_folder(files, base_path):
|
|
||||||
for file in files:
|
|
||||||
if file.filename.endswith('/'):
|
|
||||||
subfolder_path = os.path.join(base_path, secure_filename(file.filename))
|
|
||||||
os.makedirs(subfolder_path, exist_ok=True)
|
|
||||||
handle_uploaded_folder(request.files.getlist(file.filename), subfolder_path)
|
|
||||||
else:
|
else:
|
||||||
save_file(file, base_path)
|
folders.append({'name': item, 'path': relative_path})
|
||||||
|
|
||||||
@app.route('/upload/folder', methods=['POST'])
|
parent_folder = os.path.dirname(filename.rstrip('/')) if filename else None
|
||||||
def upload_folder():
|
current_folder = os.path.basename(current_path)
|
||||||
if 'file' not in request.files:
|
|
||||||
return 'No files uploaded', 400
|
|
||||||
|
|
||||||
files = request.files.getlist('file')
|
# Generate the correct parent folder URL
|
||||||
if not files:
|
parent_url = None
|
||||||
return 'No files selected', 400
|
if parent_folder:
|
||||||
|
parent_url = url_for('serve_user_page', username=username, filename=parent_folder)
|
||||||
|
elif filename: # If we're in a subfolder, parent is the root
|
||||||
|
parent_url = url_for('serve_user_page', username=username)
|
||||||
|
|
||||||
vanity = shortuuid.uuid()[:6]
|
return render_template('user_files_public.html',
|
||||||
folder_path = os.path.join(app.config['UPLOAD_FOLDER'], vanity)
|
username=username,
|
||||||
os.makedirs(folder_path)
|
files=files,
|
||||||
|
folders=folders,
|
||||||
|
current_path=filename.rstrip('/') if filename else '',
|
||||||
|
parent_url=parent_url,
|
||||||
|
current_folder=current_folder)
|
||||||
|
|
||||||
handle_uploaded_folder(files, folder_path)
|
@app.route('/<path:path>')
|
||||||
|
def redirect_vanity(path):
|
||||||
|
parts = path.rstrip('/').split('/')
|
||||||
|
vanity = parts[0]
|
||||||
|
subpath = '/'.join(parts[1:]) if len(parts) > 1 else ''
|
||||||
|
|
||||||
db = get_db()
|
|
||||||
cursor = db.cursor()
|
|
||||||
cursor.execute("INSERT INTO content (vanity, type, data) VALUES (?, ?, ?)",
|
|
||||||
(vanity, 'folder', ','.join([file.filename for file in files])))
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
return jsonify({'vanity': vanity})
|
|
||||||
|
|
||||||
@app.route('/shorten', methods=['POST'])
|
|
||||||
def shorten_url():
|
|
||||||
original_url = request.form['url']
|
|
||||||
vanity = shortuuid.uuid()[:6]
|
|
||||||
|
|
||||||
db = get_db()
|
|
||||||
cursor = db.cursor()
|
|
||||||
cursor.execute("INSERT INTO content (vanity, type, data) VALUES (?, ?, ?)",
|
|
||||||
(vanity, 'url', original_url))
|
|
||||||
db.commit()
|
|
||||||
|
|
||||||
return jsonify({'vanity': vanity})
|
|
||||||
|
|
||||||
@app.route('/<vanity>', methods=['GET'])
|
|
||||||
def redirect_vanity(vanity):
|
|
||||||
db = get_db()
|
db = get_db()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("SELECT * FROM content WHERE vanity = ?", (vanity,))
|
cursor.execute("SELECT * FROM content WHERE vanity = ?", (vanity,))
|
||||||
@ -388,6 +324,12 @@ def register():
|
|||||||
cursor.execute("INSERT INTO users (username, password_hash) VALUES (?, ?)",
|
cursor.execute("INSERT INTO users (username, password_hash) VALUES (?, ?)",
|
||||||
(username, hashed_password))
|
(username, hashed_password))
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
# Create user directory
|
||||||
|
user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username)
|
||||||
|
if not os.path.exists(user_folder):
|
||||||
|
os.makedirs(user_folder)
|
||||||
|
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
return render_template('register.html')
|
return render_template('register.html')
|
||||||
|
|
||||||
@ -396,12 +338,14 @@ def login():
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
username = request.form['username']
|
username = request.form['username']
|
||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
|
remember = 'remember' in request.form
|
||||||
db = get_db()
|
db = get_db()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
|
cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
|
||||||
user = cursor.fetchone()
|
user = cursor.fetchone()
|
||||||
if user and User.verify_password(user[2], password):
|
if user and User.verify_password(user[2], password):
|
||||||
login_user(User(user[0], user[1], user[2]))
|
user_obj = User(user[0], user[1], user[2])
|
||||||
|
login_user(user_obj, remember=remember)
|
||||||
return redirect(url_for('user_files', username=username))
|
return redirect(url_for('user_files', username=username))
|
||||||
return "Invalid username or password"
|
return "Invalid username or password"
|
||||||
return render_template('login.html')
|
return render_template('login.html')
|
||||||
@ -412,21 +356,74 @@ def logout():
|
|||||||
logout_user()
|
logout_user()
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
@app.route('/user/<username>')
|
@app.route('/dash/<username>')
|
||||||
def user_files(username):
|
@app.route('/dash/<username>/')
|
||||||
if current_user.is_authenticated and current_user.username == username:
|
@app.route('/dash/<username>/<path:subpath>')
|
||||||
user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username)
|
@login_required
|
||||||
if not os.path.exists(user_folder):
|
def user_files(username, subpath=''):
|
||||||
os.makedirs(user_folder)
|
if current_user.username != username:
|
||||||
files = os.listdir(user_folder)
|
|
||||||
return render_template('user_files.html', username=username, files=files)
|
|
||||||
return "Unauthorized", 401
|
return "Unauthorized", 401
|
||||||
|
|
||||||
@app.route('/user/<username>/upload', methods=['POST'])
|
user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username)
|
||||||
|
current_path = os.path.join(user_folder, subpath.rstrip('/'))
|
||||||
|
|
||||||
|
# Create user folder if it doesn't exist
|
||||||
|
if not os.path.exists(user_folder):
|
||||||
|
os.makedirs(user_folder)
|
||||||
|
|
||||||
|
if not os.path.exists(current_path):
|
||||||
|
return "Folder not found", 404
|
||||||
|
|
||||||
|
if not os.path.isdir(current_path):
|
||||||
|
return "Not a directory", 400
|
||||||
|
|
||||||
|
items = []
|
||||||
|
folders = []
|
||||||
|
for item in os.listdir(current_path):
|
||||||
|
item_path = os.path.join(current_path, item)
|
||||||
|
relative_path = os.path.relpath(item_path, user_folder)
|
||||||
|
if os.path.isfile(item_path):
|
||||||
|
items.append({'name': item, 'type': 'file', 'path': relative_path})
|
||||||
|
else:
|
||||||
|
items.append({'name': item, 'type': 'folder', 'path': relative_path})
|
||||||
|
folders.append(relative_path)
|
||||||
|
|
||||||
|
parent_folder = os.path.dirname(subpath.rstrip('/')) if subpath else None
|
||||||
|
current_folder = os.path.basename(current_path)
|
||||||
|
|
||||||
|
# Check if index.html exists in the current folder
|
||||||
|
index_exists = 'index.html' in [item['name'] for item in items if item['type'] == 'file']
|
||||||
|
|
||||||
|
# Get the current setting for ignoring index.html
|
||||||
|
ignore_index = session.get(f'ignore_index_{username}', False)
|
||||||
|
|
||||||
|
return render_template('user_files.html',
|
||||||
|
username=username,
|
||||||
|
items=items,
|
||||||
|
folders=folders,
|
||||||
|
current_path=subpath.rstrip('/'),
|
||||||
|
parent_folder=parent_folder,
|
||||||
|
current_folder=current_folder,
|
||||||
|
index_exists=index_exists,
|
||||||
|
ignore_index=ignore_index)
|
||||||
|
|
||||||
|
@app.route('/dash/<username>/toggle_index')
|
||||||
|
@login_required
|
||||||
|
def toggle_index(username):
|
||||||
|
if current_user.username != username:
|
||||||
|
return "Unauthorized", 401
|
||||||
|
|
||||||
|
current_setting = session.get(f'ignore_index_{username}', False)
|
||||||
|
session[f'ignore_index_{username}'] = not current_setting
|
||||||
|
|
||||||
|
return redirect(url_for('user_files', username=username))
|
||||||
|
|
||||||
|
@app.route('/dash/<username>/upload', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def upload_user_file(username):
|
def upload_user_file(username):
|
||||||
if current_user.username != username:
|
if current_user.username != username:
|
||||||
return "Unauthorized", 401
|
return "Unauthorized", 401
|
||||||
|
subpath = request.form.get('subpath', '').rstrip('/')
|
||||||
if 'file' not in request.files:
|
if 'file' not in request.files:
|
||||||
return 'No file part', 400
|
return 'No file part', 400
|
||||||
file = request.files['file']
|
file = request.files['file']
|
||||||
@ -434,11 +431,12 @@ def upload_user_file(username):
|
|||||||
return 'No selected file', 400
|
return 'No selected file', 400
|
||||||
if file:
|
if file:
|
||||||
filename = secure_filename(file.filename)
|
filename = secure_filename(file.filename)
|
||||||
file_path = os.path.join(app.config['UPLOAD_FOLDER'], username, filename)
|
file_path = os.path.join(app.config['UPLOAD_FOLDER'], username, subpath, filename)
|
||||||
|
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||||
file.save(file_path)
|
file.save(file_path)
|
||||||
return redirect(url_for('user_files', username=username))
|
return redirect(url_for('user_files', username=username, subpath=subpath))
|
||||||
|
|
||||||
@app.route('/user/<username>/delete/<filename>', methods=['POST'])
|
@app.route('/dash/<username>/delete/<filename>', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def delete_user_file(username, filename):
|
def delete_user_file(username, filename):
|
||||||
if current_user.username != username:
|
if current_user.username != username:
|
||||||
@ -448,7 +446,7 @@ def delete_user_file(username, filename):
|
|||||||
os.remove(file_path)
|
os.remove(file_path)
|
||||||
return redirect(url_for('user_files', username=username))
|
return redirect(url_for('user_files', username=username))
|
||||||
|
|
||||||
@app.route('/user/<username>/rename', methods=['POST'])
|
@app.route('/dash/<username>/rename', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def rename_user_file(username):
|
def rename_user_file(username):
|
||||||
if current_user.username != username:
|
if current_user.username != username:
|
||||||
@ -461,90 +459,100 @@ def rename_user_file(username):
|
|||||||
os.rename(old_path, new_path)
|
os.rename(old_path, new_path)
|
||||||
return redirect(url_for('user_files', username=username))
|
return redirect(url_for('user_files', username=username))
|
||||||
|
|
||||||
@app.route('/<username>')
|
@app.route('/dash/<username>/create_folder', methods=['POST'])
|
||||||
@app.route('/<username>/')
|
@login_required
|
||||||
@app.route('/<username>/<path:filename>')
|
def create_folder(username):
|
||||||
def serve_user_page(username, filename=None):
|
if current_user.username != username:
|
||||||
print(f"Accessing user page: {username}, filename: {filename}") # Debug print
|
return "Unauthorized", 401
|
||||||
|
subpath = request.form.get('subpath', '').rstrip('/')
|
||||||
|
folder_name = secure_filename(request.form['folder_name'])
|
||||||
|
folder_path = os.path.join(app.config['UPLOAD_FOLDER'], username, subpath, folder_name)
|
||||||
|
if not os.path.exists(folder_path):
|
||||||
|
os.makedirs(folder_path)
|
||||||
|
return redirect(url_for('user_files', username=username, subpath=subpath))
|
||||||
|
|
||||||
# Check if the username exists in the database
|
@app.route('/dash/<username>/delete_folder/<folder_name>', methods=['POST'])
|
||||||
db = get_db()
|
@login_required
|
||||||
cursor = db.cursor()
|
def delete_folder(username, folder_name):
|
||||||
cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
|
if current_user.username != username:
|
||||||
user = cursor.fetchone()
|
return "Unauthorized", 401
|
||||||
if not user:
|
folder_path = os.path.join(app.config['UPLOAD_FOLDER'], username, folder_name)
|
||||||
print(f"User {username} not found") # Debug print
|
if os.path.exists(folder_path):
|
||||||
return "User not found", 404
|
shutil.rmtree(folder_path)
|
||||||
|
return redirect(url_for('user_files', username=username))
|
||||||
|
|
||||||
user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username)
|
@app.route('/dash/<username>/rename_folder', methods=['POST'])
|
||||||
print(f"User folder path: {user_folder}") # Debug print
|
@login_required
|
||||||
|
def rename_folder(username):
|
||||||
|
if current_user.username != username:
|
||||||
|
return "Unauthorized", 401
|
||||||
|
old_foldername = request.form['old_foldername']
|
||||||
|
new_foldername = secure_filename(request.form['new_foldername'])
|
||||||
|
old_path = os.path.join(app.config['UPLOAD_FOLDER'], username, old_foldername)
|
||||||
|
new_path = os.path.join(app.config['UPLOAD_FOLDER'], username, new_foldername)
|
||||||
|
if os.path.exists(old_path):
|
||||||
|
os.rename(old_path, new_path)
|
||||||
|
return redirect(url_for('user_files', username=username))
|
||||||
|
|
||||||
if not os.path.exists(user_folder):
|
@app.route('/dash/<username>/move_item', methods=['POST'])
|
||||||
print(f"User folder does not exist for {username}") # Debug print
|
@login_required
|
||||||
os.makedirs(user_folder) # Create the folder if it doesn't exist
|
def move_item(username):
|
||||||
|
if current_user.username != username:
|
||||||
|
return "Unauthorized", 401
|
||||||
|
item_name = request.form['item_name']
|
||||||
|
item_type = request.form['item_type']
|
||||||
|
destination_folder = request.form['destination_folder']
|
||||||
|
source_path = os.path.join(app.config['UPLOAD_FOLDER'], username, item_name)
|
||||||
|
dest_path = os.path.join(app.config['UPLOAD_FOLDER'], username, destination_folder, item_name)
|
||||||
|
if os.path.exists(source_path):
|
||||||
|
shutil.move(source_path, dest_path)
|
||||||
|
return redirect(url_for('user_files', username=username))
|
||||||
|
|
||||||
if filename is None or filename == '':
|
@app.route('/dash/<username>/copy_item', methods=['POST'])
|
||||||
# Try to serve index.html
|
@login_required
|
||||||
index_path = os.path.join(user_folder, 'index.html')
|
def copy_item(username):
|
||||||
print(f"Checking for index.html at: {index_path}") # Debug print
|
if current_user.username != username:
|
||||||
if os.path.exists(index_path):
|
return "Unauthorized", 401
|
||||||
print(f"Serving index.html for {username}") # Debug print
|
item_name = request.form['item_name']
|
||||||
return send_file(index_path)
|
item_type = request.form['item_type']
|
||||||
|
destination_folder = request.form['destination_folder']
|
||||||
|
source_path = os.path.join(app.config['UPLOAD_FOLDER'], username, item_name)
|
||||||
|
dest_path = os.path.join(app.config['UPLOAD_FOLDER'], username, destination_folder, item_name)
|
||||||
|
if os.path.exists(source_path):
|
||||||
|
if item_type == 'file':
|
||||||
|
shutil.copy2(source_path, dest_path)
|
||||||
else:
|
else:
|
||||||
print(f"No index.html found, listing files for {username}") # Debug print
|
shutil.copytree(source_path, dest_path)
|
||||||
# If no index.html, list all files
|
return redirect(url_for('user_files', username=username))
|
||||||
files = os.listdir(user_folder)
|
|
||||||
print(f"Files in {username}'s folder: {files}") # Debug print
|
|
||||||
return render_template('user_files_public.html', username=username, files=files)
|
|
||||||
else:
|
|
||||||
# Serve the requested file
|
|
||||||
file_path = os.path.join(user_folder, filename)
|
|
||||||
print(f"Attempting to serve file: {file_path}") # Debug print
|
|
||||||
if os.path.exists(file_path) and os.path.isfile(file_path):
|
|
||||||
print(f"Serving file: {file_path}") # Debug print
|
|
||||||
return send_file(file_path)
|
|
||||||
else:
|
|
||||||
print(f"File not found: {file_path}") # Debug print
|
|
||||||
return "File not found", 404
|
|
||||||
|
|
||||||
@app.route('/debug/users')
|
@app.route('/dash/<username>/edit/<path:filename>', methods=['GET', 'POST'])
|
||||||
def debug_users():
|
|
||||||
db = get_db()
|
|
||||||
cursor = db.cursor()
|
|
||||||
cursor.execute("SELECT username FROM users")
|
|
||||||
users = cursor.fetchall()
|
|
||||||
|
|
||||||
user_files = {}
|
|
||||||
for user in users:
|
|
||||||
username = user[0]
|
|
||||||
user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username)
|
|
||||||
if os.path.exists(user_folder):
|
|
||||||
user_files[username] = os.listdir(user_folder)
|
|
||||||
else:
|
|
||||||
user_files[username] = []
|
|
||||||
|
|
||||||
return jsonify(user_files)
|
|
||||||
|
|
||||||
@app.route('/user/<username>/edit/<path:filename>', methods=['GET', 'POST'])
|
|
||||||
@login_required
|
@login_required
|
||||||
def edit_file(username, filename):
|
def edit_file(username, filename):
|
||||||
if current_user.username != username:
|
if current_user.username != username:
|
||||||
return "Unauthorized", 401
|
return "Unauthorized", 401
|
||||||
|
|
||||||
file_path = os.path.join(app.config['UPLOAD_FOLDER'], username, filename)
|
file_path = os.path.join(app.config['UPLOAD_FOLDER'], username, filename)
|
||||||
|
if not os.path.exists(file_path):
|
||||||
|
return "File not found", 404
|
||||||
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
content = request.form['content']
|
content = request.form['content']
|
||||||
with open(file_path, 'w') as file:
|
with open(file_path, 'w') as f:
|
||||||
file.write(content)
|
f.write(content)
|
||||||
return redirect(url_for('user_files', username=username))
|
return redirect(url_for('user_files', username=username))
|
||||||
|
|
||||||
if os.path.exists(file_path) and os.path.isfile(file_path):
|
with open(file_path, 'r') as f:
|
||||||
with open(file_path, 'r') as file:
|
content = f.read()
|
||||||
content = file.read()
|
|
||||||
return render_template('edit_file.html', username=username, filename=filename, content=content)
|
return render_template('edit_file.html', filename=filename, content=content)
|
||||||
else:
|
|
||||||
return "File not found", 404
|
@app.route('/debug/users')
|
||||||
|
def debug_users():
|
||||||
|
db = get_db()
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute("SELECT * FROM users")
|
||||||
|
users = cursor.fetchall()
|
||||||
|
return jsonify(users)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=True, port=7123)
|
app.run(debug=True)
|
||||||
|
@ -2,7 +2,8 @@ CREATE TABLE IF NOT EXISTS content (
|
|||||||
vanity TEXT PRIMARY KEY,
|
vanity TEXT PRIMARY KEY,
|
||||||
type TEXT NOT NULL,
|
type TEXT NOT NULL,
|
||||||
data TEXT NOT NULL,
|
data TEXT NOT NULL,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
user_id INTEGER
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
@ -154,24 +154,29 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>Content</h1>
|
<h2>Content</h2>
|
||||||
{% if created_at %}
|
{% if content.user_id %}
|
||||||
<p>Created at: {{ created_at }}</p>
|
<p>Uploaded by: {{ content.username }}</p>
|
||||||
{% endif %}
|
|
||||||
{% if language %}
|
|
||||||
<p>Detected Language: {{ language }}</p>
|
|
||||||
{% endif %}
|
|
||||||
<div class="button-container">
|
|
||||||
<button id="copy-button" onclick="copyToClipboard()">Copy Raw</button>
|
|
||||||
<a href="{{ url_for('raw_vanity', vanity=vanity) }}" target="_blank"><button>View Raw</button></a>
|
|
||||||
</div>
|
|
||||||
<div class="highlight">
|
|
||||||
{% if highlighted_content %}
|
|
||||||
{{ highlighted_content|safe }}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<pre>{{ content }}</pre>
|
<p>Uploaded by: Anonymous</p>
|
||||||
|
{% endif %}
|
||||||
|
<p>Created at: {{ content.created_at }}</p>
|
||||||
|
|
||||||
|
{% if highlighted_content %}
|
||||||
|
<style>{{ css }}</style>
|
||||||
|
{{ highlighted_content|safe }}
|
||||||
|
{% elif url %}
|
||||||
|
<p>Shortened URL: <a href="{{ url }}">{{ url }}</a></p>
|
||||||
|
{% else %}
|
||||||
|
<pre>{{ raw_content }}</pre>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if current_user.is_authenticated and current_user.id == content.user_id %}
|
||||||
|
<a href="{{ url_for('edit_content', vanity=content.vanity) }}" class="btn">Edit</a>
|
||||||
|
<form action="{{ url_for('delete_content', vanity=content.vanity) }}" method="post" style="display: inline;">
|
||||||
|
<button type="submit" class="btn">Delete</button>
|
||||||
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button id="theme-toggle">Toggle Theme</button>
|
<button id="theme-toggle">Toggle Theme</button>
|
||||||
|
22
templates/edit_content.html
Normal file
22
templates/edit_content.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Edit Content</title>
|
||||||
|
<style>
|
||||||
|
/* ... (use the same style as other pages) ... */
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h2>Edit Content</h2>
|
||||||
|
<form method="post">
|
||||||
|
<textarea name="content" rows="10" cols="50">{{ content.data }}</textarea>
|
||||||
|
<br>
|
||||||
|
<input type="submit" value="Save" class="btn">
|
||||||
|
</form>
|
||||||
|
<a href="{{ url_for('user_files', username=current_user.username) }}" class="btn">Back to Dashboard</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -112,8 +112,13 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<nav>
|
<nav>
|
||||||
|
{% if user %}
|
||||||
|
<a href="{{ url_for('user_files', username=user.username) }}">View Dashboard</a>
|
||||||
|
<a href="{{ url_for('logout') }}">Logout</a>
|
||||||
|
{% else %}
|
||||||
<a href="{{ url_for('login') }}">Login</a>
|
<a href="{{ url_for('login') }}">Login</a>
|
||||||
<a href="{{ url_for('register') }}">Register</a>
|
<a href="{{ url_for('register') }}">Register</a>
|
||||||
|
{% endif %}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="typewriter-container">
|
<div class="typewriter-container">
|
||||||
|
@ -1,6 +1,68 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Login</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
color: #f0f0f0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
.login-container {
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
color: #4CAF50;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #4CAF50;
|
||||||
|
background-color: #333;
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
input[type="submit"] {
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
input[type="submit"]:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
label {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="login-container">
|
||||||
<h2>Login</h2>
|
<h2>Login</h2>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input type="text" name="username" placeholder="Username" required>
|
<input type="text" name="username" placeholder="Username" required>
|
||||||
<input type="password" name="password" placeholder="Password" required>
|
<input type="password" name="password" placeholder="Password" required>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="remember"> Remember Me
|
||||||
|
</label>
|
||||||
<input type="submit" value="Login">
|
<input type="submit" value="Login">
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,6 +1,62 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Register</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
color: #f0f0f0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
.register-container {
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
color: #4CAF50;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #4CAF50;
|
||||||
|
background-color: #333;
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
input[type="submit"] {
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
input[type="submit"]:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="register-container">
|
||||||
<h2>Register</h2>
|
<h2>Register</h2>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input type="text" name="username" placeholder="Username" required>
|
<input type="text" name="username" placeholder="Username" required>
|
||||||
<input type="password" name="password" placeholder="Password" required>
|
<input type="password" name="password" placeholder="Password" required>
|
||||||
<input type="submit" value="Register">
|
<input type="submit" value="Register">
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,21 +1,269 @@
|
|||||||
<h2>{{ username }}'s Files</h2>
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{ username }}'s Dashboard</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
color: #f0f0f0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 800px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
h2, h3 {
|
||||||
|
color: #4CAF50;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
nav {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
nav a, .btn {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
padding: 8px 12px;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 0 5px;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
nav a:hover, .btn:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
form {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
input[type="text"], input[type="file"] {
|
||||||
|
padding: 8px;
|
||||||
|
margin-right: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #4CAF50;
|
||||||
|
background-color: #333;
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
.file-list {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.file-item {
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.file-icon {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.file-name {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
.file-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
.folder {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h2>{{ username }}'s Dashboard</h2>
|
||||||
|
<nav>
|
||||||
|
<a href="{{ url_for('index') }}">Home</a>
|
||||||
|
<a href="{{ url_for('logout') }}">Logout</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<form action="{{ url_for('toggle_index', username=username) }}" method="get" style="text-align: center;">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" onchange="this.form.submit()" {% if ignore_index %}checked{% endif %}>
|
||||||
|
Ignore index.html and always show file listing
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if index_exists and not ignore_index %}
|
||||||
|
<p style="text-align: center;">An index.html file exists in this folder. When viewing publicly, this file will be displayed instead of the file listing.</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<h3>Upload File</h3>
|
||||||
<form action="{{ url_for('upload_user_file', username=username) }}" method="post" enctype="multipart/form-data">
|
<form action="{{ url_for('upload_user_file', username=username) }}" method="post" enctype="multipart/form-data">
|
||||||
|
<input type="hidden" name="subpath" value="{{ current_path }}">
|
||||||
<input type="file" name="file" required>
|
<input type="file" name="file" required>
|
||||||
<input type="submit" value="Upload">
|
<input type="submit" value="Upload" class="btn">
|
||||||
</form>
|
</form>
|
||||||
<ul>
|
|
||||||
{% for file in files %}
|
<h3>Create Folder</h3>
|
||||||
<li>
|
<form action="{{ url_for('create_folder', username=username) }}" method="post">
|
||||||
{{ file }}
|
<input type="hidden" name="subpath" value="{{ current_path }}">
|
||||||
<form action="{{ url_for('delete_user_file', username=username, filename=file) }}" method="post" style="display: inline;">
|
<input type="text" name="folder_name" placeholder="New folder name" required>
|
||||||
<input type="submit" value="Delete">
|
<input type="submit" value="Create Folder" class="btn">
|
||||||
</form>
|
</form>
|
||||||
<form action="{{ url_for('rename_user_file', username=username) }}" method="post" style="display: inline;">
|
|
||||||
<input type="hidden" name="old_filename" value="{{ file }}">
|
<h3>Files and Folders</h3>
|
||||||
<input type="text" name="new_filename" placeholder="New filename" required>
|
<p style="text-align: center;">Current folder: {{ current_folder or 'Root' }}</p>
|
||||||
<input type="submit" value="Rename">
|
|
||||||
</form>
|
<ul class="file-list">
|
||||||
<a href="{{ url_for('edit_file', username=username, filename=file) }}">Edit</a>
|
{% if parent_folder is not none %}
|
||||||
|
<li class="file-item folder">
|
||||||
|
<span class="file-icon">📁</span>
|
||||||
|
<span class="file-name">
|
||||||
|
<a href="{{ url_for('user_files', username=username, subpath=parent_folder) }}">..</a>
|
||||||
|
</span>
|
||||||
|
<div class="file-actions">
|
||||||
|
<!-- No actions for parent directory -->
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% for item in items %}
|
||||||
|
<li class="file-item {% if item.type == 'folder' %}folder{% endif %}">
|
||||||
|
<span class="file-icon">{% if item.type == 'folder' %}📁{% else %}📄{% endif %}</span>
|
||||||
|
<span class="file-name">
|
||||||
|
{% if item.type == 'folder' %}
|
||||||
|
<a href="{{ url_for('user_files', username=username, subpath=item.path) }}">{{ item.name }}</a>
|
||||||
|
{% else %}
|
||||||
|
{{ item.name }}
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
<div class="file-actions">
|
||||||
|
<button onclick="deleteItem('{{ item.name }}', '{{ item.type }}')" class="btn">Delete</button>
|
||||||
|
<button onclick="renameItem('{{ item.name }}', '{{ item.type }}')" class="btn">Rename</button>
|
||||||
|
<button onclick="moveItem('{{ item.name }}', '{{ item.type }}')" class="btn">Move</button>
|
||||||
|
<button onclick="copyItem('{{ item.name }}', '{{ item.type }}')" class="btn">Copy</button>
|
||||||
|
{% if item.type == 'file' %}
|
||||||
|
<a href="{{ url_for('edit_file', username=username, filename=item.path) }}" class="btn">Edit</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<h3>Your Uploads</h3>
|
||||||
|
<ul class="file-list">
|
||||||
|
{% for upload in uploads %}
|
||||||
|
<li class="file-item">
|
||||||
|
<span class="file-icon">
|
||||||
|
{% if upload.type == 'pastebin' %}📝
|
||||||
|
{% elif upload.type == 'file' %}📄
|
||||||
|
{% elif upload.type == 'folder' %}📁
|
||||||
|
{% elif upload.type == 'url' %}🔗
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
<span class="file-name">
|
||||||
|
<a href="{{ url_for('redirect_vanity', path=upload.vanity) }}">{{ upload.vanity }}</a>
|
||||||
|
({{ upload.type }})
|
||||||
|
</span>
|
||||||
|
<div class="file-actions">
|
||||||
|
{% if upload.type in ['pastebin', 'url'] %}
|
||||||
|
<a href="{{ url_for('edit_content', vanity=upload.vanity) }}" class="btn">Edit</a>
|
||||||
|
{% endif %}
|
||||||
|
<form action="{{ url_for('delete_content', vanity=upload.vanity) }}" method="post" style="display: inline;">
|
||||||
|
<button type="submit" class="btn">Delete</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function deleteItem(name, type) {
|
||||||
|
if (confirm(`Are you sure you want to delete this ${type}?`)) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ url_for('delete_user_file', username=username, filename='') }}" + name;
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renameItem(name, type) {
|
||||||
|
const newName = prompt(`Enter new name for this ${type}:`, name);
|
||||||
|
if (newName && newName !== name) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ url_for('rename_user_file', username=username, subpath=current_path) }}";
|
||||||
|
const oldInput = document.createElement('input');
|
||||||
|
oldInput.type = 'hidden';
|
||||||
|
oldInput.name = 'old_filename';
|
||||||
|
oldInput.value = name;
|
||||||
|
const newInput = document.createElement('input');
|
||||||
|
newInput.type = 'hidden';
|
||||||
|
newInput.name = 'new_filename';
|
||||||
|
newInput.value = newName;
|
||||||
|
form.appendChild(oldInput);
|
||||||
|
form.appendChild(newInput);
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveItem(name, type) {
|
||||||
|
const destination = prompt(`Enter destination path for this ${type}:`, '/');
|
||||||
|
if (destination) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ url_for('move_item', username=username, subpath=current_path) }}";
|
||||||
|
const nameInput = document.createElement('input');
|
||||||
|
nameInput.type = 'hidden';
|
||||||
|
nameInput.name = 'item_name';
|
||||||
|
nameInput.value = name;
|
||||||
|
const typeInput = document.createElement('input');
|
||||||
|
typeInput.type = 'hidden';
|
||||||
|
typeInput.name = 'item_type';
|
||||||
|
typeInput.value = type;
|
||||||
|
const destInput = document.createElement('input');
|
||||||
|
destInput.type = 'hidden';
|
||||||
|
destInput.name = 'destination_folder';
|
||||||
|
destInput.value = destination;
|
||||||
|
form.appendChild(nameInput);
|
||||||
|
form.appendChild(typeInput);
|
||||||
|
form.appendChild(destInput);
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyItem(name, type) {
|
||||||
|
const destination = prompt(`Enter destination path to copy this ${type}:`, '/');
|
||||||
|
if (destination) {
|
||||||
|
const form = document.createElement('form');
|
||||||
|
form.method = 'POST';
|
||||||
|
form.action = "{{ url_for('copy_item', username=username, subpath=current_path) }}";
|
||||||
|
const nameInput = document.createElement('input');
|
||||||
|
nameInput.type = 'hidden';
|
||||||
|
nameInput.name = 'item_name';
|
||||||
|
nameInput.value = name;
|
||||||
|
const typeInput = document.createElement('input');
|
||||||
|
typeInput.type = 'hidden';
|
||||||
|
typeInput.name = 'item_type';
|
||||||
|
typeInput.value = type;
|
||||||
|
const destInput = document.createElement('input');
|
||||||
|
destInput.type = 'hidden';
|
||||||
|
destInput.name = 'destination_folder';
|
||||||
|
destInput.value = destination;
|
||||||
|
form.appendChild(nameInput);
|
||||||
|
form.appendChild(typeInput);
|
||||||
|
form.appendChild(destInput);
|
||||||
|
document.body.appendChild(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -16,12 +16,19 @@
|
|||||||
h2 {
|
h2 {
|
||||||
color: #4CAF50;
|
color: #4CAF50;
|
||||||
}
|
}
|
||||||
ul {
|
.file-list {
|
||||||
list-style-type: none;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
li {
|
.file-item {
|
||||||
margin-bottom: 10px;
|
background-color: #2a2a2a;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: #4CAF50;
|
color: #4CAF50;
|
||||||
@ -30,13 +37,34 @@
|
|||||||
a:hover {
|
a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
.folder {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.file-icon {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>{{ username }}'s Files</h2>
|
<h2>{{ username }}'s Files</h2>
|
||||||
<ul>
|
<p>Current folder: {{ current_folder or 'Root' }}</p>
|
||||||
|
|
||||||
|
{% if parent_url is not none %}
|
||||||
|
<p><a href="{{ parent_url }}">Parent Directory</a></p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<ul class="file-list">
|
||||||
|
{% for folder in folders %}
|
||||||
|
<li class="file-item folder">
|
||||||
|
<span class="file-icon">📁</span>
|
||||||
|
<a href="{{ url_for('serve_user_page', username=username, filename=folder.path) }}">{{ folder.name }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
{% for file in files %}
|
{% for file in files %}
|
||||||
<li><a href="{{ url_for('download_folder_file', vanity=username, file_name=file) }}">{{ file }}</a></li>
|
<li class="file-item">
|
||||||
|
<span class="file-icon">📄</span>
|
||||||
|
<a href="{{ url_for('serve_user_page', username=username, filename=file.path) }}">{{ file.name }}</a>
|
||||||
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Python IDE</title><script src="https://cdnjs.cloudflare.com/ajax/libs/brython/3.9.0/brython.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/brython/3.9.0/brython_stdlib.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/codemirror.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/mode/python/python.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/addon/hint/show-hint.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/addon/hint/python-hint.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/codemirror.min.css"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/theme/monokai.min.css"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.62.0/addon/hint/show-hint.css"><style>body{background-color:#1e1e1e;color:#d4d4d4;font-family:'Consolas','Courier New',monospace;margin:0;padding:20px}h1{color:#569cd6}#code{width:100%;height:300px}#output{width:100%;height:200px;background-color:#1e1e1e;border:1px solid #3c3c3c;padding:10px;margin-top:10px;overflow-y:auto;font-family:'Consolas','Courier New',monospace}#run-button,#save-button{background-color:#0e639c;color:white;border:none;padding:10px 20px;margin-top:10px;cursor:pointer}#run-button:hover,#save-button:hover{background-color:#1177bb}.toolbar{margin-bottom:10px}.toolbar button{background-color:#3c3c3c;color:#d4d4d4;border:none;padding:5px 10px;margin-right:5px;cursor:pointer}.toolbar button:hover{background-color:#4e4e4e}</style></head><body onload="brython()"><h1>Python IDE</h1><div class="toolbar"><button id="undo-button">Undo</button><button id="redo-button">Redo</button><button id="save-button">Save</button></div><textarea id="code" placeholder="Enter your Python code here"></textarea><br><button id="run-button">Run</button><div id="output"></div><script type="text/python">from browser import document,window
|
|
||||||
import sys
|
|
||||||
class _0x1234:
|
|
||||||
def __init__(_0x5678):_0x5678._0x9abc=document["output"]
|
|
||||||
def write(_0x5678,_0xdef0):_0x5678._0x9abc.innerHTML+=_0xdef0
|
|
||||||
sys.stdout=_0x1234()
|
|
||||||
sys.stderr=_0x1234()
|
|
||||||
def _0x2345(_0x6789):
|
|
||||||
document["output"].innerHTML=""
|
|
||||||
_0xabcd=window.editor.getValue()
|
|
||||||
try:exec(_0xabcd)
|
|
||||||
except Exception as _0xef01:print(f"Error: {str(_0xef01)}")
|
|
||||||
document["run-button"].bind("click",_0x2345)
|
|
||||||
def _0x3456(_0x789a):window.editor.undo()
|
|
||||||
def _0x4567(_0x89ab):window.editor.redo()
|
|
||||||
document["undo-button"].bind("click",_0x3456)
|
|
||||||
document["redo-button"].bind("click",_0x4567)
|
|
||||||
def _0x5678(_0x9abc):
|
|
||||||
_0xbcde=window.editor.getValue()
|
|
||||||
_0xcdef=window.Blob.new([_0xbcde],{'type':'text/plain'})
|
|
||||||
_0xdef0=window.URL.createObjectURL(_0xcdef)
|
|
||||||
_0xef01=document.createElement('a')
|
|
||||||
_0xef01.href=_0xdef0
|
|
||||||
_0xef01.download='python_code.py'
|
|
||||||
_0xef01.click()
|
|
||||||
window.URL.revokeObjectURL(_0xdef0)
|
|
||||||
document["save-button"].bind("click",_0x5678)</script><script>var _0x1234=CodeMirror.fromTextArea(document.getElementById("code"),{mode:"python",theme:"monokai",lineNumbers:!0,autoCloseBrackets:!0,matchBrackets:!0,indentUnit:4,tabSize:4,indentWithTabs:!1,extraKeys:{"Ctrl-Space":"autocomplete","Tab":function(_0x5678){_0x5678.somethingSelected()?_0x5678.indentSelection("add"):_0x5678.replaceSelection(_0x5678.getOption("indentWithTabs")?"\t":Array(_0x5678.getOption("indentUnit")+1).join(" "),"end","+input")}},hintOptions:{completeSingle:!1}});_0x1234.on("inputRead",function(_0x2345,_0x3456){if("+input"===_0x3456.origin){var _0x4567=_0x2345.getCursor(),_0x5678=_0x2345.getTokenAt(_0x4567);("variable"===_0x5678.type||"."===_0x5678.string)&&_0x2345.showHint({completeSingle:!1})}})</script></body></html>
|
|
Loading…
Reference in New Issue
Block a user