Comp 150-001, TTh, 11:00-2:00, DH-339, Class 9

HTML Forms and responses

When you request an html file, either explicitly through a url such as foo.com/bar.html or implicitly as foo.com/baz, where baz is a directory containing index.html, all the server does is sends the html file to you. Your browser then figures out what are the embedded items (eg images) that also have to be requested. Some limited server-side processing of html files is possible (usually with the extension .shtml): the server can dynamically paste in or otherwise alter the page.

However, true dynamic pages are usually done with the full-scale involvement of some programming language, either server-side or client-side. Any time a web page can invoke a program, there are security concerns; neither the server side nor the client side should fully trust the other. If the program runs on the server, then it must be carefully analyzed to be sure that it cannot be misused by the client to gain access to the server or the server data in unintended ways. If the program runs on the client, then the client has all sorts of concerns because that program is provided by the server, and once a program is running it can potentially do pretty much whatever it wants to the client machine. This issue of trusting programs received from elsewhere is much more general than on the web, of course; the same issue arises with freeware, embedded "macros", and other software; all viruses begin with someone running (knowingly or not) a program from somewhere else that they should not have trusted.

The oldest and simplest dynamic-page mechanism is cgi (common gateway interface), which works server-side. If a file is requested that ends in .cgi, the server treats it as an executable program. The server then runs the program and sends back the output, the program must be written so that its output is proper html. Sometimes no parameters are involved, eg when the cgi program just retrieves current status information from the server. However, in most cases the program is run in response to data entered by the user on a form. A form is an html structure defined by the <form> tag, specifying various fields and buttons to be sent to the server, and also the name of the cgi script to be run in response. Forms must choose between the "get" method (simplest) and the "post" method; this is done with the attribute method="get". All forms must supply the action and method attributes.

Between the <form> tag and the closing </form>, any html can be included (often, but not always, the entire document). Form-specific html includes <input> tags; each input has a type attribute (button, radio, checkbox, text, etc), and can be assigned a name attribute and an initial-value attribute. Other form-specific tags are select, for menu selections, and textarea, for large chunks of text. A special kind of button, typically placed near the end, is <input type="submit">; when this is clicked, the form is submitted to the server, which means all those input entries are mashed up into a long URL and sent to the server. There, the URL is decoded and the values are made available to the cgi program.

We'll stick with server-side processing here, using each individual workstation as its own server. Our scripts are pretty limited; the chance that someone else can use them to gain unintended access is very slim. A more serious risk is that a runaway script could tie up the machine, but on your workstation you have authority to halt a badly performing cgi script (kill it with the task manager).

Here's a first example of a form:
    <form action="age.cgi" method="get" enctype="multipart/form-data">
    <p>This is a form: please input your name & address<br></strong>
    name:<input name="name"><br>
    address:<input name="addr"><br>
    age:<input name="age"><br>
    <input type="submit">
    </p>
    </form>

Here's now a python script that could serve as age.cgi:

    import cgi

    def main():
        form = cgi.FieldStorage()
        name = form.getfirst("name", "no name")
        addr = form.getfirst("addr", "nowhere")
        ageStr = form.getfirst("age", "0")
        age=int(ageStr)
        age=age+5
        ageStr=str(age)
        print "Name: ", name.upper(), " Address: " + addr.upper(), "<br>"
        # <br> makes html newline
        print "In five years you will be", ageStr, "years old"

    try:
         print "Content-type: text/html\n\n"
         main()
    except:
         cgi.print_exception()

If I enter my name as "Peter", my address as "Shabbona", and my age as "52", then the URL request is
    http://localhost:8000/formdemos/age/age.cgi?name=Peter&addr=Shabbona&age=52
Note the '?' that begins the parameter section, following the script name age.cgi. The parameters are of the form name=value, where the name comes from the name attribute of the input tags, and the value comes from what was entered (in the cases here, entered in the text box). (The post alternative to the get method basically puts the parameters in the message body rather than in the URL; it is more suitable for very long parameters such as file uploads.)

The def main(): part of the cgi file just defines main(). It is the try: part that actually calls it; the except: part is then invoked if a problem was encountered. If we were sure we wouldn't have an error, we could just include the print and main() at the end.

What happens if we leave off a parameter in the string above? Or add an extra one?

Note that the python program does indeed generate html, through print statements.

Python cgi interface

You start with this:
    form1 = cgi.fieldStorage()
This causes the form to be read from the browser response, and returned in an object, here named "form1". You do this only once.

Now you can refer to fields dictionary-style, by their name attribute: form1["name1"], etc. (Note that we haven't covered python dictionaries yet.) However, there's no reason you might not have used the same name for multiple form elements (for radio buttons, you sort of have to). Therefore, getfirst and getlist (used above) are often considered safer. Which to use depends on whether the value is a single item or a list; you have to know the context to determine that.

form1["myname"] would return a list of field values if there were more than one named "myname"; form.getfirst("myname") always returns the first one and form.getlist("myname") always returns the list. It will return a list of a single entry, if that's what it is.

Demos for age:



form1: exhaustive demo of common form elements. Note how text-box data is handled with <textarea>.

All of these "widgets" can have the name= attribute, and all but textarea can have the value= attribute. (You specify the default text in a <textarea> by enclosing it between the tags. Although you can use default names, generally everything is given a name; all names except for radio button names are unique (radio buttons with the same name form a group; when you click one member of a group, the previously clicked button is unclicked.)
  
text
<input type="text" ...> size=n (width)
button
<input type="button" ...>
kind of useless in cgi; needs javascript!
submit
<input type="submit">
special button to submit your form data
radio
<input type="radio" ...>
group them by giving them the same name
checkbox
<input type="checkbox" ..."
checked
menu
<select> <option value=...> ... </select>
size=n (height), multiple
text area
<textarea> ... </textarea>
rows=n, cols=n

Here's a summary of form options: http://www.echoecho.com/htmlforms15.htm.

The button type isn't as useful as you might think, except for the required submit form. For the <select> (menu) option, we can further specify a drop-down menu (size=1) or a scrolling list (any larger value for size), and whether we're allowed to select multiple items or just one.

What can forms do?

Form1: note that buttons don't do anything.
    don't use form["key"] format; it doesn't work as expected (demo?)
    use getfirst, getlist
  
calc

calc2:   

calc3: 
   

color:
demo: add error-checking function to print out the color string that's too long

boldify:
def boldify(big, small):
    pos = big.find(small);
    epos = pos + len(small)
    return big[0:pos]+"<b>" + small + "</b>" + big[epos:]

demo: add <big>,</big> tags too



Security

CGI scripts run on the server side. Another popular option (that would work for our script demos here, but not if we needed access to a central database) is to run scripts on the client side. Client-side scripting is usually done with the JavaScript or Java programming languages. (Note that JavaScript has nothing to do with Java; Microsoft has another name for JavaScript entirely that doesn't involve the J-word.) Microsoft's misbegotten ActiveX controls are another form of client-side processing. All client-side methods pose a major security risk to the user: maybe they will do something you don't want! When you view a web page or open a word-processor file, what could go wrong? Now suppose your word-processor doc has startup macros, scripts included in the document by the author that run when the document is opened, or the web page launches a javascript program on the client.

These programs can potentially:

server-side:

client-side:

Role of java in program security (to some extent, javascript has adopted a similar strategy)
    -- defines a "sandbox" on the client in which it is safe to run untrusted programs. Access to the client machine's filesystem, for example, is forbidden.


=======================================

Reprise of why foreign programs are hard to trust
Microsoft: ActiveX controls. These are like Java Applets, but they have full access to your local machine: there are no restrictions built into the language, and the OS does not impose access restrictions (eg limited user privileges)
   
They are, however, SIGNED.

JavaScript v VBScript ... Sheesh

Footnote: ActiveX presumably violates Patent 5,838,906, known colloquially as "906", an extremely broad patent from 1993 that purports to cover anything that appears within a window. MS once modified windows to get around the patent, but has apparently now negotiated another arrangement.

The Stack

When one function calls another, we need to save the current Program Counter somewhere (representing the address we return to), and then either the called or the caller must save any registers that must be reused. One approach is for each function to set aside some chunk of memory for that purpose. However, this disallows recursion: having a function call itself.

The stack is a chunk of memory onto which we can push values, and then later pop them off, in (more-or-less) strict last-in-first-out order. The active end of the stack is typically held in a register called the stack pointer, or SP. The idea is that the caller pushes the PC onto the stack; when the called function is done it pops off the return address and branches to it. Any function parameters are also pushed onto the stack.

In order to allow recursion, each separate "invocation" of a function has to have its local variables in a separate place. This leads to using the stack to hold all local variables as well, in a stack frame. A second register, called the frame pointer, points to the current stack frame (this allows SP to grow further for such things as dynamically created local space).

Example:
    def fact(n):
       if n==1: return 1
       else return n* fact(n-1)

Let's follow the evaluation of fact(4), as called from the main python interaction loop. We push the parameter 4 and the main-loop return address.

As n=4, not 1, we then call fact(3), leading us to push the parameter 3 and the return address inside of fact() where we will resume.

This leads to calling fact(2); we push the parameter 2 and the same return address in fact(). The same thing happens when we call fact(1).

But fact(1) doesn't call anything further; it just returns 1. We now return to the fact(2) instance, having evaluated fact(1)=1; we return 2*1.

This returns us to the fact(3) instance, with fact(2)=2. We compute 3*2, and return that to the fact(4) instance.

This returns us to the fact(4) instance, with fact(3)=6. We compute 4*6=24, and return that now to the python top level.

Stacks don't require any special hardware support; any registers can be used for the Stack Pointer and Frame Pointer. However, if interrupts are to be handled by pushing the current state onto the stack, then SP does have to be designated in hardware. Most systems since the 1970s take this approach.

Buffer Overflow Attacks

Smashing the stack for fun and profit.