diff --git a/files/helpers/sanitize.py b/files/helpers/sanitize.py index aa4a2d3cad..73d5eb5200 100644 --- a/files/helpers/sanitize.py +++ b/files/helpers/sanitize.py @@ -264,7 +264,7 @@ def remove_cuniform(sanitized): if not sanitized: return "" sanitized = sanitized.replace('\u200e','').replace('\u200b','').replace('\u202e','').replace("\ufeff", "").replace("\u033f","").replace("\u0589", ":") sanitized = sanitized.replace("𒐪","").replace("𒐫","").replace("﷽","").replace("⸻","") - sanitized = sanitized.replace("\r\n", "\n") + sanitized = sanitized.replace("\r", "") sanitized = sanitized.replace("’", "'") return sanitized.strip() diff --git a/files/routes/chat.py b/files/routes/chat.py index 2ee4583150..3bd7db97d9 100644 --- a/files/routes/chat.py +++ b/files/routes/chat.py @@ -256,8 +256,9 @@ atexit.register(close_running_threads) @limiter.limit("6/minute;50/hour;200/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def messagereply(v): - body = request.values.get("body", "") - body = body[:COMMENT_BODY_LENGTH_LIMIT].strip() + body = request.values.get("body", "").strip() + if len(body) > COMMENT_BODY_LENGTH_LIMIT: + abort(400, f'Message is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)!') id = request.values.get("parent_id") parent = get_comment(id, v=v) @@ -290,7 +291,8 @@ def messagereply(v): if not g.is_tor and get_setting("dm_media"): body = process_files(request.files, v, body, is_dm=True, dm_user=user) - body = body[:COMMENT_BODY_LENGTH_LIMIT].strip() #process_files potentially adds characters to the post + if len(body) > COMMENT_BODY_LENGTH_LIMIT: + abort(400, f'Message is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)!') if not body: abort(400, "Message is empty!") diff --git a/files/routes/comments.py b/files/routes/comments.py index 37747ea813..5316c3e7d3 100644 --- a/files/routes/comments.py +++ b/files/routes/comments.py @@ -165,8 +165,10 @@ def comment(v): if level > COMMENT_MAX_DEPTH: abort(400, f"Max comment level is {COMMENT_MAX_DEPTH}") - body = request.values.get("body", "") - body = body[:COMMENT_BODY_LENGTH_LIMIT].strip() + body = request.values.get("body", "").strip() + if len(body) > COMMENT_BODY_LENGTH_LIMIT: + abort(400, f'Comment body is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)!') + if not posting_to_post or post_target.id not in ADMIGGER_THREADS: if v.longpost and (len(body) < 280 or ' [](' in body or body.startswith('[](')): @@ -242,8 +244,9 @@ def comment(v): else: abort(415) - body = body.replace('\n ', '\n').replace('\r', '') - body = body[:COMMENT_BODY_LENGTH_LIMIT].strip() + body = body.strip() + if len(body) > COMMENT_BODY_LENGTH_LIMIT: + abort(400, f'Comment body is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)!') if v.admin_level >= PERMS['USE_ADMIGGER_THREADS'] and posting_to_post and post_target.id == SNAPPY_THREAD and level == 1: with open(f"snappy_{SITE_NAME}.txt", "r+") as f: @@ -653,8 +656,9 @@ def edit_comment(cid, v): if not c.parent_post and not c.wall_user_id: abort(403) - body = request.values.get("body", "") - body = body[:COMMENT_BODY_LENGTH_LIMIT].strip() + body = request.values.get("body", "").strip() + if len(body) > COMMENT_BODY_LENGTH_LIMIT: + abort(400, f'Comment body is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)!') if len(body) < 1 and not (request.files.get("file") and not g.is_tor): abort(400, "You have to actually type something!") @@ -668,7 +672,8 @@ def edit_comment(cid, v): execute_antispam_comment_check(body, v) body = process_files(request.files, v, body) - body = body[:COMMENT_BODY_LENGTH_LIMIT].strip() # process_files potentially adds characters to the post + if len(body) > COMMENT_BODY_LENGTH_LIMIT: + abort(400, f'Comment body is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)!') body_html = sanitize(body, golden=False, limit_pings=5, showmore=(not v.hieroglyphs), commenters_ping_post_id=c.parent_post, obj=c, author=c.author) diff --git a/files/routes/oauth.py b/files/routes/oauth.py index 0dd5bfdd39..ebfe370e25 100644 --- a/files/routes/oauth.py +++ b/files/routes/oauth.py @@ -57,11 +57,15 @@ def rescind(v, aid): @limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID) @auth_required def request_api_keys(v): + description = request.values.get("description", "").strip() + if len(description) > 256: + abort(400, 'App description is too long (max 256 characters)!') + new_app = OauthApp( app_name=request.values.get('name').replace('<','').replace('>',''), redirect_uri=request.values.get('redirect_uri'), author_id=v.id, - description=request.values.get("description")[:256] + description=description, ) g.db.add(new_app) @@ -115,7 +119,12 @@ def edit_oauth_app(v, aid): app.redirect_uri = request.values.get('redirect_uri') app.app_name = request.values.get('name') - app.description = request.values.get("description")[:256] + + description = request.values.get("description", "").strip() + if len(description) > 256: + abort(400, 'App description is too long (max 256 characters)!') + + app.description = description g.db.add(app) diff --git a/files/routes/posts.py b/files/routes/posts.py index be4ecfbfd3..f97c8885a3 100644 --- a/files/routes/posts.py +++ b/files/routes/posts.py @@ -461,11 +461,13 @@ def submit_post(v, hole=None): if '\\' in url: abort(400) - title = request.values.get("title", "") - title = title[:POST_TITLE_LENGTH_LIMIT].strip() + title = request.values.get("title", "").strip() + if len(title) > POST_TITLE_LENGTH_LIMIT: + abort(400, f'Post title is too long (max {POST_TITLE_LENGTH_LIMIT} characters)!') - body = request.values.get("body", "") - body = body[:POST_BODY_LENGTH_LIMIT(g.v)].strip() + body = request.values.get("body", "").strip() + if len(body) > POST_BODY_LENGTH_LIMIT(g.v): + abort(400, f'Post body is too long (max {POST_BODY_LENGTH_LIMIT(g.v)} characters)!') if not title: abort(400, "Please enter a better title!") @@ -551,8 +553,9 @@ def submit_post(v, hole=None): if len(url) > 2048: abort(400, "There's a 2048 character limit for URLs!") - body = process_files(request.files, v, body) - body = body[:POST_BODY_LENGTH_LIMIT(v)].strip() # process_files() adds content to the body, so we need to re-strip + body = process_files(request.files, v, body).strip() + if len(body) > POST_BODY_LENGTH_LIMIT(g.v): + abort(400, f'Post body is too long (max {POST_BODY_LENGTH_LIMIT(g.v)} characters)!') flag_notify = (request.values.get("notify", "on") == "on") flag_new = request.values.get("new", False, bool) or 'megathread' in title.lower() @@ -1011,11 +1014,13 @@ def edit_post(pid, v): and v.admin_level < PERMS["IGNORE_1MONTH_EDITING_LIMIT"] and v.id not in EXEMPT_FROM_1MONTH_EDITING_LIMIT: abort(403, "You can't edit posts older than 1 month!") - title = request.values.get("title", "") - title = title[:POST_TITLE_LENGTH_LIMIT].strip() + title = request.values.get("title", "").strip() + if len(title) > POST_TITLE_LENGTH_LIMIT: + abort(400, f'Post title is too long (max {POST_TITLE_LENGTH_LIMIT} characters)!') - body = request.values.get("body", "") - body = body[:POST_BODY_LENGTH_LIMIT(g.v)].strip() + body = request.values.get("body", "").strip() + if len(body) > POST_BODY_LENGTH_LIMIT(g.v): + abort(400, f'Post body is too long (max {POST_BODY_LENGTH_LIMIT(g.v)} characters)!') if p.author.longpost and (len(body) < 280 or ' [](' in body or body.startswith('[](')): abort(403, "You have to type more than 280 characters!") @@ -1049,8 +1054,9 @@ def edit_post(pid, v): p.title = title p.title_html = title_html - body = process_files(request.files, v, body) - body = body[:POST_BODY_LENGTH_LIMIT(v)].strip() # process_files() may be adding stuff to the body + body = process_files(request.files, v, body).strip() + if len(body) > POST_BODY_LENGTH_LIMIT(g.v): + abort(400, f'Post body is too long (max {POST_BODY_LENGTH_LIMIT(g.v)} characters)!') if body != p.body or p.chudded: body_html = sanitize(body, golden=False, limit_pings=100, obj=p, author=p.author) diff --git a/files/routes/settings.py b/files/routes/settings.py index 63f254d1a0..1b0e0d90c8 100644 --- a/files/routes/settings.py +++ b/files/routes/settings.py @@ -247,7 +247,7 @@ def settings_personal_post(v): sig = request.values.get("sig").replace('\n','').replace('\r','').strip() sig = process_files(request.files, v, sig) - sig = sig.strip() # process_files potentially adds characters to the post + sig = sig.strip() if len(sig) > 200: abort(400, "New signature is too long (max 200 characters)") @@ -262,14 +262,13 @@ def settings_personal_post(v): return {"message": "Your sig has been updated."} elif not updated and FEATURES['USERS_PROFILE_BODYTEXT'] and request.values.get("friends"): - friends = request.values.get("friends")[:BIO_FRIENDS_ENEMIES_LENGTH_LIMIT] + friends = request.values.get("friends", "").strip() + if len(friends) > BIO_FRIENDS_ENEMIES_LENGTH_LIMIT: + abort(400, f'Ypur friend list is too long (max {BIO_FRIENDS_ENEMIES_LENGTH_LIMIT} characters)!') friends_html = sanitize(friends, blackjack="friends") - if len(friends_html) > BIO_FRIENDS_ENEMIES_HTML_LENGTH_LIMIT: - abort(400, "Your friends list is too long") - - friends = friends[:BIO_FRIENDS_ENEMIES_LENGTH_LIMIT] + abort(400, "Your friend list is too long") notify_users = NOTIFY_USERS(friends, v, oldtext=v.friends) if notify_users: @@ -296,14 +295,13 @@ def settings_personal_post(v): elif not updated and FEATURES['USERS_PROFILE_BODYTEXT'] and request.values.get("enemies"): - enemies = request.values.get("enemies")[:BIO_FRIENDS_ENEMIES_LENGTH_LIMIT] + enemies = request.values.get("enemies", "").strip() + if len(enemies) > BIO_FRIENDS_ENEMIES_LENGTH_LIMIT: + abort(400, f'You enemy list is too long (max {BIO_FRIENDS_ENEMIES_LENGTH_LIMIT} characters)!') enemies_html = sanitize(enemies, blackjack="enemies") - if len(enemies_html) > BIO_FRIENDS_ENEMIES_HTML_LENGTH_LIMIT: - abort(400, "Your enemies list is too long") - - enemies = enemies[:BIO_FRIENDS_ENEMIES_LENGTH_LIMIT] + abort(400, "Your enemy list is too long") notify_users = NOTIFY_USERS(enemies, v, oldtext=v.enemies) if notify_users: @@ -329,18 +327,16 @@ def settings_personal_post(v): return {"message": "Your enemies list has been updated."} - elif not updated and FEATURES['USERS_PROFILE_BODYTEXT'] and \ - (request.values.get("bio") or request.files.get('file')): - bio = request.values.get("bio", "")[:BIO_FRIENDS_ENEMIES_LENGTH_LIMIT] + elif not updated and FEATURES['USERS_PROFILE_BODYTEXT'] and (request.values.get("bio") or request.files.get('file')): + bio = request.values.get("bio", "").strip() bio = process_files(request.files, v, bio) - bio = bio.strip() - bio_html = sanitize(bio, blackjack="bio") + if len(bio) > BIO_FRIENDS_ENEMIES_LENGTH_LIMIT: + abort(400, f'Your bio is too long (max {BIO_FRIENDS_ENEMIES_LENGTH_LIMIT} characters)!') + bio_html = sanitize(bio, blackjack="bio") if len(bio_html) > BIO_FRIENDS_ENEMIES_HTML_LENGTH_LIMIT: abort(400, "Your bio is too long") - - v.bio = bio[:BIO_FRIENDS_ENEMIES_LENGTH_LIMIT] v.bio_html=bio_html g.db.add(v) return {"message": "Your bio has been updated."} diff --git a/files/routes/users.py b/files/routes/users.py index 9c845b2a86..0b3813e7c1 100644 --- a/files/routes/users.py +++ b/files/routes/users.py @@ -597,12 +597,14 @@ def message(v, username=None, id=None): if user.has_muted(v): abort(403, f"@{user.username} is muting notifications from you, so messaging them is pointless!") - body = request.values.get("message", "") - body = body[:COMMENT_BODY_LENGTH_LIMIT].strip() + body = request.values.get("message", "").strip() + if len(body) > COMMENT_BODY_LENGTH_LIMIT: + abort(400, f'Message is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)!') if not g.is_tor and get_setting("dm_media"): body = process_files(request.files, v, body, is_dm=True, dm_user=user) - body = body[:COMMENT_BODY_LENGTH_LIMIT].strip() #process_files potentially adds characters to the post + if len(body) > COMMENT_BODY_LENGTH_LIMIT: + abort(400, f'Message is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)!') if not body: abort(400, "Message is empty!")