Solved

send cURL post to be received exactly like form post

Posted on 2010-08-17
15
1,455 Views
Last Modified: 2013-11-22
I am trying to send simple entries in a form using PHP cURL so a remote server that the entries go to receives them in exactly the same manner as if sent from a plain and ordinary form.  So far, the remote server accepts post directly from the form but not when sent by this PHP attempt.  fopen and fsockopen etc. are set to "off" by the host (Yahoo) that I use, so cURL seems to be the best alternative.

As far as I can tell, no matter how the remote server is set up, if an ordinary post transmission is duplicated in its entirety, the server should accept the entries using cURL if it accepts the posted entries directly from the form.
    $header[]='Content-type: application/x-www-form-urlencoded';
    $URL="http://remote_server.net/cgi-bin/cqsl.cgi";
    $useragent = 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.8) Gecko/20100722 Ant.com Toolbar 2.0.1 Firefox/3.6.8 ( .NET CLR 3.5.30729)   AutoPager/0.6.1.22';
    $referer="http://mysite-curl.php";

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    curl_setopt($ch, CURLOPT_URL, $URL);
    curl_setopt($ch, CURLOPT_USERAGENT, $useragent);
    curl_setopt($ch, CURLOPT_REFERER, $referer);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);
    curl_exec ($ch);    
    curl_close ($ch);

Open in new window

The remote server will not accept the entries using this code.

From Firebug - Response Headers when form entries are posted:

Date: Tue, 17 Aug 2010 22:36:34 GMT
Server: Apache/2.2.8 (Fedora)
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

From Firebug - Request Headers when form entries are posted:

Host: www.remote-server.net
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.8) Gecko/20100722 Ant.com Toolbar 2.0.1 Firefox/3.6.8 ( .NET CLR 3.5.30729) AutoPager/0.6.1.22
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://mysite-form.htm
X-AutoPager: 0.6.1.22

What can be done to make the entries be received the same as if sent by the form?
     FORM action="http://remote_server.cgi"  method="POST"

Open in new window


0
Comment
Question by:mainiak
  • 7
  • 4
  • 4
15 Comments
 
LVL 6

Accepted Solution

by:
merwetta1 earned 250 total points
ID: 33460879
I compared your curl code to some I have working on a site, and posted a hybrid below. If that works, you could try adding back in some of the other header commands.
$URL="http://remote_server.net/cgi-bin/cqsl.cgi";
    
$fields = "";
foreach($_POST as $key => $value ) $fields .= "$key=" . urlencode( $value ) . "&";

$ch = curl_init($URL); 
curl_setopt($ch, CURLOPT_HEADER, 0); // set to 0 to eliminate header info from response
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Returns response data instead of TRUE(1)
curl_setopt($ch, CURLOPT_POSTFIELDS, rtrim( $fields, "& " )); // use HTTP POST to send form data
$resp = curl_exec($ch); //execute post and get results
curl_close ($ch);

Open in new window

0
 

Author Comment

by:mainiak
ID: 33461114
Thanks for the reply, merwetta1.

I copied and pasted, inserted the actual URL, and upon submit, I get a blank page but no errors show in scripts.log.
0
 
LVL 6

Expert Comment

by:merwetta1
ID: 33461969
The code I provided doesn't have any output. I'm assuming you have some other code that executes after the curl, or perhaps I don't fully understand what you are trying to accomplish. If your CGI script outputs a result string, it will be captured in the $resp variable. So you could add one more line:
echo $resp;

What does your CGI script do and can you tell if it's running properly now?
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 33464738
What you're trying to do here is commonly used to hack or attack web sites.  If the remote site wants you to make automated posts, the owner of the site should give you clear instructions showing how to use their API.  

In addition, this line is almost certainly wrong - cURL POSTFIELDS are a string -- not the same format as the array $_POST.
    curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);

Please post the ACTUAL URL of the page you're trying to target with automated post information.  Without seeing that, we have almost no hope of helping you.

Thanks, ~Ray
0
 

Author Comment

by:mainiak
ID: 33467725
Thank you both for your replies.

These are not automated posts and it is the vendor's remote server which has the cgi script.

Users make entries into a form on my site which are then sent to a vendor's remote server which generates a variable length page of results for the users' perusal.  I want the results to be displayed on my site but I discover that there is a problem with iframe height so I am trying PHP in a separate file to avoid an iframe.  Then maybe I can cache the result pages and display them without needing an iframe.  The Javascript remote server security issue looks daunting so I am trying to use a PHP solution first.

The URL that entries go to is:

http://www.compulife.net/cgi-bin/cqsl.cgi

You can see the output from the form by going to:

http://lifeinsurance.insurancebrochure.com/life-insurance-term.htm

If you scroll down, you will see that the quote results are in an iframe of fixed height which is not the best because the result pages are of varying height.  The alternative is a double scroll bar which is inconvenient for any user.

I have been unable to find any better alternative to the iframe height problem and had hoped that this would be simpler than it is.
0
 
LVL 108

Assisted Solution

by:Ray Paseur
Ray Paseur earned 250 total points
ID: 33468121
Not sure what to tell you about iFrames, but this script will POST the data to the remote URL and retrieve the HTML generated by the server.  HTH, ~Ray
<?php // RAY_temp_curl_post_example.php
error_reporting(E_ALL);

function curl_post($url, $post_array, $timeout=2, $error_report=FALSE)
{
    // PREPARE THE POST STRING
    $post_string = '';
    foreach ($post_array as $key => $val)
    {
        $post_string .= urlencode($key) . '=' . urlencode($val) . '&';
    }
    $post_string = rtrim($post_string, '&');

    // PREPARE THE CURL CALL
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL,            $url);
    curl_setopt($curl, CURLOPT_HEADER,         FALSE);
    curl_setopt($curl, CURLOPT_POST,           TRUE);
    curl_setopt($curl, CURLOPT_POSTFIELDS,     $post_string);
    curl_setopt($curl, CURLOPT_TIMEOUT,        $timeout);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);

    // EXECUTE THE CURL CALL
    $htm = curl_exec($curl);
    $err = curl_errno($curl);
    $inf = curl_getinfo($curl);
    curl_close($curl);

    // ON FAILURE
    if (!$htm)
    {
        // PROCESS ERRORS HERE
        if ($error_report)
        {
            echo "CURL FAIL: $url TIMEOUT=$timeout, CURL_ERRNO=$err";
            echo "<pre>\n";
            var_dump($inf);
            echo "</pre>\n";
        }
        return FALSE;
    }

    // ON SUCCESS
    return $htm;
}

// USAGE EXAMPLE CREATES ASSOCIATIVE ARRAY OF KEY=>VALUE PAIRS
/* IMPLEMENT THESE VALUES
<INPUT type="hidden" name="UserLocation" value="1447">
<INPUT TYPE="hidden" name="SortOverride1" value="A">
<INPUT TYPE="hidden" name="TEMPLATEFILE" value="TEMPLATE_LOGO_2.HTM">
<INPUT TYPE="hidden" name="HTEMPLATEFILE" value="HTEMPLATE_LOGO_2.HTM">
<SELECT name="State" size="1"><OPTION selected value="5">California</OPTION></SELECT>
<SELECT NAME="BirthMonth"><OPTION selected value="6">June</OPTION></SELECT>
<SELECT NAME="Birthday" ><OPTION selected>15</OPTION></SELECT>
<SELECT NAME="BirthYear" ><OPTION selected>1970</OPTION></SELECT>
Male&nbsp;<INPUT type="radio" checked name="Sex" value="M">
No&nbsp;<INPUT type="radio" checked name="Smoker" value="N">
<SELECT name="Health" size="1" ><OPTION selected value="PP">Preferred Plus</OPTION></SELECT>
<SELECT name="NewCategory"><OPTION SELECTED value="5">20 Year Level Term</OPTION></SELECT>&nbsp;
<SELECT name="FaceAmount" size="1"><OPTION selected value="500000">$500,000</OPTION></SELECT>
<SELECT name="ModeUsed" size="1"><OPTION selected value="M"> Monthly </OPTION></SELECT>
<SELECT NAME="CompRating"><OPTION selected value="4">A- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Excellent</OPTION></SELECT>
<INPUT type="submit" name="CqsComparison" value=" Compare Now ">
*/

$args["UserLocation"] = "1447";
$args["SortOverride1"] = "A";
$args["TEMPLATEFILE"] = "TEMPLATE_LOGO_2.HTM";
$args["HTEMPLATEFILE"] = "HTEMPLATE_LOGO_2.HTM";
$args["State"] = "5";
$args["BirthMonth"] = "6";
$args["Birthday"] = "15";
$args["BirthYear"] = "1970";
$args["Sex"] = "M";
$args["Smoker"] = "N";
$args["Health"] = "PP";
$args["NewCategory"] = "5";
$args["FaceAmount"] = "500000";
$args["ModelUsed"] = "M";
$args["CompRating"] = "4";
$args["CqsComparison"] = " Compare Now ";


// SET THE URL
$url = "http://www.compulife.net/cgi-bin/cqsl.cgi";

// CALL CURL TO POST THE EATA
$htm = curl_post($url, $args, 6, TRUE);
if (!$htm) die("NO $url");

// SHOW WHAT CAME BACK
echo "<pre>";
echo htmlentities($htm);

Open in new window

0
 

Author Comment

by:mainiak
ID: 33469296
Thanks Ray, but there is still the basic problem.

The hidden values I can change.  All other values are entered by each visitor. The values on the page when you open it are just default values which the life insurance shopper changes for their own situation.

The vendor sets the file that way when they send it to their customers (like me), but I may change the default to blanks if I conclude that buyers may prefer that.

Listing the values of default entries in the code will not suffice.  Every submission is different as you would see if you ran your own quote.

$_POST varies with every visitor and that is what I am unable to get sent in an acceptable form by PHP.
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 108

Expert Comment

by:Ray Paseur
ID: 33469393
This is your application, not mine, and I don't have time to write all the code for you.  Can you please break it down a little bit into questions we can answer?  For example, are you unable to put a form on the web page, receive the input and copy the values out of $_POST?  Where is the sticking point?
0
 
LVL 6

Expert Comment

by:merwetta1
ID: 33470835
mainiak, Ray's solution rocks. I think the only thing you aren't getting is that he used the $args array to reproduce a sample $_POST array. As long as your form has all the appropriately named fields, you could replace line 89 of Ray's script with this and it should work:

$htm = curl_post($url, $_POST, 6, TRUE);

Then you can delete all the lines that start with "$args".
0
 

Author Comment

by:mainiak
ID: 33471982
Please let there be no misunderstanding. I am well aware that this is my application and nowhere do I ask anyone to "write all the code".

I have written code and am trying to understand its deficiencies.  I have previously outlined the situation, but will explain again in different words so as to clarify the "sticking point".

I am devising a substitute to posting from a form directly to a remote server.  A PHP file is now to be in the middle:           Form - - - PHP - - - remote server.

Of itself, the form has been working for many years and continues to do so, but for reasons already explained, I now want entries to go from the form to a PHP file and then be passed on to the remote server.

Here is the action in the form as provided by the vendor:

<FORM action="http://www.compulife.net/cgi-bin/cqsl.cgi" method="POST">

I changed that to:

<FORM action="http://lifeinsurance.insurancebrochure.com/compulife-action.php" method="POST">

So the POST goes first to my file in which there is PHP code.

I want the various posted entries entered by visitors to be passed along by PHP to the vendor just the same as if by the form directly.

That is what is meant by "... so a remote server that the entries go to receives them in exactly the same manner as if sent from a plain and ordinary form... "  

The code I posted, and the many other variations I have tried, results in a message from the remote server "Error in form found... ", instead of generating quote results, so my attempt does not duplicate transmission directly from the usual and common type of form.

You said earlier "...  this line is almost certainly wrong - cURL POSTFIELDS are a string -- not the same format as the array $_POST.
    curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);... "

At php.net I find:
CURLOPT_POSTFIELDS         The full data to post in a HTTP "POST" operation. To post a file, prepend a filename with @ and use the full path. This can either be passed as a urlencoded string like 'para1=val1&para2=val2&...' or as an array with the field name as key and field data as value. If value is an array, the Content-Type header will be set to multipart/form-data.

If CURLOPT_POSTFIELDS is not appropriate, what is?  I am unable to find a suitable substitute.

I assumed that POST from the form, being an array, would be passed along as such by
              curl_setopt($ch, CURLOPT_POSTFIELDS, $_POST);

If I am mistaken, what is the remedy?

Based on the php.net statement, I removed  $header[]='Content-type: application/x-www-form-urlencoded'; and substituted $header[]='Content-type: text/html'; based on the Request and Response headers, but the "Error in form... " remains.

  So far the vendor is unable to help with this problem.

In short, what does it take for the remote server to receive differing sets of POST form entries through the auspices of a PHP file using cURL exactly as if direct from a form?
0
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 33478009
Please refer to my sample script posted at ID:33468121.  Lines 6 through 12 convert a post array into the raw post string that is required by this call to CURL.  I have rarely gotten an array to work correctly, so I prefer to use the urlencoded string.

Your general design pattern would work like this:

1. Put up a form on your site to receive the client data in the $_POST array
2. Merge the client input with the hidden input.  You can write this information into an associative array
3. Use the curl_post function shown above to pass the merged data to the remote service and read the response.

However a better solution would be a formal API, with documentation.  As I wrote above, "If the remote site wants you to make automated posts, the owner of the site should give you clear instructions showing how to use their API."  There could be any number of reasons why the remote server is rejecting your data.  Finding and debugging this without help from the owners of the site is a daunting and thankless task.
0
 

Author Comment

by:mainiak
ID: 33527048
This is now almost there:

The code from merwetta1 (ID: 334760879) is accepted by the remote server provided that the CURLOPT_RETURNTRANSFER line is removed (CURLOPT_HEADER line not needed).  

However, the results page opens in the PHP file (compulife-action.php) but must open at the remote server so relative links on the results page can function.  The vendor refuses to change the links.

If the results page opens at the remote server ($URL), this would then be resolved.    
 
[code]
$URL="http://www.compulife.net/cgi-bin/cqsl.cgi";

$fields = "";
foreach($_POST as $key => $value ) $fields .= "$key=" . urlencode( $value ) . "&";  

$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_POSTFIELDS, rtrim( $fields, "& " )); // use HTTP POST to send form data
curl_exec ($ch);  
curl_close ($ch);
[/code]

Ray, your comments in ID: 33478009 indicates a misunderstanding, e.g., "There could be any number of reasons why the remote server is rejecting your data."   That is not correct.  There is only one reason which is that POST from the vendor's form on my site was not being replicated.  The data is choices made by visitors from a range of options provided by the vendor who wrote the form.

A "formal API, with documentation"?  No, not needed.

"Finding and debugging this without help from the owners of the site is a daunting and thankless task."

Not correct.  No debugging is needed.  The solution is to just replicate POST from a form, as I said in my original question ID: 26410312.

The vendor's remote server has NO requirements except POST from the vendor supplied form.

Using your code in ID:33468121, upon submit, the remote server generates only a 'view source' of results with static entry values, and opens at the PHP file.

I amended your code according to merwetta1 in ID: 33470835.  That also results in a 'view source' of the results page containing whatever values are entered into the form and similarly opens at the PHP file.

However, if in addition, SHOW WHAT CAME BACK is amended to:
[code]
//echo "<pre>";
//echo htmlentities($htm);
echo ($htm);
[/code]
that opens the results page itself, at the PHP file (compulife-action.php), but it needs to open at the remote server.  Doing that resolves this question.  

I have tried everything I can to tell the remote server to simply open the results there, like,
[code]
header ("Location: http://www.compulife.net/cgi-bin/cqsl.cgi");
[/code]

etc., but it's all after the fact.  As far as I can tell, it has to be included in the POST but I can't find or think of what is appropriate to that.    

 
0
 
LVL 6

Expert Comment

by:merwetta1
ID: 33536368
If the only remaining issue is relative links in the HTML, you could do some string replacements to insert the correct "http://domain.com/" before any relative links. For example, replace "src=images/" with "src=http://domain.com/images". (Assuming you have permission to link to the site's graphics of course.)

You have been offered a lot of help and code here. Your original question was: "What can be done to make the entries be received the same as if sent by the form?" I think that has been answered. You should consider awarding points and starting a new question that includes the code of where you are at now.
0
 

Author Comment

by:mainiak
ID: 33537299
Sure, it has been mostly answered and I appreciate the help because I could not have gotten this far by myself.

I will post a new question as suggested.

The remaining issue is not relative links but that it must open at the remote server like it does direct from the form.  It opens at my php file and functionality is lost because of the relative links in a page that is impossible for me to change.

The results page that contains the relative links is controlled solely by the vendor.  Linking to the site's 100+ graphics is not possible.  They have to be changed at their remote server and the other party has reasons to keep them the way they are.
0
 

Author Closing Comment

by:mainiak
ID: 33537324
Very helpful, a good start to solving this issue.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Wordpress syntax error 1 29
Modify PHP Code on the Fly? 8 42
Paging Using PHP 7 34
google marking mail as spam using PHPMailer 6 11
Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
As a financial services provider, your business is impacted by two of the strictest federal regulations on record: the Sarbanes-Oxley Act and the Gramm-Leach-Bliley Act. Correctly implementing faxing into your organization to provide secure, real-ti…
The viewer will learn how to dynamically set the form action using jQuery.
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

746 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

15 Experts available now in Live!

Get 1:1 Help Now