2020-07-18 13:10:03 +00:00
from flask_wtf import FlaskForm
2020-08-25 13:02:48 +03:00
from wtforms import StringField , SubmitField , TextAreaField , ValidationError
2020-08-21 12:17:17 +03:00
from wtforms . validators import DataRequired , Length , Optional
2020-07-20 16:53:18 +00:00
from tiny0 . config import WEBSITE_DOMAIN
2020-08-21 12:17:17 +03:00
from tiny0 import db
from tiny0 . models import URL
2020-07-18 13:10:03 +00:00
2020-08-22 15:36:09 +03:00
# Validates a url
2020-07-18 16:40:51 +00:00
def validate_URL ( form , field ) :
# Make sure the url is not too short or long
if len ( field . data ) < 4 or len ( field . data ) > 2000 :
2020-07-19 22:14:49 +00:00
return
2020-07-18 13:10:03 +00:00
2020-07-18 16:40:51 +00:00
# If the url contains spaces or does not have any dots
2020-07-23 17:07:21 +00:00
if ( " " in field . data ) or not ( " . " in field . data ) :
2020-07-18 16:40:51 +00:00
# Raise a ValidationError
2020-07-19 20:01:03 +00:00
raise ValidationError ( " Invalid URL " )
2020-07-18 13:10:03 +00:00
2020-07-18 21:50:47 +00:00
# If the url starts with a dot after http:// or after https:// or just starts with a dot
2020-08-16 21:35:02 +03:00
if field . data . lower ( ) . startswith ( " http://. " ) or field . data . lower ( ) . startswith ( " https://. " ) or field . data . startswith ( " . " ) :
2020-07-18 21:50:47 +00:00
# Raise a ValidationError
2020-07-19 20:01:03 +00:00
raise ValidationError ( " Invalid URL " )
2020-07-18 21:50:47 +00:00
2020-07-23 16:57:16 +00:00
# If the url starts with a slash after http:// or after https:// or just starts with a slash
2020-08-16 21:35:02 +03:00
if field . data . lower ( ) . startswith ( " http:/// " ) or field . data . lower ( ) . startswith ( " https:/// " ) or field . data . startswith ( " / " ) :
2020-07-23 16:57:16 +00:00
# Raise a ValidationError
raise ValidationError ( " Invalid URL " )
2020-07-18 21:50:47 +00:00
# If the url ends with a dot and it is the only dot
if field . data . endswith ( " . " ) and field . data . count ( " . " ) == 1 :
# Raise a ValidationError
2020-07-19 20:01:03 +00:00
raise ValidationError ( " Invalid URL " )
2020-07-18 21:50:47 +00:00
2020-07-20 16:53:18 +00:00
# If the url contains the websites domain
2020-08-16 21:35:02 +03:00
if WEBSITE_DOMAIN in field . data . lower ( ) :
2020-08-21 12:17:17 +03:00
# Raise a ValidationError
2020-08-19 16:31:22 +03:00
raise ValidationError ( " Invalid URL " )
2020-07-20 16:53:18 +00:00
2020-07-18 16:40:51 +00:00
# If the URL does not start with http:// and https://
2020-08-16 21:35:02 +03:00
if not ( field . data . lower ( ) . startswith ( " http:// " ) ) and not ( field . data . lower ( ) . startswith ( " https:// " ) ) :
2020-07-20 18:55:07 +00:00
# Add http:// to the beginning of the URL
field . data = " http:// " + field . data
2020-07-18 16:40:51 +00:00
2020-08-21 12:17:17 +03:00
# Validates a token
def validate_token ( form , field ) :
# Make sure the token is not too short or long
if len ( field . data ) < 6 or len ( field . data ) > 16 :
return
2020-08-21 18:05:30 +03:00
# If the token is the same as a pages route
2020-08-24 15:25:42 +03:00
if field . data == " tracker " or field . data == " lookup " or field . data == " report " or field . data == " donate " :
2020-08-21 18:05:30 +03:00
# Raise a ValidationError
raise ValidationError ( " Token already exists " )
2020-08-21 12:17:17 +03:00
# For each character in the token
for char in field . data :
# If it is not a valid character
if not ( char . isalpha ( ) ) and not ( char . isdigit ( ) ) and not ( char == " _ " ) and not ( char == ' - ' ) :
# Raise a ValidationError
raise ValidationError ( " Token contains invalid characters " )
# If the token exists in the database
if db . session . query ( db . session . query ( URL ) . filter_by ( token = field . data ) . exists ( ) ) . scalar ( ) :
# Raise a ValidationError
raise ValidationError ( " Token already exists " )
2020-08-22 15:36:09 +03:00
# Validates a short url
def validate_short_URL ( form , field ) :
# Make sure the short url is not too short or long
if len ( field . data ) < ( len ( WEBSITE_DOMAIN ) + 7 ) or len ( field . data ) > ( len ( WEBSITE_DOMAIN ) + 25 ) :
return
# If the start of the short url is not valid
if ( not ( field . data . lower ( ) . startswith ( WEBSITE_DOMAIN + " / " ) )
and not ( field . data . lower ( ) . startswith ( " http:// " + WEBSITE_DOMAIN + " / " ) )
and not ( field . data . lower ( ) . startswith ( " https:// " + WEBSITE_DOMAIN + " / " ) ) ) :
# Raise a ValidationError
raise ValidationError ( " Invalid short URL " )
# Get the token of the short url
if field . data . lower ( ) . startswith ( WEBSITE_DOMAIN + " / " ) :
token = field . data [ len ( WEBSITE_DOMAIN ) + 1 : ]
elif field . data . lower ( ) . startswith ( " http:// " + WEBSITE_DOMAIN + " / " ) :
token = field . data [ len ( WEBSITE_DOMAIN ) + 8 : ]
elif field . data . lower ( ) . startswith ( " https:// " + WEBSITE_DOMAIN + " / " ) :
token = field . data [ len ( WEBSITE_DOMAIN ) + 9 : ]
# If the token of the short url does not exist in the database
if not db . session . query ( db . session . query ( URL ) . filter_by ( token = token ) . exists ( ) ) . scalar ( ) :
# Raise a ValidationError
raise ValidationError ( " That short URL does not exists " )
# After all the validation is done set the forms url value as the token
field . data = token
2020-07-18 16:40:51 +00:00
class URLForm ( FlaskForm ) :
2020-08-22 15:36:09 +03:00
url = StringField ( validators = [ DataRequired ( ) , Length ( min = 4 , max = 2000 , message = " Invalid URL length " ) , validate_URL ] )
2020-07-18 16:40:51 +00:00
2020-08-21 12:17:17 +03:00
token = StringField ( validators = [ Optional ( ) , Length ( min = 6 , max = 16 , message = " Invalid token length " ) , validate_token ] )
2020-07-18 23:39:18 +00:00
submit = SubmitField ( " Shorten " )
2020-08-22 15:36:09 +03:00
2020-08-25 12:11:00 +03:00
class ShortURLForm ( FlaskForm ) :
2020-08-22 15:36:09 +03:00
url = StringField ( validators = [ DataRequired ( ) , Length ( min = len ( WEBSITE_DOMAIN ) + 7 , max = len ( WEBSITE_DOMAIN ) + 25 , message = " Invalid short URL " ) , validate_short_URL ] )
2020-08-25 13:02:48 +03:00
submit = SubmitField ( " Submit " )
class ReportForm ( FlaskForm ) :
url = StringField ( validators = [ DataRequired ( ) , Length ( min = len ( WEBSITE_DOMAIN ) + 7 , max = len ( WEBSITE_DOMAIN ) + 25 , message = " Invalid short URL " ) , validate_short_URL ] )
message = TextAreaField ( validators = [ DataRequired ( ) , Length ( 1 , 200 , message = " Message too short or too long " ) ] )
submit = SubmitField ( " Submit " )