Using HTML Forms to pass data to PHP

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Atli
    Recognized Expert Expert
    • Nov 2006
    • 5062

    Using HTML Forms to pass data to PHP

    Introduction
    At some point, all web developers will need to collect data from their users. In a dynamic web page, everything revolves around the users input, so knowing how to ask for and collect this data is essential to any developer.
    This article is a basic tutorial on how to user HTML Forms, the most common method of data collection.

    Assumptions
    - Basic HTML knowledge.
    - Basic PHP knowledge.

    HTML Forms
    A common and simple way of gathering data is through HTML Forms. Forms are containers for user input and can contain any number of different input types.
    The HTML form element requires a few parameters to work properly:
    • action: this should point to the page that is meant to process the collected data. As soon as the form is submitted, the browser is redirected to this location, along with all your data.
    • method: this is the method of transportation. There are two choices here: 'GET' and 'POST'. I will cover them both in the next chapter.

    A typical form element might look like this:
    [code=html]
    <form id="Form1" action="submit. php" method="post">
    <!-- Input elements will be put here -->
    </form>
    [/code]


    The data delivery methods, GET and POST.
    As you may have guessed from the names of the two protocols, the GET and POST requests are designed for different purposes.

    The purspose of the GET protocol is to fetch and display data to the user. Simple key-value pairs can be passed via the query string, but they should ideally be used to specify what should be displayed on the page, rather than to push user data onto the server.

    That is what the POST protocol is for. It is designed to allow clients to send pretty much any amount of data to the server, in pretty much any format. This is what most forms should be using, and it is required for things like file uploads and to upload large amounts of text.

    Essentially, GET should be used for navigation and things of that nature, but POST should be used to send actual data. Now lets examine them in more detail, individually.

    The GET protocol
    When using GET, the data from the form is encoded into the URL of the request. For example, if you were to submit this form:
    [code=html]<form action="action. php" method="get">
    <input type="text" name="Username" value="John"><b r>
    <input type="password" name="Password" value="thePassw ord"><br>
    <input type="submit">
    </form>[/code]

    When you hit the submit button, the browser would redirect you to this URL:
    - action.php?User name=John&Passs word=thePasswor d

    A very usefult aspect of the GET protocol is the fact that we do not have to use a form to submit GET data. The URL can be manually constructed as well, and the server will not see any difference. Which means that the above data can also be submitted using the following HTML link:
    [CODE=html]<a href="action.ph p?Username=John &Passsword=theP assword">Submit </a>[/CODE]
    This can be extremely usefuel in websites that show dynamically created content, such as forums or blogs, where you often need to create dynamic navigation links. In fact, this is used in most dynamic web 2.0 applications out there.

    The POST protocol
    The data submitted via the POST protocol is not visible in the URL. The data itself is put into the body of the request, which allows POST requests to upload more data, and more complex data, than the GET request.

    For example, to send a username and an image, you would use a form like this:
    [CODE=html]<form action="action. php" method="post" enctype="multip art/form-data">
    <input type="text" name="Username" ><br>
    <input type="file" name="UserImage ">
    <input type="submit">
    </form>[/CODE]

    You will notice there that an additional attribute has been added to the form. The "enctype" attribute is required when sending files. If it is missing, the files will not be sent. - This attribute simply tells the client how to format the body of the request. By default it is a fairly simple format, but to send a binary object, a more complex one is required.

    The <input> element
    Like all forms, HTML forms need fields for the user to fill out. This is what the <input> element is for.
    Input elements are positioned inside the <form> element, and can be used as a number of different types of fields. The type is set by chaning the "type" attribute of the field to one of the following values:
    • text: This is a simple text box. Allows users to input any text.
    • password: This is similar to the "text" input, except this is meant for passwords. The text is obfuscated, so the actual text you type into it is not visible. (Usually by replacing each character with an asterisk.)
    • button: This creates a button. It has no special purpose. It's mostly used to execute JavaScript code.
    • submit: This forms a button that when clicked, submits the form. If you specify a name and a value, they will be included in the data. Otherwise not.
    • reset: This forms a button that resets all the fields in the form. Use with caution!
    • checkbox: This creates a checkbox. Only boxes that have been checked will be sent along with the data. Unchecked boxes will be disregarded.
    • radio: This creates a radio button. If you create a number of these with the same name, only one of them can be selected at any given time, and only the selected one will be included with the data. The "value" attribute of the selected box will be sent.
    • hidden: This field is not displayed. It is hidden, but its value will be sent. These are highly useful when you need to include a value from your PHP or JavaScript code, but don't want it visible to the user.
    • file: This type allows a file to be selected and uploaded to the server.

    A simple example of a form populated with input elements:
    [code=html]<form id="Form1" action="submit. php" method="post">
    Username: <input type="text" name="Username" ><br>
    Password: <input type="password" name="Password" ><br>
    Remember me: <input type="checkbox" name="Remember" checked="checke d">
    <input type="hidden" name="SubmitChe ck" value="sent">
    <input type="Submit" name="Form1_Sub mit" value="Login">
    </form>[/code]

    Reading the form data
    To read the data submitted by a form, using PHP, we use one of three special arrays. Those are: $_GET, $_POST or $_REQUEST. The first two contain the data submitted via their respective protocols. The third, $_REQUEST contains the data from both.

    The index(key) of the array is the name property of the input element. So if we were to send the form we created earlier, we could print the Username you passed like this:
    Code:
    echo $_POST['Username'];
    If you are lazy you can just call "$_REQUEST['Username']" instead, but it comes at a price. Depending on your PHP configuration either the $_GET or $_POST array supersedes the other, overriding duplicate values. That means that if both the POST and GET protocols send a value with the same name, one of them will not be available, and you risk using the incorrect value in your code. - And to make matters worse, the Cookie and Enviromental variables are also thrown into the mix, increasing the risk even further.

    The moral of this story is: use the $_GET and $_POST arrays, rather than the $_REQUEST array. It's safest that way.

    Using the collected data
    Before we finish, let's make a simple example, using our login form from before.

    This form tests for the username 'John' and the password 'Doe' and responds accordingly. - Note, that I have changed the 'action' property of the form to point to itself, which will cause the page to reload, along with the data.
    [code=php]
    <?php
    /**
    * WARNING!
    * This EXAMPLE code contains severe SECURITY ISSUES
    * which should be addressed before real-life usage!!
    *
    * These issues have been ignored intentionally to
    * simplify the code so we can focus on the topic
    * in discussion.
    */

    // Lets test if the form has been submitted
    if(isset($_POST['SubmitCheck'])) {
    // The form has been submited
    // Check the values!
    if($_POST['Username'] == "John" and $_POST['Password'] == "Doe") {
    // User validated!
    echo "Thats right! You have been logged in!";

    // Check if the checkbox was checked
    if(isset($_POST['Remember'])) {
    echo "<br>You will be remembered!";
    }
    else {
    echo "<br>John who?!";
    }
    }
    else {
    // User info invalid!
    echo "Sorry mate, try again!";
    }
    }
    else {
    // The form has not been posted
    // Show the form
    ?>
    <form id="Form1" action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
    Username: <input type="text" name="Username" ><br>
    Password: <input type="password" name="Password" ><br>
    Remember me: <input type="checkbox" name="Remember" checked="chekce d">
    <input type="hidden" name="SubmitChe ck" value="sent">
    <input type="Submit" name="Form1_Sub mit" value="Login">
    </form>
    <?php
    }
    ?>
    [/code]

    The finish line
    So, thats it for my basic article on HTML Forms.

    A final warning!
    Use data posted through HTML Forms carefully.
    Always assume the data you receive is somehow meant to damage your web and validate it accordingly!

    Remember that your web is only as good as the information it displays, so make sure your data is in order.

    All the best,
    - Atli Þór
    Last edited by Atli; May 25 '10, 04:26 AM. Reason: Updated for clarity.
  • kumarsantosh
    New Member
    • Dec 2007
    • 1

    #2
    Good Codeing for
    Creat login Id using html in php

    Comment

    • absentmindedjwc
      New Member
      • Dec 2007
      • 3

      #3
      Good tutorial, but this is incredibly important... (to the readers, not to the author, lol)you may have heard that $_GET poses a security risk, but it is technically no bigger than $_POST. With a basic understanding of web development, the firefox web developer toolbar, and a few minutes, a malicious user can easily pass any value he/she wants through that POST value.

      the moral of the story, NEVER TRUST DATA COMING FROM THE USER!!! This rule is absolute, I dont care if the only user is the tech guy that works at your office, any data from any user has to be taken with a grain of salt.

      That said, it is rather easy to sterilize data

      Code:
      function sterilize (&$sterilize=NULL) {
      	if ($sterilize==NULL) {return NULL;}
      	$check = array (1 => "'", 2 => '"', 3 => '<', 4 => '>');
      	foreach ($check as $value) {
      		$sterilize=str_replace($value, '', $sterilize);
      	}
      	$sterilize=strip_tags ($sterilize);
      	$sterilize=stripcslashes ($sterilize);
      	$sterilize=stripslashes ($sterilize);
      	$sterilize=addslashes ($sterilize);
      	return $sterilize;
      }
      now, imagine the user is entering his name, so $_POST['name']='Jason', all you would have to do is call the function above like this:
      $Name=sterilize ($_POST['name']);

      the data, although not fighting against any sql injections (have another function for that), will clean the data of any tags, slashes, and escapes.

      edit: just wanted to add a little bit, not trusting data isnt just for text boxes and fields, but also for drop down boxes, and even lowly checkboxes and radio buttons

      (note, I know I am passing the var by ref, but it is just easier to set it to an easy to remember var and sanitize in the same step)

      Comment

      • tenest
        New Member
        • Dec 2007
        • 1

        #4
        Originally posted by absentmindedjwc
        Good tutorial, but this is incredibly important... (to the readers, not to the author, lol)you may have heard that $_GET poses a security risk, but it is technically no bigger than $_POST. With a basic understanding of web development, the firefox web developer toolbar, and a few minutes, a malicious user can easily pass any value he/she wants through that POST value.

        the moral of the story, NEVER TRUST DATA COMING FROM THE USER!!! This rule is absolute, I dont care if the only user is the tech guy that works at your office, any data from any user has to be taken with a grain of salt.

        That said, it is rather easy to sterilize data

        Code:
        function sterilize (&$sterilize=NULL) {
        	if ($sterilize==NULL) {return NULL;}
        	$check = array (1 => "'", 2 => '"', 3 => '<', 4 => '>');
        	foreach ($check as $value) {
        		$sterilize=str_replace($value, '', $sterilize);
        	}
        	$sterilize=strip_tags ($sterilize);
        	$sterilize=stripcslashes ($sterilize);
        	$sterilize=stripslashes ($sterilize);
        	$sterilize=addslashes ($sterilize);
        	return $sterilize;
        }
        now, imagine the user is entering his name, so $_POST['name']='Jason', all you would have to do is call the function above like this:
        $Name=sterilize ($_POST['name']);

        the data, although not fighting against any sql injections (have another function for that), will clean the data of any tags, slashes, and escapes.

        edit: just wanted to add a little bit, not trusting data isnt just for text boxes and fields, but also for drop down boxes, and even lowly checkboxes and radio buttons

        (note, I know I am passing the var by ref, but it is just easier to set it to an easy to remember var and sanitize in the same step)
        while I agree with you on never trusting user-supplied data, I completely disagree with you on relying on sanitation. Sanitation will NEVER be able to completely insulate you from an attack as someone will ALWAYS be able to evade your filters (which is essentially what you are doing with your sanitation routine). User-supplied data should always be VALIDATED, and validation != sanitation. You can certainly do both (validation and sanitation), but NEVER rely on sanitation only.

        For example, a user name is most likely comprised of alpha characters and maybe digits. If that is the case, then you check to make sure that what the user supplied is ONLY alpha/num characters
        Code:
        if(ctype_alnum($_POST['Username'])){
            //continue with log in process
        } else {
            //refuse the login
        }
        If you need additional characters in the user name, then build a regex pattern, and compare the user-supplied data to the pattern. If it fails, dont go any farther.

        Furthermore, you should hash the password in storage, then compare the hash of the user-supplied password to what you have in storage:
        Code:
        if(sha1($_POST['Password']) == $usersStoredHashedPassword){
            //continue with login process
        } else {
            //refuse login
        }
        Last, before echo'ing back ANY user-supplied data to the browser, ALWAYS encode it first!

        oh, and absentmindedjwc, the contact me form on your website is susceptible to XSS injection. ;)

        Comment

        • RalphSlate
          New Member
          • Dec 2007
          • 1

          #5
          What is the advantage of using the _GET and _POST arrays versus the variables that get automatically created when the form is submitted.

          For example, if I have a form with the input variable "Username", why should I bother to refer to this as $_POST['Username'] rather than $Username?

          Comment

          • absentmindedjwc
            New Member
            • Dec 2007
            • 3

            #6
            Originally posted by tenest
            oh, and absentmindedjwc, the contact me form on your website is susceptible to XSS injection. ;)
            I noticed, :/

            a variant of what I have currently on the site, and what I posted here (among a couple other things) are going into the redesign of my site. Using JUST what I have up there clears up every XSS injection that I threw at it...

            BTW: closed the hole ;)

            Comment

            • absentmindedjwc
              New Member
              • Dec 2007
              • 3

              #7
              Originally posted by RalphSlate
              What is the advantage of using the _GET and _POST arrays versus the variables that get automatically created when the form is submitted.

              For example, if I have a form with the input variable "Username", why should I bother to refer to this as $_POST['Username'] rather than $Username?
              either I am misunderstandin g your question, or you are misunderstandin g how GET and POST arrays work... when you push submit, the data gets sent to the server as either a GET or a POST, depending on the method of the form. $username will not be set unless you set it, the variable $_POST['username'], on the other hand, will be set.

              Comment

              • pbmods
                Recognized Expert Expert
                • Apr 2007
                • 5821

                #8
                Originally posted by RalphSlate
                What is the advantage of using the _GET and _POST arrays versus the variables that get automatically created when the form is submitted.

                For example, if I have a form with the input variable "Username", why should I bother to refer to this as $_POST['Username'] rather than $Username?
                Heya, RalphSlate.

                You're talking about register_global s, which is being discontinued in PHP 6.

                register_global s is convenient, but it actually encourages you to write insecure code. Have a look at this page.

                Comment

                • Atli
                  Recognized Expert Expert
                  • Nov 2006
                  • 5062

                  #9
                  I completely agree with you about the data validation and sanitation.
                  All data you received using HTML forms, such as the one discussed in the article, should always, without exception, be considered dangerous until proven safe.

                  There are of course many different methods of validating and securing user input, each with it's uses and limitations. PHP does provide a few very handy functions that help deal with user input, such as the htmlspecialchar s function and the htmlentities function.

                  To be as safe as possible, it would be best to go with a "white-list" approach, which essentially goes through the input and removes all characters that have not be approved.

                  The opposite method would be a "black-list" approach, which would remove only those characters you have listed. This is naturally less secure but does not run the risk of removing excess data.

                  As the the question of $_POST['var'] vs $var...

                  As pbmods mentioned, the difference there is that the second variable is created by PHP if you have the register_global s directive enabled in the PHP configuration.

                  As of PHP 5, this is disabled by default and if I am not mistaken this option will be completely removed in PHP 6, as it does create a possible security risk. Details on that can be found in the link pbmods posted.

                  Comment

                  • nstone
                    New Member
                    • Mar 2008
                    • 1

                    #10
                    Originally posted by Atli
                    As of PHP 5, this is disabled by default and if I am not mistaken this option will be completely removed in PHP 6, as it does create a possible security risk. Details on that can be found in the link pbmods posted.
                    I always use extract($POST); as an early line in my scripts. It reads all $POST[variables] into $variables. The only caveat is to avoid using the same names for locally declared variables.

                    Comment

                    • Atli
                      Recognized Expert Expert
                      • Nov 2006
                      • 5062

                      #11
                      Originally posted by nstone
                      I always use extract($POST); as an early line in my scripts. It reads all $POST[variables] into $variables. The only caveat is to avoid using the same names for locally declared variables.
                      This is essentially the exact same thing being done when the register_global s directive is enabled. The only difference would be that this way neither the $_GET nor the $_SESSION super-globals are being serialized into the global scope.

                      As pbmods says, this can be convenient but it does open up a possible security risk. All request data should, with no exceptions, be treated as harmful until proven safe. This method is essentially importing possibly harmful data into your global scope, which is obviously something you should avoid.

                      Comment

                      • Markus
                        Recognized Expert Expert
                        • Jun 2007
                        • 6092

                        #12
                        Dugg.

                        Nice read.

                        :)

                        Comment

                        • acoder
                          Recognized Expert MVP
                          • Nov 2006
                          • 16032

                          #13
                          Originally posted by markusn00b
                          Dugg.
                          Erm...wasn't this already dugg back in December last year?

                          Comment

                          • Kathy Li

                            #14
                            Great article!

                            very clear, very practical, and very very helpful tutorial.

                            Comment

                            • Anton Tomi
                              New Member
                              • Jan 2011
                              • 1

                              #15
                              From a book I was using, a POST method was suggested for an order form.
                              When it came to coding the php file for outputing the results from the order form, it gave the following syntax:
                              echo $tireqty." tires";
                              it only displayed "tires" and not the amount (variable).
                              The syntax is based on php v4 and I am using php v5 could there be a change with the syntax?
                              Otherwise I am trying out what's been suggested. Very good tutorials.

                              Comment

                              Working...