Solved

Emulate Submit Button After Server-Side Form Validation to Redirect Page to External SSL Site

Posted on 2007-04-09
7
227 Views
Last Modified: 2010-05-18
I've been having a tough time figuring out this problem and could really use some help. I've got a page that verifies user form input server side, but then I need to submit the entire page, including the verified form data as a POST to an external SSL page to which I have no access. Basically, after checking the entered form data I want to 'resubmit' the page to an external site. Can anyone help me?

I've pasted my code to date below, but the below code only posts the header data, not the page itself AND the form data.

Example: http://www.ericcovarrubias.com/validation6.php


<?


// Here is the function with SSL and header redirection properly set up!  (fully commented for those who are unaccustomed to this stuff)
// You can add the $dataStream aurgument back into the function, but if you do, change "$_POST" to "$dataStream" in the first foreach line.
// I took $dataStream out because I always use the $_POST data

function post_it($url)
{
  $saveurl = $url;  // Here we save the original $url because it will be altered in the next line and we wouldn't be able to use it like we need to later
 
  $url  = preg_replace("@^https://@i", "", $url);  // $url getting altered here so we saved it in the previous line
  $host = substr($url, 0, strpos($url, "/"));
  $uri  = strstr($url, "/");
            
  $reqbody = "";
 
  foreach($_POST as $key=>$val)  {  // change "$_POST" to "$dataStream" if you still want to send the data to the function instead, but $_POST is fine since its global already

    if (is_array($val)) {      //don't url encode an array (added by an austute person on this site); you don't need to worry about it
      if (!empty($reqbody)) $reqbody .= "&";
      $reqbody .= $key . "=" . $val;
    }
    else {if (!empty($reqbody)) $reqbody .= "&"; $reqbody .= $key . "=" . urlencode($val);}      // "if (!is_empty.." should be changed to if (!empty...", it is here already!
  }

  $reqlength = strlen($reqbody);

  // here we change "HTTP/1.1" to "HTTP/1.0" or you may get "chunked" data with funny stuff on the end of your post data when its passed
  // a missing "\r" was added to the line "Host: $host (it only had a "\n" before and caused some problems I believe)
  $reqheader = "POST $uri HTTP/1.0\r\n".
                      "Host: $host\r\n" . "User-Agent: PostIt\r\n".
                      "Content-Type: application/x-www-form-urlencoded\r\n".
                      "Content-Length: $reqlength\r\n\r\n".
                      "$reqbody\r\n";
 
  // THIS IS THE LINE you add that enables the browser to redirect itself properly (you will see the right url in the address window now!)
  // Here you can see the "$saveurl variable we stored from "$url" at the top of the function
  // $saveurl must contain "https://www.yoursite.com/pageyourgoingto.php"
  header("Location: $saveurl");

  // "ssl://" added for SSL and "80" changed to "443" (thanks to another astute person on this thread)
  $socket = fsockopen("ssl://" . $host, 443, $errno, $errstr);

  if (!$socket) {$result["errno"] = $errno; $result["errstr"] = $errstr; return $result;}
  fputs($socket, $reqheader);
  while (!feof($socket)) {$result[] = fgets($socket, 4096);}
  fclose($socket);
      
  return $result;
}

    $isvalidated       = 1;
      $emailerror          = "";
    $emailclass       = "basictext1";
      $emailpattern       = '/^[[:alnum:]_\.\-]+@([[:alnum:]_\.\-]+\.)+[[:alpha:]]{2,4}$/';
    $fullnamerror       = "";
      $fullnameclass      = "basictext1";
      $fullnamepattern= '/[a-zA-Z ]{1,}/';
      $phoneerror            = "";
      $phoneclass            = "basictext1";
      $phonepattern      = '/[\(.]?[2-9]\d\d[\).]?[ -]?[2-9]\d\d[-.]\d{4}/';
      $phone                  = "";

    if ($_POST['process'] == 1) {
       
            if (preg_match($emailpattern, $_POST['email']) < 1) {
            $emailerror          = "Please enter a valid email address.";
                  $emailclass       = "errortext";
                  $isvalidated      = 0;
        }else{
                  $email = $_POST['email'];
            }
            
            if (preg_match($fullnamepattern, $_POST['name']) < 1) {
            $fullnameerror          = "Please enter your name.";
                  $fullnameclass       = "errortext";
                  $isvalidated      = 0;
        }else{
                  $name = $_POST['name'];
            }
            
            if (preg_match($phonepattern, $_POST['phone']) < 1) {
            $phoneerror          = "Please enter your phone number.";
                  $phoneclass       = "errortext";
                  $isvalidated      = 0;
        }else{
                  $phone = $_POST['phone'];
            }
            
            if ($isvalidated == 1) {
            
            $url = "https://www480.ssldomain.com/ericcovarrubias/verified.cfm";
            
            post_it($url);

            }
            
    }
?>

<html>
<style>
.basictext1 {
    font: Arial, Helvetica, sans-serif 12px;
}
.errortext {
    font: Arial, Helvetica, sans-serif 12px bold;
    color:#CC0000;
}
</style>
<body>
<form action="validation6.php" method="post">

      <div>
      <label for="name" class="<? print $fullnameclass; ?>">Name:</label>
      <input name="name" type="text" class="textbox" id="name" value="<? print $name; ?>" />
      <? if ($fullnameerror != "") {
            print '<br /><span class="errortext">'.
                  $fullnameerror."</span>\n";
      }
      ?>
      </div>                  
      <div>
      <label for="email" class="<? print $emailclass; ?>">E-mail Address:</label>
      <input name="email" type="text" id="email" value="<? print $email; ?>" />
      <? if ($emailerror != "") {
            print '<br /><span class="errortext">'.
                  $emailerror."</span>\n";
      }
      ?>
      </div>
      <div>
      <label for="phone" class="<? print $phoneclass; ?>">Phone Number:</label>
      <input name="phone" type="text" id="phone" value="<? print $phone; ?>" />
                                          <? if ($phoneerror != "") {
                                                print '<br /><span class="errortext">'.
                                                      $phoneerror."</span>\n";
                                          }
                                          ?>
      </div>
      <input type="hidden" name="process" value="1">
      <input type="hidden" name="oid" value="xxx">
      <input type="hidden" name="retURL" value="verified.php">
      <input name="Submit" type="submit" value="Submit" class="buttons" />
</form>
</body>
</html>
0
Comment
Question by:ecovarrubias
  • 4
  • 3
7 Comments
 
LVL 29

Expert Comment

by:rdivilbiss
ID: 18878489
>>but the below code only posts the header data, not the page itself AND the form data.


You are posting:

POSTDATA=name=example&email=example%40example.com&phone=222-222-2222&process=1&oid=xxx&retURL=verified.php&Submit=Submit

To the cfm form okay.  (Get the Tamper Data plugin for FireFox and see for yourself.

Look in verified.cfm to see what field names and values it is expecting.
0
 
LVL 29

Expert Comment

by:rdivilbiss
ID: 18878575
See for yourself:  http://www.rodsdot.com/ee/Q_22499376.php

An exact copy of your code posting to https://www.rodsdot.com/ee/verified6.php.

Which is:

<?PHP
foreach($_POST as $key=>$val) {
    echo $key . "=" . $val . "<br>";
}
?>


Your PHP is working.  Either the cfm page is expecting other data or has a problem.
Q_22499376.php

<?


// Here is the function with SSL and header redirection properly set up!  (fully commented for those who are unaccustomed to this stuff)
// You can add the $dataStream aurgument back into the function, but if you do, change "$_POST" to "$dataStream" in the first foreach line.
// I took $dataStream out because I always use the $_POST data

function post_it($url)
{
  $saveurl = $url;  // Here we save the original $url because it will be altered in the next line and we wouldn't be able to use it like we need to later
 
  $url  = preg_replace("@^https://@i", "", $url);  // $url getting altered here so we saved it in the previous line
  $host = substr($url, 0, strpos($url, "/"));
  $uri  = strstr($url, "/");
            
  $reqbody = "";
 
  foreach($_POST as $key=>$val)  {  // change "$_POST" to "$dataStream" if you still want to send the data to the function instead, but $_POST is fine since its global already

    if (is_array($val)) {      //don't url encode an array (added by an austute person on this site); you don't need to worry about it
      if (!empty($reqbody)) $reqbody .= "&";
      $reqbody .= $key . "=" . $val;
    }
    else {if (!empty($reqbody)) $reqbody .= "&"; $reqbody .= $key . "=" . urlencode($val);}      // "if (!is_empty.." should be changed to if (!empty...", it is here already!
  }

  $reqlength = strlen($reqbody);

  // here we change "HTTP/1.1" to "HTTP/1.0" or you may get "chunked" data with funny stuff on the end of your post data when its passed
  // a missing "\r" was added to the line "Host: $host (it only had a "\n" before and caused some problems I believe)
  $reqheader = "POST $uri HTTP/1.0\r\n".
                      "Host: $host\r\n" . "User-Agent: PostIt\r\n".
                      "Content-Type: application/x-www-form-urlencoded\r\n".
                      "Content-Length: $reqlength\r\n\r\n".
                      "$reqbody\r\n";
 
  // THIS IS THE LINE you add that enables the browser to redirect itself properly (you will see the right url in the address window now!)
  // Here you can see the "$saveurl variable we stored from "$url" at the top of the function
  // $saveurl must contain "https://www.yoursite.com/pageyourgoingto.php"
  header("Location: $saveurl");

  // "ssl://" added for SSL and "80" changed to "443" (thanks to another astute person on this thread)
  $socket = fsockopen("ssl://" . $host, 443, $errno, $errstr);

  if (!$socket) {$result["errno"] = $errno; $result["errstr"] = $errstr; return $result;}
  fputs($socket, $reqheader);
  while (!feof($socket)) {$result[] = fgets($socket, 4096);}
  fclose($socket);
      
  return $result;
}

    $isvalidated       = 1;
      $emailerror          = "";
    $emailclass       = "basictext1";
      $emailpattern       = '/^[[:alnum:]_\.\-]+@([[:alnum:]_\.\-]+\.)+[[:alpha:]]{2,4}$/';
    $fullnamerror       = "";
      $fullnameclass      = "basictext1";
      $fullnamepattern= '/[a-zA-Z ]{1,}/';
      $phoneerror            = "";
      $phoneclass            = "basictext1";
      $phonepattern      = '/[\(.]?[2-9]\d\d[\).]?[ -]?[2-9]\d\d[-.]\d{4}/';
      $phone                  = "";

    if ($_POST['process'] == 1) {
       
            if (preg_match($emailpattern, $_POST['email']) < 1) {
            $emailerror          = "Please enter a valid email address.";
                  $emailclass       = "errortext";
                  $isvalidated      = 0;
        }else{
                  $email = $_POST['email'];
            }
            
            if (preg_match($fullnamepattern, $_POST['name']) < 1) {
            $fullnameerror          = "Please enter your name.";
                  $fullnameclass       = "errortext";
                  $isvalidated      = 0;
        }else{
                  $name = $_POST['name'];
            }
            
            if (preg_match($phonepattern, $_POST['phone']) < 1) {
            $phoneerror          = "Please enter your phone number.";
                  $phoneclass       = "errortext";
                  $isvalidated      = 0;
        }else{
                  $phone = $_POST['phone'];
            }
            
            if ($isvalidated == 1) {
            
            $url = "https://www.rodsdot.com/ee/verified6.php";
            
            post_it($url);

            }
            
    }
?>

<html>
<style>
.basictext1 {
    font: Arial, Helvetica, sans-serif 12px;
}
.errortext {
    font: Arial, Helvetica, sans-serif 12px bold;
    color:#CC0000;
}
</style>
<body>
<form action="Q_22499376.php" method="post">

      <div>
      <label for="name" class="<? print $fullnameclass; ?>">Name:</label>
      <input name="name" type="text" class="textbox" id="name" value="<? print $name; ?>" />
      <? if ($fullnameerror != "") {
            print '<br /><span class="errortext">'.
                  $fullnameerror."</span>\n";
      }
      ?>
      </div>                  
      <div>
      <label for="email" class="<? print $emailclass; ?>">E-mail Address:</label>
      <input name="email" type="text" id="email" value="<? print $email; ?>" />
      <? if ($emailerror != "") {
            print '<br /><span class="errortext">'.
                  $emailerror."</span>\n";
      }
      ?>
      </div>
      <div>
      <label for="phone" class="<? print $phoneclass; ?>">Phone Number:</label>
      <input name="phone" type="text" id="phone" value="<? print $phone; ?>" />
                                          <? if ($phoneerror != "") {
                                                print '<br /><span class="errortext">'.
                                                      $phoneerror."</span>\n";
                                          }
                                          ?>
      </div>
      <input type="hidden" name="process" value="1">
      <input type="hidden" name="oid" value="xxx">
      <input type="hidden" name="retURL" value="verified.php">
      <input name="Submit" type="submit" value="Submit" class="buttons" />
</form>
</body>
</html>

verified6.php
<?PHP
foreach($_POST as $key=>$val) {
    echo "POST: " . $key . "=" . $val . "<br>";
}

echo "SERVER: ALL_HTTP = " . $_SERVER["ALL_HTTP"] . "<br>";
echo "SERVER: HTTPS = " . $_SERVER["HTTPS"] . "<br>";
echo "SERVER: REMOTE_ADDR = " . $_SERVER["REMOTE_ADDR"] . "<br>";
echo "SERVER: REQUEST_METHOD = " . $_SERVER["REQUEST_METHOD"] . "<br>";
echo "SERVER: REFERER = " . $_SERVER["HTTP_REFERER"] . "<br>";
?>

Open in new window

0
 

Author Comment

by:ecovarrubias
ID: 18879346
I actually have tamper data and see it being passed in headers, but what I need is for the entire page to post to a given external URL (not just the headers and not just the page after the fact.) So the form action would submit to $url with the post data all at once - does that make sense?
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 29

Expert Comment

by:rdivilbiss
ID: 18879549
But it does...change in your code on your server

$url = "https://www480.ssldomain.com/ericcovarrubias/verified.cfm";

to

$url = "http://www.rodsdot.com/ee/Q_22499376_verified6.php";

and you'll see you ARE posting your form data.

Rod
0
 

Author Comment

by:ecovarrubias
ID: 18941666
Yes I see the form data posting fine using tamper data, but the entire page must post - just as if there was no form validation. The form action must be the page that contains the form (so all validation fields are tested) but the $URL is an external domain. AFTER validating the page must post not just the form fields but the entire page to the $URL location. Basically the data and the visitor should end up at $URL despite the form action being the processing page and NOT $URL.
0
 
LVL 29

Accepted Solution

by:
rdivilbiss earned 500 total points
ID: 18950126
The  whole page is never sent to any page ona POST, just the headers containing among other things the postdata.

What may be causing you an issue is that the https://www480.ssldomain.com/ericcovarrubias/verified.cfm page may be expecting the original pages URL as the HTTP_REFERER and you second page is intercepting this and probably submitting its own URL as the HTTP_REFERER.

If that is the case, you can rename your first page something else, and name your second page to the URL expected by https://www480.ssldomain.com/ericcovarrubias/verified.cfm.

If that is not the case, the only way we can help you more is to see the source of https://www480.ssldomain.com/ericcovarrubias/verified.cfm so we can figure out what it expects.
0
 

Author Comment

by:ecovarrubias
ID: 18952403
Ignore https://www480.ssldomain.com/ericcovarrubias/verified.cfm. It doesn't matter. If https://www480.ssldomain.com/ericcovarrubias/verified.cfm is a 404 thats fine. Perhaps 'whole page' is confusing you. If the action (target) of the form was an external page the browser window would end up on that page after a user clicks submit, right? So thats what I need. The headers AND the browser sent to an external site all in one action.

So far the headers are making it to 'any external page' using the above code, but the browser window does NOT - it remains on the page with the form. A simple redirect won't work as the external site will redirect submissions based on entered data.
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Popularity Can Be Measured Sometimes we deal with questions of popularity, and we need a way to collect opinions from our clients.  This article shows a simple teaching example of how we might elect a favorite color by letting our clients vote for …
Things That Drive Us Nuts Have you noticed the use of the reCaptcha feature at EE and other web sites?  It wants you to read and retype something that looks like this.Insanity!  It's not EE's fault - that's just the way reCaptcha works.  But it is …
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to count occurrences of each item in an array.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now