#!/usr/bin/python
###############################################################################
# formProcess:  Process an HTML form 
#
#      1. Mail the content of the form, if an email address is provided
#         either at the end of URL, or as a hidden field in the form. 
#         such as:  <form ..... action=http://..../formProcess.cgi/email@addr>   
#           or as:  <input type=hidden name=_email value="email@addr">
#
#      2. Save the content of the form in a file, if a file is specified
#         as a hidden field in the form. The file name should have absolute path.
#         such as:  <input type=hidden name=_file value="/home/students/userid/data.txt">
#
#      3. Redirect to another html page, if a redirect url is specified
#         as a hidden field in the form. The url should be an absolute url.
#         such as:  <input type=hidden name=_redirect value="http://....">  
###############################################################################
import os                               #for environment variables
import re                               #for regex
import subprocess                       #for unix mail command
import datetime                         #for date and time
import cgi                              #cgi 
import cgitb                            #cgi with traceback error handling
 
cgitb.enable()

elements   = cgi.FieldStorage()         #obtain the http form parameters
fieldnames = elements.keys()            #get all the form field names
fieldnames.sort()                       #sort them
 
###############################################################################
# mailData:  If email address is specified,
#                then mail the form data to the e-mail address.
###############################################################################
def mailData():

    email = os.environ.get('PATH_INFO') or ' ';     #get email addr from end of URL
    email = email[1:]                               #strip out first '/'

    email = elements.getvalue('_email') or \
            elements.getvalue('_EMAIL') or \
            email                                   #if none, take if from end of URL 

    if (not email): return                          #exit if no email specified
 
    from_email = 'Web-Server'
    to_email   = email
    subject    = 'Form Element Content'
    body       = 'Your Form Elements and Values are: \n'

    for name in fieldnames:
        if re.match('(?i)(_email|_file|_redirect)', name):      #if _email, _file or _redirect (ignore case)  
            continue                                            #skip
        value = elements.getvalue(name)
        name  = name.upper()
        body += F'{name}: {value} \n'

    body = body.replace(chr(13),'')                             #remove all \r characters (ascii 13) 
    body = bytes(body, 'utf-8')                                 #convert string to bytes-array (required for mail pgm)
    
    try:
        process = subprocess.Popen(['/usr/bin/mailx', '-r', from_email, '-s', subject, to_email], stdin=subprocess.PIPE)
        process.communicate(body)
    except Exception as error:
       print("Content-type: text/html \n")
       print("Could not send email -" , error)
       exit()
 
###############################################################################
# saveData: If a file is specified,
#               then save the form data in the file  
###############################################################################
def saveData():
     
    file = elements.getvalue('_file') or \
           elements.getvalue('_FILE')               #get _file name from form param  
    
    if (not file): return                           #exit if no file specified

    now = datetime.datetime.now()                   #current date and time
    body = F'{now} \n'              

    for name in fieldnames:
        if re.match('(?i)(_email|_file|_redirect)', name):      #if _email, _file or _redirect (ignore case)  
            continue                                            #skip
        value = elements.getvalue(name)
        name  = name.upper()
        body += F'{name}: {value} \n'

    body += "---------- END ----------\n" 

    try:    
        f = open(file , 'a')                        #open the file
        f.write(body)                               #write
        f.close()                                   #close file
    except Exception as error:
       print("Content-type: text/html \n")
       print("Could not send email -" , error)
       exit()
 
###############################################################################
# printHTML: If a redirect is specified, 
#                 then redirect to the requested URL
#                 else generate a simple output HTML page
###############################################################################
def printHTML():
 
    redirect = elements.getvalue('_redirect') or \
               elements.getvalue('_REDIRECT')           #get _redirect url from form   

    if (redirect):                                      #if a redirect is requested
        print(f"Location: {redirect} \n")               #create HTTP Location header
        return

    print("Content-type: text/html \n")
    print();

    print("""
        <HTML>
        <HEAD>
        <TITLE>Thank you</TITLE>
        </HEAD>
        <BODY>
        <H2 ALIGN=center>Thank you for your submission</H2>
        <TABLE BORDER=2 ALIGN=center>
    """)
 
    for name in fieldnames:
        print(F'<tr><td VALIGN=top> {name} </b><td> \n')
        value = elements.getvalue(name)
        if type(value) is str:                          #a single value 
            print(F' {value} <br>')
        else:                                           #a list of values       
            for val in value:                       
                print(F' {val} <br>')
 
    print("""
        </TABLE>
        </BODY>
        </HTML>
    """)
 
###############################################################################
# main code
###############################################################################

mailData();                                  # Call mailData to e-mail

saveData();                                  # Call saveData to save data

printHTML();                                 # Call printHTML to print HTML