You've received inputs now from the terminal or command prompt. But most of your users may not have direct access to your server (if they do, that could be *very* dangerous!). Instead, they will likely be filling out forms on a website, and you will be receiving the information they fill out, and doing something with it.
- [[#A Little HTML is Needed]]
- [[#Perl makes the HTML Document]]
# A Little HTML is Needed
In order to do this, let's learn an extremely small amount of HTML. This is not proper instruction in that language, but it will be enough to achieve our next goal - receiving user inputs from whatever they enter in a form on their browser.
Like Perl's *shebang*, you must tell the browser you are giving it an HTML document (even if it isn't called an `.html` file, if you tell it to treat it like HTML, it will).
``` html
<!DOCTYPE html>
```
There is more HTML that we would normally use, but for our purposes we will use only a few tags, `<html></html>`, `<body></body>`, `<form></form>`, `<button></button>`, `<br>` and `<input>`.
- `<html></html>`, `<body></body>`, `<form></form>` and `<button></button>` are **container** tags. Stuff goes inside them.
- `<html></html>` contains the entire contents of the document.
- `<body></body>` contains the things that appear in the viewport (the screen)
- `<form></form>` is a container of things a user can interact with (fields, buttons, etc.)
- `<button></button>` is a container that a user can click on. Its contents are what appears in the button.
- `<br>` and `<input>` are **inline** tags. They place an object at the point you place them.
- `<br>` is HTML's equivalent of Perl's `\n`, a newline
- `<input>` is an object that can be a field for text, a checkbox, a radio button, and many other interactive items
## A sample HTML document with a form
``` html
<!DOCTYPE html>
<html>
<body>
<form method="POST" action="https://learn.ndcfinearts.ca/myID/cgi-bin/form.cgi" id="MyForm">
Enter your name: <input form="MyForm" type="text" name="yourName"> <br>
<button form="MyForm" type="submit" name="submitButton" value="1">Submit</button>
</form>
</body>
</html>
```
Notice how many tags have "attribute", items that equal something. We can use that information in Perl
- `method="POST"` tells the HTML that when the user submits the form, the data will be [[Client vs. Server Side#Server-Side Processing|POSTed]] to the server. In particular, it will POST it to the script you identify in `action`.
- `form="MyForm"` just tells the HTML that the `<input>` and `<button>` belong to the `<form>` with that id "attribute".
- `<input>` and `<button>` tags have
- `type` tags that tell it how to behave.
- `name` and `value` tags which will be important for our Perl code (the value of the `<input>` is provided by the user, they will type something into the textbox).
# Perl makes the HTML Document
When someone requests data from your script, your script doesn't just look for an HTML document give back. Instead, your script is going to create the HTML document, then send it, rather than the server just handing over an already-made HTML document.
## HTTP Headers
You will be sending your information over the [[NDC Coding/CSE1110 - Structured Programming I/Protocols of the World Wide Web#HTTP – Hypertext Transfer Protocol – “The Internet Protocol”|HTTP]] Protocol, so you will need to send **HTTP Headers** that will tell the Client the basics about the kind of data you're sending. Therefore you need Perl to make those HTTP Headers. The most important one, the one that says you're sending data the Client should treat like HTML, is as follows;
``` perl
print "Content-type: text/html\n\n";
```
The double newline `\n\n` is what separates anything else you print from the HTTP Header (the Client will be looking for that double newline so that it knows where the real file starts).
Other file MIME types include `text/plain`, `application/pdf`, `audio/mp3` and hundreds more, so it's important you tell the Client what to expect.
## Now for the HTML
If you have a real HTML file, it would look like the [[#A sample HTML document with a form|sample above]]. But you're making Perl create one for you, so you need to tell your Perl script to virtually "type" the file for you.
``` perl
print "<!DOCTYPE html>\n";
print "<html>\n";
print " <body>\n";
print " Hello\n";
print " </body>\n";
print "</html>\n";
```
The Client would see the following, know that it is supposed to receive HTML, look for the HTML shebang to confirm, and then print the HTML. The browser would then turn that HTML into something nice for the user.
``` text
Content-type: text/html
<!DOCTYPE html>
<html>
<body>
Hello
</body>
</html>
```
# Receiving Data from POST
Most requests to get a specific web page are [[Client vs. Server Side#Server-Side Processing|GET]] requests, because all it wants to do is "get" the file so it can show it. When a user submits an HTML form, it sends a [[Client vs. Server Side#Server-Side Processing|POST]] request to the target script, your script, instead.
The script ingests whatever information it gets from that `POST` request into [[STDIN]]. However it comes in a special format that you will need to interpret in order to get what you want out of it.
``` text
noun1=apple&verb1=sing&noun2=mouse&past_tense_verb1=fell
```
**SECURITY CHECK:** A hacker can sneak extra data in beyond what the form is supposed to send. To stop your script from letting a hacker sneak information in, we use a special command: `read`. As part of that command, we limit the information we get to the data the form says we're supposed to get, and not allow any more.
``` perl
read(STDIN, $postedData, $ENV{'CONTENT_LENGTH'});
```
This command reads the data in `STDIN`, stores it in `$postedData` but stores a maximum amount of data according to what the form said it's supposed to send, identified by the **environment variable** `$ENV{'CONTENT_LENGTH'}`.
Now `$postedData = "noun1=apple&verb1=sing&noun2=mouse&past_tense_verb1=fell"`.
## split
That data includes a bunch of `key=value` pairs. To get those pairs by themselves without the ampersands (`&`) we need to split them apart. To do so, we use Perl's `split` command.
``` perl
@pairs = split('&', $postedData);
```
This looks for the ampersand (`&`) everywhere in the data we received inside `$postedData` and splits it apart into a whole bunch of scalars that now sit inside `@pairs`. So `@pairs` now looks like this:
``` text
noun1=apple
verb1=sing
noun2=mouse
past_tense_verb=fell
```
However we still don't have any scalars that simply say "apple", "sing", "mouse" or "fell" yet. We know what we would want them called, but we haven't actually made them. So we'll add them to a [[NDC Coding/CSE1110 - Structured Programming I/Perl Explained#Hashes (also known as Objects or Collections)|hash]] using `split` once again to separate the *key* from its *value*.
First we make the hash:
``` perl
%FORM = ();
```
Then we traverse through all the `@pairs` we already created above. As we move through the `@pairs` we split each `$pair` into its *key* and *value* using `split`, this time on the equals sign (`=`). After we've done that, we add the *key* and *value* into the `%FORM` hash, one *scalar reference* at a time.
``` perl
for $pair (@pairs) { # Call whatever pair we're looking at $pair
chomp($pair); # get rid of any sneaky newlines \n
($key, $value) = split('=', $pair);
# example: $key = noun1, $value = apple
$FORM{$key} = $value; # now $FORM{'noun1'} = 'apple'
}
```
Now we can print any of those pieces of data we want, like so;
``` perl
print $FORM{'verb1'};
print " about a ";
print $FORM{'noun2'};
print " who ";
print $FORM{'past_tense_verb'};
print " on an ";
print $FORM{'noun1'};
# sing about a mouse who fell on an apple
```
# Assignment
You previously created a Mad Lib that could be completed from the terminal. Now create an HTML Form that lets a user enter their prompts, and a Perl script that will receive their responses and produce a full and complete Mad Lib.