Skip to content

Commit

Permalink
Normalize line endings in form submissions
Browse files Browse the repository at this point in the history
Fixes #506
  • Loading branch information
rubenwardy committed Jun 22, 2024
1 parent d6e25f3 commit da090fd
Show file tree
Hide file tree
Showing 10 changed files with 29 additions and 21 deletions.
4 changes: 2 additions & 2 deletions app/blueprints/admin/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@

from app.markdown import render_markdown
from app.tasks.emails import send_user_email, send_bulk_email as task_send_bulk
from app.utils import rank_required, add_audit_log
from app.utils import rank_required, add_audit_log, normalize_line_endings
from . import bp
from app.models import UserRank, User, AuditSeverity


class SendEmailForm(FlaskForm):
subject = StringField("Subject", [InputRequired(), Length(1, 300)])
text = TextAreaField("Message", [InputRequired()])
text = TextAreaField("Message", [InputRequired()], filters=[normalize_line_endings])
submit = SubmitField("Send")


Expand Down
4 changes: 2 additions & 2 deletions app/blueprints/admin/languageseditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from wtforms.validators import InputRequired, Length, Optional

from app.models import db, AuditSeverity, UserRank, Language, Package, PackageState, PackageTranslation
from app.utils import add_audit_log, rank_required
from app.utils import add_audit_log, rank_required, normalize_line_endings
from . import bp


Expand All @@ -38,7 +38,7 @@ def language_list():

class LanguageForm(FlaskForm):
id = StringField("Id", [InputRequired(), Length(2, 10)])
title = TextAreaField("Title", [Optional(), Length(2, 100)])
title = TextAreaField("Title", [Optional(), Length(2, 100)], filters=[normalize_line_endings])
submit = SubmitField("Save")


Expand Down
4 changes: 2 additions & 2 deletions app/blueprints/admin/tagseditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

from . import bp
from app.models import Permission, Tag, db, AuditSeverity
from app.utils import add_audit_log
from app.utils import add_audit_log, normalize_line_endings


@bp.route("/tags/")
Expand All @@ -44,7 +44,7 @@ def tag_list():

class TagForm(FlaskForm):
title = StringField("Title", [InputRequired(), Length(3, 100)])
description = TextAreaField("Description", [Optional(), Length(0, 500)])
description = TextAreaField("Description", [Optional(), Length(0, 500)], filters=[normalize_line_endings])
name = StringField("Name", [Optional(), Length(1, 20), Regexp("^[a-z0-9_]", 0,
"Lower case letters (a-z), digits (0-9), and underscores (_) only")])
submit = SubmitField("Save")
Expand Down
4 changes: 2 additions & 2 deletions app/blueprints/admin/warningseditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import InputRequired, Length, Optional, Regexp

from app.utils import rank_required
from app.utils import rank_required, normalize_line_endings
from . import bp
from app.models import UserRank, ContentWarning, db

Expand All @@ -33,7 +33,7 @@ def warning_list():

class WarningForm(FlaskForm):
title = StringField("Title", [InputRequired(), Length(3, 100)])
description = TextAreaField("Description", [Optional(), Length(0, 500)])
description = TextAreaField("Description", [Optional(), Length(0, 500)], filters=[normalize_line_endings])
name = StringField("Name", [Optional(), Length(1, 20),
Regexp("^[a-z0-9_]", 0, "Lower case letters (a-z), digits (0-9), and underscores (_) only")])
submit = SubmitField("Save")
Expand Down
4 changes: 2 additions & 2 deletions app/blueprints/collections/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from wtforms.validators import InputRequired, Length, Optional, Regexp

from app.models import Collection, db, Package, Permission, CollectionPackage, User, UserRank, AuditSeverity
from app.utils import nonempty_or_none
from app.utils import nonempty_or_none, normalize_line_endings
from app.utils.models import is_package_page, add_audit_log, create_session

bp = Blueprint("collections", __name__)
Expand Down Expand Up @@ -78,7 +78,7 @@ class CollectionForm(FlaskForm):
name = StringField("URL", [Optional(), Length(1, 20), Regexp("^[a-z0-9_]", 0,
"Lower case letters (a-z), digits (0-9), and underscores (_) only")])
short_description = StringField(lazy_gettext("Short Description"), [Optional(), Length(0, 200)])
long_description = TextAreaField(lazy_gettext("Page Content"), [Optional()], filters=[nonempty_or_none])
long_description = TextAreaField(lazy_gettext("Page Content"), [Optional()], filters=[nonempty_or_none, normalize_line_endings])
private = BooleanField(lazy_gettext("Private"))
pinned = BooleanField(lazy_gettext("Pinned to my profile"))
descriptions = FieldList(
Expand Down
5 changes: 3 additions & 2 deletions app/blueprints/packages/packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
PackageScreenshot, NotificationType, AuditLogEntry, PackageAlias, PackageProvides, PackageGameSupport, \
PackageDailyStats, Collection
from app.utils import is_user_bot, get_int_or_abort, is_package_page, abs_url_for, add_audit_log, get_package_by_info, \
add_notification, get_system_user, rank_required, get_games_from_csv, get_daterange_options, post_to_approval_thread
add_notification, get_system_user, rank_required, get_games_from_csv, get_daterange_options, \
post_to_approval_thread, normalize_line_endings
from app.logic.package_approval import validate_package_for_approval, can_move_to_state
from app.logic.game_support import game_support_set

Expand Down Expand Up @@ -238,7 +239,7 @@ class PackageForm(FlaskForm):
license = QuerySelectField(lazy_gettext("License"), [DataRequired()], allow_blank=True, query_factory=lambda: License.query.order_by(db.asc(License.name)), get_pk=lambda a: a.id, get_label=lambda a: a.name)
media_license = QuerySelectField(lazy_gettext("Media License"), [DataRequired()], allow_blank=True, query_factory=lambda: License.query.order_by(db.asc(License.name)), get_pk=lambda a: a.id, get_label=lambda a: a.name)

desc = TextAreaField(lazy_gettext("Long Description (Markdown)"), [Optional(), Length(0,10000)])
desc = TextAreaField(lazy_gettext("Long Description (Markdown)"), [Optional(), Length(0,10000)], filters=[normalize_line_endings])

repo = StringField(lazy_gettext("VCS Repository URL"), [Optional(), URL()], filters = [lambda x: x or None])
website = StringField(lazy_gettext("Website URL"), [Optional(), URL()], filters = [lambda x: x or None])
Expand Down
4 changes: 2 additions & 2 deletions app/blueprints/packages/reviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
Permission, AuditSeverity, PackageState, Language
from app.tasks.webhooktasks import post_discord_webhook
from app.utils import is_package_page, add_notification, get_int_or_abort, is_yes, is_safe_url, rank_required, \
add_audit_log, has_blocked_domains, should_return_json
add_audit_log, has_blocked_domains, should_return_json, normalize_line_endings
from . import bp


Expand Down Expand Up @@ -57,7 +57,7 @@ class ReviewForm(FlaskForm):
get_pk=lambda a: a.id,
get_label=lambda a: a.title,
default=get_default_language)
comment = TextAreaField(lazy_gettext("Comment"), [InputRequired(), Length(10, 2000)])
comment = TextAreaField(lazy_gettext("Comment"), [InputRequired(), Length(10, 2000)], filters=[normalize_line_endings])
rating = RadioField(lazy_gettext("Rating"), [InputRequired()],
choices=[("5", lazy_gettext("Yes")), ("3", lazy_gettext("Neutral")), ("1", lazy_gettext("No"))])
btn_submit = SubmitField(lazy_gettext("Save"))
Expand Down
4 changes: 2 additions & 2 deletions app/blueprints/report/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@
from app.models import User, UserRank
from app.tasks.emails import send_user_email
from app.tasks.webhooktasks import post_discord_webhook
from app.utils import is_no, abs_url_samesite
from app.utils import is_no, abs_url_samesite, normalize_line_endings

bp = Blueprint("report", __name__)


class ReportForm(FlaskForm):
message = TextAreaField(lazy_gettext("Message"), [InputRequired(), Length(10, 10000)])
message = TextAreaField(lazy_gettext("Message"), [InputRequired(), Length(10, 10000)], filters=[normalize_line_endings])
submit = SubmitField(lazy_gettext("Report"))


Expand Down
10 changes: 5 additions & 5 deletions app/blueprints/threads/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@

from flask import Blueprint, request, render_template, abort, flash, redirect, url_for
from flask_babel import gettext, lazy_gettext
from sqlalchemy import or_
from sqlalchemy.orm import selectinload, joinedload
from sqlalchemy.orm import selectinload

from app.markdown import get_user_mentions, render_markdown
from app.tasks.webhooktasks import post_discord_webhook
Expand All @@ -27,7 +26,8 @@
from flask_login import current_user, login_required
from app.models import Package, db, User, Permission, Thread, UserRank, AuditSeverity, \
NotificationType, ThreadReply
from app.utils import add_notification, is_yes, add_audit_log, get_system_user, has_blocked_domains
from app.utils import add_notification, is_yes, add_audit_log, get_system_user, has_blocked_domains, \
normalize_line_endings
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField, BooleanField
from wtforms.validators import InputRequired, Length
Expand Down Expand Up @@ -178,7 +178,7 @@ def delete_reply(id):


class CommentForm(FlaskForm):
comment = TextAreaField(lazy_gettext("Comment"), [InputRequired(), Length(2, 2000)])
comment = TextAreaField(lazy_gettext("Comment"), [InputRequired(), Length(2, 2000)], filters=[normalize_line_endings])
btn_submit = SubmitField(lazy_gettext("Comment"))


Expand Down Expand Up @@ -279,7 +279,7 @@ def view(id):

class ThreadForm(FlaskForm):
title = StringField(lazy_gettext("Title"), [InputRequired(), Length(3,100)])
comment = TextAreaField(lazy_gettext("Comment"), [InputRequired(), Length(10, 2000)])
comment = TextAreaField(lazy_gettext("Comment"), [InputRequired(), Length(10, 2000)], filters=[normalize_line_endings])
private = BooleanField(lazy_gettext("Private"))
btn_submit = SubmitField(lazy_gettext("Open Thread"))

Expand Down
7 changes: 7 additions & 0 deletions app/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ def nonempty_or_none(str):
return str


def normalize_line_endings(value: Optional[str]) -> Optional[str]:
if value is None:
return None

return value.replace("\r\n", "\n").strip() + "\n"


def should_return_json():
return "application/json" in request.accept_mimetypes and \
not "text/html" in request.accept_mimetypes
Expand Down

0 comments on commit da090fd

Please sign in to comment.