Curl via Wordpress - php

Hi I am having major problems and its driving me mad - 3 x php developers all say the code is right, but it still doesnt 'post' the data from the form into the seperate crm website. - which is clearly the whole point ! when someone submits a form i want their record to be created in my crm system
I have a wordpress site using formidable Pro form, that i want to send data to my crm system.
I think there is a problem with how wordpress sends or tells curl to work, - bit i'm not a tech person so my knowledge and understanding is a bit thin. Right now - i believe the code gets a 200 code which means its all ok - trouble is there is no data at the other end in my crm system - could anyone point out whats wrong ?
( ps posting url changed just so i dont break privacy rules on here , pps i have echoed out // a lot of the items just to see if i can get it to even just send the surname through )
The numbers in boxes are how formidable pro sees the data its collected ie surname is [861] is it the brackets that are causing an issue or is it the way the curl is dending the data - or is it wordpress !?
pps using 'code snippets' a php plugin for wordpress to enable the php code
code.........
add_action('frm_after_create_entry', 'after_entry_created', 30, 2);
function after_entry_created($entry_id, $form_id){
if($form_id == 21){
$url = 'https://secure4.mline.co.uk/DavidFarrell/php/NewMortgage.php';
$fields = array(
//Mandatory fields go here:
'MortgageMode' => urlencode(1), // OR 'CommercialMode => urlendcode(1), for CommercialKeeper
'StagePK' => urlencode(25),
'AdvisorPK' => urlencode(1),
'Surname1'=>urlencode($_POST['[861]']),
//Other fields to post into go here:
//Mortgage Details
//'LenderPK'=>urlencode(1),
//'InterestRateTypePK'=>urlencode(2),
//'Rate'=>urlencode(3.45),
//'DealTerm'=>urlencode(5),
//'Term'=>urlencode(25),
//'ActionPK'=>urlencode(11),
//'ActionText'=>urlencode($_POST['Notes']),
//Applicant Details
//'Forename1'=>urlencode($_POST['859']),
//'Email1'=>urlencode($_POST['Emailaddress'][864]),
//'DayPhone'=>urlencode($_POST['[867]']),
//'MobilePhone'=>urlencode($_POST['MobilePhone1'][866]),
//'Forename2'=>urlencode($_POST['[880]']),
//'Surname2'=>urlencode($_POST['[882]']),
//'MidNameApp1'=>urlencode($_POST['[860]']),
//'MidNameApp2'=>urlencode($_POST['[881]']),
//Submit is also mandatory and typically is placed at the end of your array
'submit'=>true
);
// Loops through the $fields array and results in a string variable called $fields_string which is a URL friendly string
foreach($fields as $key => $value)
{
//adds the key which is the eKeeper field followed by an '=', followed by and ampersand (&)
$fields_string.=$key.'='.$value.'&';
}
//trims any whitespace and cleans up the $fields_string variable
rtrim($fields_string,'&');
// Initialises a cURL connection
$ch = curl_init();
//Sets the URL to post into using the $url variable that was initialised earlier
curl_setopt($curl_connection, CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_URL,$url);
// Sets the number of fields to be passed, this is achieved by using the count() function to count the elements in the $fields array.
//curl_setopt($ch,CURLOPT_POST,count($fields));
// Sets the string that contains the eKeeper fields and their values ($fields_string)
curl_setopt($curl_connection, CURLOPT_POSTFIELDS, $post_string);
//curl_setopt($ch,CURLOPT_POSTFIELDS,$fields_string);
// Sets the return transfer option to true so that the return value after execution
// curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl_connection, CURLOPT_RETURNTRANSFER, false);
// Executes the curl session. must not be done until after the session has been initilised and the relevant curl options have been set.
$result = curl_exec($ch);
// Closes the connection/curl session
curl_close($ch);
}
}

well, this part is definitely wrong
foreach($fields as $key => $value)
{
//adds the key which is the eKeeper field followed by an '=', followed by and ampersand (&)
$fields_string.=$key.'='.$value.'&';
}
//trims any whitespace and cleans up the $fields_string variable
rtrim($fields_string,'&');
neither the key nor the value is url encoded, so if the key or value contains ÆØÅ or spaces or & or a bunch of other characters, they will be encoded wrong. also that rtrim is NOT how you trim an urlencoded string at all, no idea how that got past 3 devs.
correcting that would be
foreach($fields as $key => $value)
{
$fields_string.=urlencode($key).'='.urlencode($value).'&';
}
if(!empty($fields)){
//remove the last &
$fields_string=substr($fields_string,0,-1);
}
but luckily, PHP has a built-in function for making x-www-form-urlencoded-formatted strings called http_build_query, so the entire code could be replaced with:
$fields_string.=http_build_query($fields);
which would basically do that entire encoding loop for you. other than that, you have a bunch of undefined variables, but i guess those are mostly just removed code (you state that you removed a bunch before posting it here), but if not, setting error_reporting=E_ALL in php.ini would notice you of of most of them (but not arrays, because php is stupid, arrays are implicitly created without warning when pushed to)
but, as i have said so many times before, when debugging curl requests, always enable CURLOPT_VERBOSE - do that, and post the CURLOPT_VERBOSE stderr log in your main post, with that log, we may be of more assistance

Related

How do you submit a PHP form that doesn't return results immediately using Python?

There is a PHP form which queries a massive database. The URL for the form is https://db.slickbox.net/venues.php. It takes up to 10 minutes after the form is sent for results to be returned, and the results are returned inline on the same page. I've tried using Requests, URLLib2, LXML, and Selenium but I cannot come up with a solution using any of these libraries. Does anyone know of a way to retrieve the page source of the results after submitting this form?
If you know of a solution for this, for the sake of testing just fill out the name field ("vname") with the name of any store/gas station that comes to mind. Ultimately, I need to also set the checkboxes with the "checked" attribute but that's a subsequent goal after I get this working. Thank you!
I usually rely on Curl to do these kind of thing.
Instead of sending the form with the button to retrieve the source, call directly the response page (giving it your request).
As i work under PHP, it's quite easy to do this. With python, you will need pycURL to manage the same thing.
So the only thing to do is to call venues.php with the good arguments values thrown using POST method with Curl.
This way, you will need to prepare your request (country code, cat name), but you won't need to check the checkbox nor load the website page on your browser.
set_ini(max_execution_time,1200) // wait 20 minutes before quitting
$ch = curl_init();
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, "https://db.slickbox.net/venues.php");
curl_setopt($ch, CURLOPT_HEADER, 0);
// prepare arguments for the form
$data = array('adlock ' => 1, 'age' => 0,'country' => 145,'imgcnt'=>0, 'lock'=>0,'regex'=>1,'submit'=>'Search','vname'=>'test');
//add arguments to our request
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
//launch request
if( ! $result = curl_exec($ch))
{
trigger_error(curl_error($ch));
}
echo $result;
How about ghost?
from ghost import Ghost
ghost = Ghost()
with ghost.start() as session:
page, extra_resources = session.open("https://db.slickbox.net/venues.php", wait_onload_event=True)
ghost.set_field_value("input[name=vname]", "....")
# Any other values
page.fire_on('form', 'submit')
page, resources = ghost.wait_for_page_loaded()
content = session.content # or page.content I forgot which
After you can use beautifulsoup to parse the HTML or Ghost may have some rudimentary utilities to do that.

How to "POST" data in an xml file, and then display it after receiving at the other end

I am trying to get used to using cURL, and have hit a wall. Currently I have two php scripts, a "sender" hosted on one site and a "receiver" hosted under a different domain on a totally different site. I want the sender to read in an xml file saved in a folder, and post it to the receiver. Then when I load the receiver page, I want to see the contents of the xml displayed on screen.
Here is my code so far.
SENDER.
//Load the xml file, into an object called $message.
if(file_exists('../XML/example.xml')) {
$message = simplexml_load_file('../XML/example.xml');
}
else
{
exit ('Could not load the xml file from the specified path location');
}
//POST the data using cURL to the receiving page.
$url = "http://dev.somewhere_else.com/receiver.php"; //destination
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
$output = curl_exec($ch);
curl_close($ch);
echo $output;
// The output gets generated and looks like an array
eg:
array(4) { ["#attributes"]=> string(5) "Array" ["header_section"]=> string(23) " " ["application_section"]=> string(18) " " ["name"]=> string(7) "example" }
So far so good? In theory this means the response via cURL is the expected data. However when I go to the other site and load the receiving page, instead of seeing something similar I get.....
array(0) { }
result =
RECEIVER.
// Display the contents of the super global..
var_dump($_POST);
This displays "array(0) {}" here on this page. I suspect because the data is xml, and so $_POST isn't populated. Puzzling though, as the response the sender gets display's correctly. To fix this I added..
$dataFromPost = file_get_contents('php://input');
echo"<br><br>result =";
echo $dataFromPost;
So these last three lines should read the incoming stream from my "sender" and put it in the $dataFromPost variable. It should then display it on the screen, but all i get is blank...
I've read countless examples and followed many different guides, but can't get it to work the way I expect it to. Can anyone please put me out of my misery?
Like we found out in the comments, the script itself seems to work as you are getting the processed XML like you mentioned here:
// The output gets generated and looks like an array eg: array(4) {
["#attributes"]=> string(5) "Array" ["header_section"]=> string(23) "
" ["application_section"]=> string(18) " " ["name"]=> string(7)
"example" }
So I think you are just missunderstood the POST so I would recommend you to take a look at the manual for $_POST. You already suspected that something is different than you probably thought and you are correct with this.
Just some good and simple information about post:
POST requests are never cached
POST requests do not remain in the browser history
POST requests cannot be bookmarked
Here you can find additional info:
How PHP Works
HTTP Methods: GET vs. POST
Zend: PHP 101
So in your case, you have to save the XML. I don't know what is your intention to do, but here is a small approach:
Just take the XML from the cURL request, save it in file with file_put_contents() and add a condition (if isset post[your key] then file write else show file) to you site or split the files, one which shows only the output and one which takes your request and renews the XML.
I made this (post[your key]) bold, because you have to secure it at least a bit, otherwise I have just to post to your page and it will change.
Note without SSL it is not really possible to secure your requests, but you can at least use some key in your post to validate that this is your script, where the post comes from.
Additional information:
how to secure POST method without using SSL?
Fake a $_POST via PHP
To get back to your question:
If you post something you can see the content of the post with your var_dump() in the receiver file, If you navigate in your browser to that file $_POST is empty, because of the reason you have not postet anything, you just created a GET request. I don´t want to confuse you but the GET request method has (usually) nothing to do with the PHP $_GET variable => HTTP Request Methods
You are setting the post fields incorrectly. Typically, you would want to pass an array with CURLOPT_POSTFIELDS like so:
curl_setopt($ch, CURLOPT_POSTFIELDS, array('message' => $message));
or even better by building a query string with http_build_query():
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array('message' => $message)));
The PHP manual also describes a way of posting the entire file with this setting:
The full data to post in a HTTP "POST" operation. To post a file,
prepend a filename with # and use the full path. The filetype can be
explicitly specified by following the filename with the type in the
format ';type=mimetype'. This parameter 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. As of PHP
5.2.0, value must be an array if files are passed to this option with the # prefix. As of PHP 5.5.0, the # prefix is deprecated and files
can be sent using CURLFile. The # prefix can be disabled for safe
passing of values beginning with # by setting the CURLOPT_SAFE_UPLOAD
option to TRUE.
You should then be able to receive the data from $_POST however you decide to send it.
I have not tried the following solution but You can try
Sender code
Make a JSON string of your object
$post_data['xmlobj'] = json_encode($message) //or u can use` serialize/unserialize
pass the post data array in your request
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
Reciever Code.
at the recieving point get Post array use json_decode
get the object_string from post array and decode it
$obj = json_decode($_POST['xmlobj']); // if you are using serialize then use unserialize here.
NOTE:
if you are using json_decode you will get stdclass obje
if you are using unserialize then you will get simplexmlobj

trying to use libcurl to POST results in $_GET being set and not $_PUT in my server php code

I'm using C++ on the client side and am trying to do an HTTP POST via libcurl. I've successfully done GETs with it. The problem I'm seeing though is that on my server side, the $_GET variable is being filled with my URL parameters and $_POST is empty. However, I can check file_get_contents('php://input') and it does contain the body of my POST request.
Here's my C++ code:
CURLcode result = curl_easy_setopt(s->mHandle, CURLOPT_WRITEFUNCTION, read_callback_func);
result = curl_easy_setopt(s->mHandle, CURLOPT_WRITEDATA, (void*)s->mHandle);
result = curl_easy_setopt(s->mHandle, CURLOPT_URL, complete_url.c_str());
result = curl_easy_setopt(s->mHandle, CURLOPT_POST, 1);
result = curl_easy_setopt(s->mHandle, CURLOPT_COPYPOSTFIELDS, body.c_str());
result = curl_easy_setopt(s->mHandle, CURLOPT_CONNECTTIMEOUT, 15);
CURLMcode mresult = curl_multi_add_handle(mMultiHandle, s->mHandle);
mresult = curl_multi_perform(mMultiHandle, &mNumRunningHandles);
the variable "complete_url" in this case has the value "http://ip.addressofserver.com/pageinquestion.php?data=url_encoded_json_string"
where the url encoded json string is an object that contains a field named "function" set to the name of the function I'm trying to execute.
The variable "body" contains the text block that I'm trying to post to the server that the user has filled in. This is what appears when I check the value of file_get_contents('php://input').
When I look at what my php code on my server is getting, the $_GET field contains the key "data" mapped to the url encoded json string. $_POST is empty. Looking at my server globals, REQUEST_METHOD is set to POST and CONTENT_TYPE is application/x-www-form-urlencoded.
Now, I can make do since I have all the information I need to insert into my DB. However it just seems "not right" to do it that way since I'd expect my libcurl POST attempt to result in my server getting a POST and not a GET. Any ideas as to what I may be doing wrong? Thanks.
EDIT: Am I perhaps misunderstanding something fundamental? I saw the answer to this problem here which implies that I should in fact see all my URL parameters in the $_GET array. $_POST is supposed to be populated with the message body (which it isn't, it's always empty) however I can access it via that php://input line of code. Is it essentially working as intended?

Using MediaWiki API with the Continue Command

I need some help Using the Mediawiki API with the "Continue" or "query-continue" Command to pull information from my wiki articles. I have a large number of wiki articles (more than 800 currently) and I need to use the api to pull them in batches of 50 and then print ou sections.
My API call works properly:
//Stackoverflow making me use a valid URL here, this api is actually my own localhost server
http://en.wikipedia.org/w/api.php?action=query&list=allpages&apfrom=a&apto=z&apnamespace=0&format=xml&aplimit=50 I am querying all pages, therefore "apfrom" and "apto".
I just need help processing the code with PHP and CURL accessing the API and processing the batches of 50 and using the "continue" to access more records until I hit the end. So far my php code is:
//the CURL commands here work and outputs a data set but only for the first 50 records, so I need to call "continue" to get to the end.
//My api url is localhost but I'm forced to use a valid URL by Stackoverflow.com
$url = sprintf('http://en.wikipedia.org/w/api.php?
action=query&list=allpages&apfrom=a&apto=z&apnamespace=0&format=xml&aplimit=50');
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'My site');
$res = curl_exec($ch);
$continue = '';
while ( // I don't know what to set here as true to get the while loop going, maybe continue = true? maybe set query-continue as true?)
{
//Maybe I need something other than $res['query-continue]??
if (empty($res['query-continue']))
{
exit;
}
else
{
$continue = '&apcontinue='.urlencode($res['query-continue']);
foreach ($res['query']['allpages'] as $v)
{
echo $v['title'];
}
}
}
Can someone correct my while loop code above so I can do a simple print out of the title from each wiki article in the loop? I've done a lot of searching online but I'm stuck!! I found a python loop example at http://www.mediawiki.org/wiki/API:Query but I have to do it in PHP. And I am not sure if I call continue or query-continue.
As svick said, please use a client library which handles continuation for you.
The query continuation mechanism has changed multiple times in MediaWiki, you don't want to understand it or even less rely on it.

How to capture a response after $_POST in php?

So i have a file named instance.php that contains my class "listing".page 2 is sending
$_POST arguments to instance.php. instance.php in favor instantiates an object of "listing" and echos a unique id. i want page 2 to capture this id, and maybe even more than that.
The problem is that instance.php and page 2 do not live in the same server. I know how to handle oop in Java quiet well but i'm getting the feeling that in php it's not that straightforward. I'm pretty sure i'm missing something here.
Could you help me with suggesting a good design for my implementation requirement?
EDIT: To be clear, i'm searching for a way for two or more php files that don't live on the same server/domain to have this relationship.
If you insist on using POST for interaction ( which is kinda strange choice ), then you will have to use cULR to facilitate it.
The other way would be to use file_get_contents() function. That would limit you to using only GET method:
// in your Page2
$val = 12345;
$data = file_get_contents("http://external.site.foo/instance.php?param={$val}");
var_dump($data);
// in the instance.php
echo $_GET['param'] , '-verified';
You would need to install and use cURL. The code in page 2 will look something like:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://example.com/instance.php");
curl_setopt($ch, CURLOPT_POSTFIELDS, "key1=value1&key2=value2");
$id = curl_exec($ch);
curl_close($ch);
If you want to retrieve more than the ID, I would suggest making an array() on instance.php and serializing it:
echo serialize(array("id" => 1, "name" => "John"));
and unserializing it in page 2:
...
$arr = unserialize(curl_exec($ch))
...

Categories