CS1116/CS5018

Web Development 2

Dr Derek Bridge

School of Computer Science & Information Technology

University College Cork

Revision: A question about HTML

Two server-side programs that expect user input

challenge.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Challenge</title>
    </head>
    <body>
        <p>
            Halt! Who goes there?
        </p>
        <form action="response.py" method="get">
            <input type="text" name="firstname" />
            <input type="text" name="surname" />
            <input type="submit" />
        </form>
    </body>
</html>

response.py

#!/usr/local/bin/python3

from cgitb import enable
enable()

from cgi import FieldStorage

print('Content-Type: text/html')
print()

form_data = FieldStorage()
fname = form_data.getfirst('firstname')
sname = form_data.getfirst('surname')

print("""
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <title>Challenge</title>
        </head>
        <body>
            <p>
                Hello, %s %s. You may go on your way.
            </p>
        </body>
    </html>""" % (fname, sname))

Questions about response.py

A better version of response.py

#!/usr/local/bin/python3

from cgitb import enable
enable()

from cgi import FieldStorage

print('Content-Type: text/html')
print()

form_data = FieldStorage()
fname = form_data.getfirst('firstname', '').strip()
sname = form_data.getfirst('surname', '').strip()

outcome = ''
if fname and sname:
    outcome = 'Hello, %s %s. You may go on your way.' % (fname, sname)
else:
    outcome = 'You did not enter a first name and a surname. You are under arrest.'

print("""
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <title>Challenge</title>
        </head>
        <body>
            <p>
                %s
            </p>
        </body>
    </html>""" % (outcome))

User data that contains HTML tags

A script injection attack

An even better version of response.py

#!/usr/local/bin/python3

from cgitb import enable
enable()

from cgi import FieldStorage
from html import escape

print('Content-Type: text/html')
print()

form_data = FieldStorage()
fname = escape(form_data.getfirst('firstname', '').strip())
sname = escape(form_data.getfirst('surname', '').strip())

outcome = ''
if fname and sname:
    outcome = 'Hello, %s %s. You may go on your way.' % (fname, sname)
else:
    outcome = 'You did not enter a first name and a surname. You are under arrest.'

print("""
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <title>Challenge</title>
        </head>
        <body>
            <p>
                %s
            </p>
        </body>
    </html>""" % (outcome))

bmi.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>BMI</title>
    </head>
    <body>
        <form action="bmi.py" method="get">
            <label for="mass_kg">Mass (kg): </label>
            <input type="text" name="mass_kg" id="mass_kg" />
            <label for="height_m">Height (m): </label>
            <input type="text" name="height_m" id="height_m" />
            <input type="submit" value="Calculate BMI" />
        </form>
    </body>
</html>

bmi.py

#!/usr/local/bin/python3

from cgitb import enable
enable()

from cgi import FieldStorage

print('Content-Type: text/html')
print()

form_data = FieldStorage()
mass_kg = float(form_data.getfirst('mass_kg'))
height_m = float(form_data.getfirst('height_m'))
bmi = mass_kg / (height_m * height_m)
category = ''
if bmi < 18.5:
    category = 'underweight'
elif bmi > 25:
    category ='overweight'
else:
    category = 'normal'

print("""
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <title>BMI</title>
        </head>
        <body>
            <p>
                Your mass in kg is %.1f. Your height in m is %.1f. 
                Your BMI is %.2f. You are %s.
            </p>
        </body>
    </html>""" % (mass_kg, height_m, bmi, category))

Questions about bmi.py

Ways to test for a decimal number

A better version of bmi.py

#!/usr/local/bin/python3

from cgitb import enable
enable()

from cgi import FieldStorage

print('Content-Type: text/html')
print()

form_data = FieldStorage()
mass_kg = form_data.getfirst('mass_kg', '').strip()
height_m = form_data.getfirst('height_m', '').strip()

outcome = ''
try:
    mass_kg = float(mass_kg)
    height_m = float(height_m)
    bmi = mass_kg / (height_m * height_m)
    category = ''
    if bmi < 18.5:
        category = 'underweight'
    elif bmi > 25:
        category ='overweight'
    else:
        category = 'normal'
    outcome = """Your mass in kg is %.1f. Your height in m is %.1f. 
                 Your BMI is %.2f. You are %s.""" % (mass_kg, height_m, bmi, category)
except ValueError:
    outcome = 'You should enter numbers for your weight and height.'

print("""
    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="utf-8" />
            <title>BMI</title>
        </head>
        <body>
            <p>
                %s                
            </p>
        </body>
    </html>""" % (outcome))

Notes