From 2e119ab7dfe121b50cad5b2607ae9c6c17fd2b27 Mon Sep 17 00:00:00 2001 From: aneuhmanh Date: Thu, 6 Mar 2025 16:54:32 +0200 Subject: [PATCH] minor upload changes --- app.py | 49 +++++++++++++++++++++++++++++++++------ templates/comic_edit.html | 3 ++- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/app.py b/app.py index 1dab931..7530040 100644 --- a/app.py +++ b/app.py @@ -27,6 +27,7 @@ from flask_wtf import FlaskForm, RecaptchaField from dotenv import load_dotenv, find_dotenv import aiofiles.os from sqlalchemy import func, or_ +import magic dotenv_path = find_dotenv() load_dotenv(dotenv_path, override=True) @@ -66,6 +67,12 @@ def check_file_size(file, max_size): file.seek(0) return file_size <= max_size +def check_file_content(file, allowed_mime_types): + mime = magic.Magic(mime=True) + file_mime_type = mime.from_buffer(file.read(1024)) + file.seek(0) + return file_mime_type in allowed_mime_types + db = SQLAlchemy(app) bcrypt = Bcrypt(app) login_manager = LoginManager(app) @@ -583,26 +590,35 @@ async def upload(): if form.validate_on_submit(): image_file = form.image_file.data tags = form.tags.data + allowed_mime_types = {'image/png', 'image/jpeg', 'image/gif', 'image/webp'} + if not (allowed_file(image_file.filename, app.config['ALLOWED_IMAGE_EXTENSIONS']) and + check_file_content(image_file, allowed_mime_types) and await check_file_size(image_file, app.config['MAX_IMAGE_SIZE'])): return redirect(url_for('upload')) + unique_filename = f"{uuid.uuid4().hex}.webp" filepath = os.path.join(app.config['UPLOAD_FOLDER']['images'], unique_filename) if os.path.exists(filepath): return redirect(url_for('upload')) + webp_image = await convert_to_webp(image_file) async with aiofiles.open(filepath, 'wb') as f: await f.write(webp_image.read()) + img = Image(image_file=unique_filename, username=current_user.username, tags=tags, cookie_votes=0) db.session.add(img) + user_cookie = Cookies.query.filter_by(username=current_user.username).first() if user_cookie: user_cookie.cookies += 1 else: user_cookie = Cookies(username=current_user.username, cookies=1) db.session.add(user_cookie) + db.session.commit() return redirect(url_for('index')) + return render_template('upload.html', form=form) def allowed_file(filename, allowed_extensions): @@ -647,12 +663,17 @@ async def upload_video(): tags = form.tags.data description = form.description.data + allowed_video_mime_types = {'video/mp4', 'video/x-msvideo', 'video/quicktime'} + allowed_image_mime_types = {'image/png', 'image/jpeg', 'image/gif', 'image/webp'} + if video_file and video_thumbnail: - if not allowed_file(video_file.filename, app.config['ALLOWED_VIDEO_EXTENSIONS']): + if not (allowed_file(video_file.filename, app.config['ALLOWED_VIDEO_EXTENSIONS']) and + check_file_content(video_file, allowed_video_mime_types)): return redirect(url_for('upload_video')) if not await check_file_size(video_file, app.config['MAX_VIDEO_SIZE']): return redirect(url_for('upload_video')) - if not allowed_file(video_thumbnail.filename, app.config['ALLOWED_IMAGE_EXTENSIONS']): + if not (allowed_file(video_thumbnail.filename, app.config['ALLOWED_IMAGE_EXTENSIONS']) and + check_file_content(video_thumbnail, allowed_image_mime_types)): return redirect(url_for('upload_video')) video_filename = await generate_unique_filename(app.config['UPLOAD_FOLDER']['videos'], 'mp4') @@ -698,10 +719,16 @@ async def comic_upload(): n = request.form['title'] tags = request.form.get('tags', '') + allowed_image_mime_types = {'image/png', 'image/jpeg', 'image/gif', 'image/webp'} + if db.session.execute(db.select(Comic).filter_by(name=n)).scalar(): return render_template('comic_upload.html') if ct: + if not (allowed_file(ct.filename, app.config['ALLOWED_IMAGE_EXTENSIONS']) and + check_file_content(ct, allowed_image_mime_types)): + return redirect(url_for('comic_upload')) + tf = f"{uuid.uuid4().hex}.webp" tp = os.path.join(app.config['UPLOAD_FOLDER']['comicthumbs'], tf) webp_thumbnail = await convert_to_webp(ct) @@ -725,6 +752,10 @@ async def comic_upload(): pages = request.files.getlist('pages[]') for i, p in enumerate(sorted(pages, key=lambda x: x.filename), start=1): if p: + if not (allowed_file(p.filename, app.config['ALLOWED_IMAGE_EXTENSIONS']) and + check_file_content(p, allowed_image_mime_types)): + return redirect(url_for('comic_upload')) + filename = f"{uuid.uuid4().hex}.webp" file_path = os.path.join(cf, filename) webp_page = await convert_to_webp(p) @@ -1039,7 +1070,7 @@ class EmptyForm(FlaskForm): @app.route('/comic_edit/', methods=['GET', 'POST']) @login_required -def comic_edit(comic_id): +async def comic_edit(comic_id): comic = Comic.query.get_or_404(comic_id) if comic.username != current_user.username: @@ -1063,9 +1094,11 @@ def comic_edit(comic_id): elif action == 'update' and (page_id := request.form.get('page')) and 'new_page' in request.files: new_page = request.files['new_page'] - filename = secure_filename(new_page.filename) + filename = f"{uuid.uuid4().hex}.webp" file_path = os.path.join(cfp, filename) - new_page.save(file_path) + webp_image = await convert_to_webp(new_page) + async with aiofiles.open(file_path, 'wb') as f: + await f.write(webp_image.read()) page = ComicPage.query.get(page_id) if page: @@ -1075,9 +1108,11 @@ def comic_edit(comic_id): elif action == 'add' and 'new_page' in request.files: new_page = request.files['new_page'] - filename = secure_filename(new_page.filename) + filename = f"{uuid.uuid4().hex}.webp" file_path = os.path.join(cfp, filename) - new_page.save(file_path) + webp_image = await convert_to_webp(new_page) + async with aiofiles.open(file_path, 'wb') as f: + await f.write(webp_image.read()) page_number = (db.session.query(db.func.max(ComicPage.page_number)).filter_by(comic_id=comic.id).scalar() or 0) + 1 db.session.add(ComicPage(comic_id=comic.id, page_number=page_number, file_path=file_path)) diff --git a/templates/comic_edit.html b/templates/comic_edit.html index 3575338..5025089 100644 --- a/templates/comic_edit.html +++ b/templates/comic_edit.html @@ -7,6 +7,7 @@ + 🫐comic edit - artberry🫐 @@ -25,7 +26,7 @@