I have been using curl with PHP for a while. Today I've been trying to fetch http://www.webhostingstuff.com/category/Best-Hosting.html and I keep getting http code 0, which is new to me.
I set the headers
$s->headers = array(
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language: en-gb,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: https://google.com"
);
and I have a cookie file (which has nothing in it when the script finishes loading)
Here's the curl function
function fetch($url, $username='', $data='', $proxy=''){
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
if(isset($proxy)) {
curl_setopt($ch,CURLOPT_TIMEOUT,30);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($ch, CURLOPT_PROXYPORT, $proxy);
curl_setopt($ch, CURLOPT_PROXYUSERPWD, 'proxyadmin:parola');
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FRESH_CONNECT,true);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
if(!empty($username)) {
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookie/{$username}.txt");
curl_setopt($ch, CURLOPT_COOKIEJAR, "cookie/{$username}.txt");
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
if (is_array($data) && count($data)>0) {
curl_setopt($ch, CURLOPT_POST, true);
$params = http_build_query($data);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
}
if (is_array($this->headers) && count($this->headers)>0){
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers);
}
$this->result = curl_exec($ch);
$curl_info = curl_getinfo($ch);
$header_size = $curl_info["header_size"];
$this->headers = substr($this->result, 0, $header_size);
$this->http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$this->error = curl_error($ch);
curl_close($ch);
}
I've also tried to execute via SSH from a different server(in case it's IP blocked)
[brian#ip-184-168-22-244 ~]$ curl -url http://www.webhostingstuff.com/addcomments/5ite.html
Enter host password for user 'rl':
curl: (7) couldn't connect to host
[brian#ip-184-168-22-244 ~]$
How might I resolve this?
Your command
curl -url http://www.webhostingstuff.com/addcomments/5ite.html
should have been:
curl --url http://www.webhostingstuff.com/addcomments/5ite.html
cURL thinks you are specifying the -u option, which is used to specify a username, hence the error message you got. You need to specify --url (two dashes).
Hope that at least helps with the debugging.
Statuscode 0 means the connection was closed (gracefully) before any output was returned.
I guess I'd start by figuring out whether you can connect to the machine at all. If you have access to the remote machine it will likely help debugging.
In my case, the http code 0 was being returned because of a connection timeout. By adding
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
I was able to get rid of the error
Yesterday I faced similar problem. I spent 2 hours on this issue. I was on RHEL system. The curl code had below block for authentication:
if($httpCode == 200) {
$_SESSION["username"] = $username;
$_SESSION["password"] = $password;
return array(true, "Login successful. Please wait while you are redirected to home page.");
}else if($httpCode == 401){
return array(false, "Login failure. Incorrect username / password");
}
This code was being used for authentication. In lab environment it returned 200, but on production it returned 0.
Then I made a similar script (which used curl), and run if from command line like php test3.php . This run resulted in 200 status code.
Then out of curiosity I decided to turn off SELinux temporarily by running this command:
setenforce 0
And guess what this worked. You can then properly set context by running setsebool httpd_can_network_connect on
0 code means curl can't find the server you were looking for.
"yahoo.com/whatever" will return 404, while "yahoo.comwhatever" will return 0.
Maybe it was some internal server error? Right now it works:
> GET /category/Best-Hosting.html HTTP/1.1
> User-Agent: HTTP_Request2/0.5.2 (http://pear.php.net/package/http_request2) PHP/5.2.12
> Host: www.webhostingstuff.com
> Accept: */*
> Accept-Encoding: deflate, gzip
>
< HTTP/1.1 200 OK
< date: Sun, 31 Jul 2011 10:57:43 GMT
< server: Apache
< last-modified: Sun, 31 Jul 2011 10:55:00 GMT
< content-encoding: gzip
< vary: Accept-Encoding
< transfer-encoding: chunked
< content-type: text/html
I use HTTP_Request2 pear package as curl wrapper, the code:
$url = 'http://www.webhostingstuff.com/category/Best-Hosting.html';
$request = new HTTP_Request2 (
$url,
HTTP_Request2::METHOD_GET,
array (
'adapter' => new HTTP_Request2_Adapter_Curl(),
'ssl_verify_peer' => false,
)
);
$request->attach(new HTTP_Request2_Observer_Log('log.txt'));
$result = $request->send();
Related
I'm trying to create a REST API and looking for a way to login using PHP, the documentation provided a login example using Python but I don't have an idea how to do this using PHP. I'm thinking if there's a PHP version of the Python code below.
See below code:
def login():
global sessionID
req = urllib2.Request("https://<host>/appserver/j_spring_security_check")
req.add_data(urllib.urlencode({"j_username" : "admin","j_password" :"demoserver"}))
res = opener.open(req)
sessionID = getCookie("JSESSIONID",cookies)
# Get the value of JSESSIONID cookie
response = res.read()
return
What is the login script (PHP version) that I can use if I need to login to web service using PHP (considering the Python example)?
Additional information:
Logging into the web service requires a JSON object as the request body with user name and password:
Successful execution of the method will return a Cookie session Id
Example request JSON: {"j_username" : "username", "j_password":"*******"}
User needs to parse the cookies and extract cookie with key as JSESSIONID. This JSESSIONID value needs to be added manually in all headers of the Rest calls
“Cookie”: “JSESSIONID=“ + cookieValue
Another example using Python:
//Request for All Apps
global sessionID
sID = "JSESSIONID="+sessionID
uri = "https://<hostname>/appserver/portal/api/1.0/apps"
req = urllib2.Request(uri)
req.add_header("Content-Type", "application/json")
req.add_header("Cookie", sID) # Header
req.get_method = "lambda: GET” # Method Type
res = opener.open(req) # URL Call
response = res.read()
return response
Request headers:
Host: 192.168.100.100:444
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:51.0) Gecko/20100101 Firefox/51.0
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, br
Referer: https://192.168.100.100:444/appserver/portal/login;jsessionid=6AD37194D43AB02BB79E26C71554958F
Cookie: JSESSIONID=6AD37194D43AB02BB79E26C71554958F
Connection: keep-alive
Upgrade-Insecure-Requests: 1
----------
When I tried curl using Linux, here's the code.
curl -k -i -H "Content-type: application/x-www-form-urlencoded" -c cookies.txt -X POST https://192.168.100.100:444/appserver/j_spring_security_check -d "j_username=admin&j_password=demoserver"
Here's the result of the linux curl, which I believe has succeed in connecting since I was routed to the welcome page.
HTTP/1.1 302 Found
Date: Thu, 16 Feb 2017 18:41:59 GMT
Server: Apache/2.2.26 (Unix) mod_ssl/2.2.25 OpenSSL/1.0.1e mod_jk/1.2.37
Set-Cookie: JSESSIONID=358446CC1F87B2D698D48AFECA373691; Path=/appserver/; HttpOnly
Location: https://192.168.100.100:444/appserver/portal/welcome;jsessionid=358446CC1F87B2D698D48AFECA373691
Content-Length: 0
Access-Control-Allow-Origin: *
Content-Type: text/plain
----------
But when I tried using PHP curl with the code, still could not connect though.
<?php
$ch = curl_init();
$url = "https://192.168.100.100:444/appserver/j_spring_security_check";
$postData = 'j_username=admin&j_password=demoserver';
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST, 1); // -X
curl_setopt($ch, CURLOPT_POSTFIELDS,$postData); // -d
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'application/x-www-form-urlencoded'
)); // -H
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt'); // -c
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt'); // -c
curl_setopt($ch, CURLOPT_HEADER, true); // -i
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // -k
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
echo curl_exec ($ch);
curl_close ($ch);
This is the resulting header in my browser.
Request URL: http://localhost/curl.php
Request method: GET
Remote address: 127.0.0.1:80
Status code: 200 OK
Version: HTTP
Response header:
Host: localhost
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:51.0) Gecko/20100101 Firefox/51.0
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
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Response headers:
Date: Thu, 16 Feb 2017 18:43:52 GMT
Server: Apache/2.2.26 (Unix) mod_ssl/2.2.25 OpenSSL/1.0.1e mod_jk/1.2.37
Content-Language: en-US
Content-Length: 4815
Access-Control-Allow-Origin: *
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html;charset=UTF-8
You need to use CURL
Request to url : "https://<host>/appserver/j_spring_security_check"
And post data : "j_username=admin&j_password=demoserver"
So your code would look like
<?php
$ch = curl_init();
$url = "https://<host>/appserver/j_spring_security_check";
$postData = "j_username=admin&j_password=demoserver";
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$postData);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec ($ch);
echo $server_output;
curl_close ($ch);
?>
Maybe you need cookie support? Something like this:
<?php
// this is for cookie handling in the session
session_start();
$tmpFname = tempnam(sys_get_temp_dir(),"COOKIE");
if (isset($_SESSION['cookies'])) {
file_put_contents($tmpFname,$_SESSION['cookies']);
}
// the request
$ch = curl_init();
$url = "https://<host>/appserver/j_spring_security_check";
$postData = "j_username=admin&j_password=demoserver";
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$postData);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/x-www-form-urlencoded'
// you may add more request headers here
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// the next two options are for cookie handling
curl_setopt($ch, CURLOPT_COOKIEJAR, $tmpFname);
curl_setopt($ch, CURLOPT_COOKIEFILE, $tmpFname);
$server_output = curl_exec ($ch);
echo $server_output;
curl_close ($ch);
// this is for cookie handling in the session
$_SESSION['cookies'] = file_get_contents($tmpFname);
unlink($tmpFname);
I hope that helps.
Based on your edited question I think it would be best if you did:
<?php
$ch = curl_init();
$url = "https://<host>/appserver/j_spring_security_check";
$postData = '{"j_username":"admin","j_password":"demoserver"}';
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS,$postData);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Host: 192.168.100.100:444',
'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:51.0) Gecko/20100101 Firefox/51.0',
'Referer: https://192.168.100.100:444/appserver/portal/login;jsessionid=6AD37194D43AB02BB79E26C71554958F',
'Cookie: JSESSIONID=6AD37194D43AB02BB79E26C71554958F'
));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // see comment
$server_output = curl_exec ($ch);
echo $server_output;
curl_close ($ch);
I think this suits your question, in it's current form, better.
I'm trying to make a script that makes things easier for Apple users, I don't really want to expose it right now but those are the steps I need to follow.
Login to Apple and saving the cookies.
Getting the data from apple with the saved cookies.
Creating automation tools.
And i'm stuck in the first step, Curl isn't submitting the custom headers as I need to submit the json header.
Here is my code:
<?php
function login($url,$data){
$data=json_encode($data);
$login = curl_init();
curl_setopt($login, CURLOPT_COOKIEJAR, "cookie.txt");
curl_setopt($login, CURLOPT_COOKIEFILE, "cookie.txt");
curl_setopt($login, CURLOPT_NOBODY, false);
curl_setopt($login, CURLOPT_HEADER, false);
curl_setopt($login, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($login, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($login, CURLOPT_TIMEOUT, 40000);
curl_setopt($login, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($login, CURLOPT_URL, $url);
curl_setopt($login, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
curl_setopt($login, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($login, CURLOPT_POST, TRUE);
curl_setopt($login, CURLOPT_POST, 1);
curl_setopt($login, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data))
);
curl_setopt($login, CURLOPT_POSTFIELDS, $data);
//ob_start();
$rez=curl_exec ($login);
}
$data = array("accountName" => "myemail#me.com", "password" => "MyPassWord","rememberMe" => "true");
$url="https://idmsa.apple.com/appleauth/auth/signin";
login($url,$data);
?>
Whenever I try tampering the data when sending request, it never shows the custom headers
Apple uses X-Apple-Widget-Key like CSRF. I think you need to catch it. You can find it on source code. You can get status by using curl_getinfo()
// your code .....
curl_setopt($login, CURLOPT_POSTFIELDS, $data);
//ob_start();
$rez = curl_exec($login);
$status = curl_getinfo($login);
print_r($status);
This would be unmanageable as a comment, so here is how i see what goes on the wire:
$verbiage = null;
if ($this->verbose) {
curl_setopt($ch , CURLINFO_HEADER_OUT , false);
curl_setopt($ch , CURLOPT_VERBOSE , true);
$verbiage = fopen('php://temp' , 'w+');
curl_setopt($ch , CURLOPT_STDERR , $verbiage);
}
$resp = curl_exec($ch);
if ($this->verbose) {
rewind($verbiage);
$verboseLog = stream_get_contents($verbiage);
$log->info("Verbose information:\n$verboseLog");
fclose($verbiage);
}
curl_close($ch);
where $log is a log4php object, you pick your display method.
EDIT adding a sample log with this 'trace' option enabled
INFO - testCreateLabRequest starts.
TRACE - Query for lab request [dispensary[1]inboundLabRequest[2]ForPatient[1]] returned no records for feed [toubibCreamedFeedGuid]
DEBUG - Sending json
{ *redacted* , "trackingId":"5ac4473b-407f-4d7d-83eb-1a3f9abe5b8b"}
INFO - Verbose information:
* Trying fe80::3636:3bff:fecf:804c...
* Connected to darkmax.local (fe80::3636:3bff:fecf:804c) port 80 (#0)
> POST /ehr/feed/lab/request HTTP/1.1
Host: darkmax.local
Protocol_version : 1.1
Connection: Close
Content-Type: application/json ; charset=utf-8
Proxy-Connection: Close
User-Agent: Portable EHR(106)
Accept: application/json, text/html;
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Content-Length: 851
* upload completely sent off: 851 out of 851 bytes
< HTTP/1.1 200 OK
< Date: Wed, 31 Aug 2016 02:04:03 GMT
< Server: Apachee/2.4.12
< Access-Control-Allow-Origin: *
< Origin: http://darkmax.local
< Connection: close
< Transfer-Encoding: chunked
< Content-Type: application/json; charset=utf-8
<
* Closing connection 0
The lines with a < correspond to what my cURL session is receiving from the remote peer. Having some visibility into the actual HTTP protocol flying from me-to-peer-back-to-me has helped me many times figure out the nature of some underlying issue.
I have been trying to make cURL login into pinterest.com for the last 17 hours straight, have tried countless and countless different ways just with cURL but it does not work at all.
My current code only goes to the page but the data is not posted, so it does not login just takes me to the login page.
This first code is using USERPWD which is where it takes me to the login page but it does not login.
error_reporting(E_ALL);
ini_set("display_errors", 1);
$url = "https://www.pinterest.com/login/";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6");
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // allow https verification if true
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); // check common name and verify with host name
curl_setopt($ch, CURLOPT_SSLVERSION,3); //
curl_setopt($ch, CURLOPT_CAINFO, getcwd() . "pin.pem"); // allow ssl cert direct comparison
curl_setopt($ch, CURLOPT_COOKIESESSION, TRUE); // set new cookie session
curl_setopt($ch, CURLOPT_COOKIEJAR, "cookies.txt");
curl_setopt($ch, CURLOPT_COOKIEFILE, "cookies.txt");
curl_setopt($ch, CURLOPT_USERPWD, "email:password");
curl_setopt($ch, CURLOPT_SSLVERSION,3);
// grab URL and pass it to the browser
curl_exec($ch);
// close cURL connection, save cookie file, free up system resources
curl_close($ch);
and if I switch it from CURLOPT_USERPWD to
curl_setopt($ch, CURLOPT_POSTFIELDS, 'username_or_email=$email&password=$password');
it just displays a blank page.
The pin.pem is the X.509 Certificate (PEM) file.
Any direction to make this work would be greatly appreciated it.
Edit
new code but leaves blank page and I got the output with a few arrays and displays this:
Array ( [url] => https://www.pinterest.com/login/ [content_type] => [http_code] => 0 [header_size] => 0 [request_size] => 0 [filetime] => -1 [ssl_verify_result] => 0 [redirect_count] => 0 [total_time] => 0.036169 [namelookup_time] => 3.3E-5 [connect_time] => 0.036186 [pretransfer_time] => 0 [size_upload] => 0 [size_download] => 0 [speed_download] => 0 [speed_upload] => 0 [download_content_length] => -1 [upload_content_length] => -1 [starttransfer_time] => 0 [redirect_time] => 0 [certinfo] => Array ( ) [redirect_url] => )
error_reporting(E_ALL);
ini_set("display_errors", 1);
$email = 'email';
$password = 'password';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.pinterest.com/login/');
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_SSLVERSION,3); //
curl_setopt($ch, CURLOPT_CAINFO, getcwd() . 'pin.pem');
curl_setopt($ch, CURLOPT_COOKIESESSION, TRUE);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_POSTFIELDS, 'username_or_email=$email&password=$password');
curl_setopt($ch, CURLOPT_SSLVERSION,3);
curl_exec($ch);
$output=#curl_exec($ch);
$info = #curl_getinfo($ch);
echo $output;
print_r($info);
curl_close($ch);
The Pinterest login process isn't quite that simple. They use a CSRF token which you must extract and send with your login, along with the username and password in the POST body.
Here is what an actual login request to Pinterest looks like, so you will need to emulate this with cURL.
POST /resource/UserSessionResource/create/ HTTP/1.1
Host: www.pinterest.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:28.0) Gecko/20100101 Firefox/28.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-CSRFToken: 2rjgN4Qv67pN4wX91kTr4eIkgF54CzJH
X-NEW-APP: 1
X-APP-VERSION: 737af79
X-Requested-With: XMLHttpRequest
Referer: https://www.pinterest.com/login/
Content-Length: 300
Cookie: csrftoken=2rjgN4Qv67pN4wX91kTr4eIkgF54CzJH; _pinterest_sess="aPgJnrIBzvSKLUY/4H5UocshliA47GkkGtHLQwo1H4IcQv58vrdazclonByOb4fWCzb3a3nycKjQzDc6SkCB9eBKoejaLiCjkKLk/QAFRn2x1pvHFlFM+1EoD01/yFxmeQKlvULYU9+qf4D6Mkj8A=="; _track_cm=1;
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
source_url=%2Flogin%2F&data=%7B%22options%22%3A%7B%22username_or_email%22%3A%22YOU%40YOUROMAIN.COM%22%2C%22password%22%3A%22YOURPASSWORD%22%7D%2C%22context%22%3A%7B%7D%7D&module_path=App()%3ELoginPage()%3ELogin()%3EButton(class_name%3Dprimary%2C+text%3DLog+In%2C+type%3Dsubmit%2C+size%3Dlarge)
The source_url data in the request is the POST body (urlencoded). Take note that username_or_email is your login (I put YOU%40YOURDOMAIN.COM) and password is the password.
What you will have to do is make a GET request to /login/ to establish a session and cookies in the cURL session. Then using the same cURL handle, you can switch to a POST request, set CURLOPT_POSTFIELDS with the data from the source_url...... line.
You will probably also need to set the headers X-CSRFToken, X-NEW-APP, X-APP-VERSION, and X-Requested-With to match the above (except you will need to figure out how to get the correct CSRF Token value).
Unfortunately I don't have the time right now to make a working example, the next paragraph may help. You will need to use your browser to help you debug some of the HTTP requests to figure out all the requests you may need to make to get all the relevant data for your request.
If you check out this answer it shows curl login with PHP and links to a number of useful other related answers with examples.
EDIT:
Here is a working example of using PHP and cURL to log in to Pinterest.
This code is a Pinterest PHP login example (works as of 2014-05-11]. You may ask yourself, can what I want to do be done with the API instead of this hackish code which could break at any time???
As you can see I parse the CSRF_Token out of the headers, you should probably do this for the APP-VERSION as well since it can update almost daily. Right now it's hard coded.
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
$username = 'you#yoursite.com'; // your username
$password = 'yourpassword'; // your password
// this is the http post data for logging in - username & password are substituted in later
$login_post = array(
'source_url' => '/login/',
'data' => '{"options":{"username_or_email":"%s","password":"%s"},"context":{}}',
'module_path' => 'App()>LoginPage()>Login()>Button(class_name=primary, text=Log In, type=submit, size=large',
);
$pinterest_url = 'https://www.pinterest.com/'; // pinterest home url
$login_url = $pinterest_url . 'login/'; // pinterest login page url
$login_post_url = $pinterest_url . 'resource/UserSessionResource/create/'; // pinterest login post url
// http headers to send with requests
$httpheaders = array(
'Connection: keep-alive',
'Pragma: no-cache',
'Cache-Control: no-cache',
'Accept-Language: en-US,en;q=0.5',
);
// http headers to send when logging in
$login_header = array(
'X-NEW-APP: 1',
'X-APP-VERSION: d2bb370', // THIS WILL UPDATE FREQUENTLY, CHANGE IT!!!
'X-Requested-With: XMLHttpRequest',
'Accept: application/json, text/javascript, */*; q=0.01');
// ----------------------------------------------------------------------------
// request home page to establish cookies and a session, set curl options
$ch = curl_init($pinterest_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Iron/31.0.1700.0 Chrome/31.0.1700.0');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookie.txt');
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_STDERR, fopen('/tmp/debug.txt', 'w+'));
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheaders);
$data = curl_exec($ch);
// ----------------------------------------------------------------------------
// parse the csrf token out of the cookies to set later when logging in
list($headers, $body) = explode("\r\n\r\n", $data, 2);
preg_match('/csrftoken=(.*?)[\b;\s]/i', $headers, $csrf_token);
// next request the login page
curl_setopt($ch, CURLOPT_URL, $login_url);
$data = curl_exec($ch);
// ----------------------------------------------------------------------------
// perform login post
$login_header[] = 'X-CSRFToken: ' . $csrf_token[1];
$login_post['data'] = sprintf($login_post['data'], $username, $password);
$post = http_build_query($login_post);
curl_setopt($ch, CURLOPT_URL, $login_post_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge($httpheaders, $login_header));
curl_setopt($ch, CURLOPT_REFERER, $login_url);
curl_setopt($ch, CURLOPT_HEADER, 0);
$data = curl_exec($ch);
// check response and output status
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) != 200) {
echo "Error logging in.<br />";
var_dump(curl_getinfo($ch));
} else {
$response = json_decode($data, true);
if ($response === null) {
echo "Failed to decode JSON response.<br /><br />";
var_dump($response);
} else if ($response['resource_response']['error'] === null) {
echo "Login successful, " . $response['resource_response']['data']['username'] . "<br /><br />";
echo "You have {$response['resource_response']['data']['follower_count']} followers, are following {$response['resource_response']['data']['following_count']} users. You have liked {$response['resource_response']['data']['like_count']} pins.";
}
}
My output:
Login successful, drew010
You have 0 followers, are following 0 users. You have liked 0 pins.
FYI, Pinterest has login rate limit so don't run this before every request.
Here is my Ruby implementation of the Pinterest login/session mechanism.
Run this once a day to save the headers (including csrftoken). Then use the saved headers to do requests that are not (yet) supported by the api (like ads reports).
class PinterestHeadersScheduler
include Sidekiq::Worker
sidekiq_options queue: :recurring, retry: 0
HOMEPAGE = 'https://ads.pinterest.com/'
LOGIN_URL = "#{HOMEPAGE}login/"
SESSION_URL = "#{HOMEPAGE}resource/UserSessionResource/create/"
LOGIN_DATA = {
source_url: '/login/',
data: { options: { username_or_email: ENV['PI_USERNAME'], password: ENV['PI_PASSWORD'] }, context: {} }.to_json
}
HEADERS = {
'Accept': 'application/json,text/html,image/webp,image/apng,*/*;q=0.8',
'Origin': 'https://ads.pinterest.com',
'Referer': 'https://ads.pinterest.com/',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36',
'Connection': 'keep-alive',
'Cache-Control': 'no-cache',
'Accept-Charset': 'utf-8;ISO-8859-1q=0.7,*;q=0.7',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'en-US,en;q=0.8'
}
SESSION_HEADERS = HEADERS.merge({
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest'
})
def perform
login = HTTParty.get(LOGIN_URL, { headers: HEADERS })
cjar = login.get_fields('Set-Cookie').each_with_object(HTTParty::CookieHash.new) { |cookie, jar| jar.add_cookies(cookie) }
headers = SESSION_HEADERS.merge({ 'Cookie': cjar.to_cookie_string, 'X-CSRFToken': cjar[:csrftoken] })
res = HTTParty.post(SESSION_URL, { headers: headers, body: LOGIN_DATA.to_param })
session = JSON.parse(ActiveSupport::Gzip.decompress(res.body))
raise "login error #{session['resource_response']['error']}" if session['resource_response']['error']
cjar = res.headers.get_fields('Set-Cookie').each_with_object(HTTParty::CookieHash.new) { |cookie, jar| jar.add_cookies(cookie) }
save_session_headers(HEADERS.merge({ 'Cookie' => cjar.to_cookie_string }))
end
def save_session_headers(headers)
# replace this with your cache/db
Utils::RedisUtil.set(:pinterest_session_headers, headers.to_json)
end
end
I am opening a HTTPS page using cURL. The page I request issues a redirect request. I have set cURL to follow the redirect, but I cannot seem to be able to get it to request the correct page. I have tracked the same request in a browser and I see my browser making a different request to what cURL makes. What can I do to correct this? The correct URL is shown in the output of a verbose cURL dump. It follows the "* Issue another request to this URL"
Here is a snippet of the output from cURL's verbose output:
< HTTP/1.1 302 Moved Temporarily
< Location: /XXX
< Content-Type: text/html; charset=UTF-8
< Date: Tue, 31 Dec 2013 15:51:46 GMT
< Expires: Tue, 31 Dec 2013 15:51:46 GMT
< Cache-Control: private, max-age=0
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< Server: GSE
< Alternate-Protocol: 443:quic
< Transfer-Encoding: chunked
<
* Ignoring the response-body
* Connection #0 to host 127.0.0.1 left intact
* Issue another request to this URL: 'XYYYZ'
* Re-using existing connection! (#0) with host 127.0.0.1
* Connected to 127.0.0.1 (127.0.0.1) port 8888 (#0)
> GET /??? HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0
The PHP code I use follows:
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_COOKIEJAR, COOKIE_FILE);
curl_setopt($ch, CURLOPT_COOKIEFILE, COOKIE_FILE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8888');
$target = ADDR;
curl_setopt($ch, CURLOPT_URL, $target);
$page = curl_exec($ch);
cURL follows the Location: Header, but be sure to send the exact headers (content-language, referer) browser does using CURLOPT_HTTPHEADER option because some servers refuse connectios to prevent automated requests. In Firefox you have live http headers to see what browser does.
Also make sure the Location: header contains the absolute url and not a relative path according to http 1.1.
If that dosen't work you can use the option CURLOPT_HEADER with curl_info to catch the 302 and redirect it manually.
Here i post an example to do it manually so you check if would produce an infinite loop.
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; rv:25.0) Gecko/20100101 Firefox/25.0');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_COOKIEJAR, COOKIE_FILE);
curl_setopt($ch, CURLOPT_COOKIEFILE, COOKIE_FILE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_PROXY, '127.0.0.1:8888');
$target = ADDR;
curl_setopt($ch, CURLOPT_URL, $target);
$page = curl_exec($ch);
$curl_info = curl_getinfo($ch);
if ($curl_info['http_code'] == 302 || $curl_info['http_code'] == 301)
{
$response_headers = substr($page, 0, $curl_info['header_size']);
if (preg_match('#Location: (.*)#', $response_headers, $location_header))
{
// Call again curl to follow location; Better to wrap the curl process in a function called follow_location
// echo $location_header return an Array
// echo $location_header[0] return "Location: http//blablabla"
// echo $location_header[1] return URL only "http://blablbalba.com" and you can process with cURL :D
echo $location_header[1];
}
}
I'm using a PHP script to read an RSS feed in my Flex 4 app. The script works when I put the URL of the feed in the actual script, but I can't get it to work when I try to send the URL as a parameter from a HTTPService in Flex.
Here is the HTTPService from Flex 4 that I'm using:
<mx:HTTPService url="http://talk.6te.net/proxy.php"
id="proxyService" method="POST"
result="rssResult()" fault="rssFault()">
<mx:request>
<url>
http://feeds.feedburner.com/nah_right
</url>
</mx:request>
</mx:HTTPService>
This is the script that works:
<?php
$ch = curl_init();
$timeout = 30;
$userAgent = $_SERVER['HTTP_USER_AGENT'];
curl_setopt($ch, CURLOPT_URL, "http://feeds.feedburner.com/nah_right");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo curl_error($ch);
} else {
curl_close($ch);
echo $response;
}
?>
But this is what I actually want to use, but it doesn't work (only line 6 is different):
<?php
$ch = curl_init();
$timeout = 30;
$userAgent = $_SERVER['HTTP_USER_AGENT'];
curl_setopt($ch, CURLOPT_URL, $_REQUEST['url']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo curl_error($ch);
} else {
curl_close($ch);
echo $response;
}
?>
Here is the request and response output of the HTTPService from the network monitor in Flash Builder 4 (using the PHP script that doesn't work):
Request:
POST /proxy.php HTTP/1.1
Host: talk.6te.net
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
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
Content-type: application/x-www-form-urlencoded
Content-length: 97
url=%0A%09%09%09%09%09http%3A%2F%2Ffeeds%2Efeedburner%2Ecom%2Fnah%5Fright%0A%20%20%20%20%09%09%09
Response:
HTTP/1.1 200 OK
Date: Mon, 10 May 2010 03:23:27 GMT
Server: Apache
X-Powered-By: PHP/5.2.13
Content-Length: 15
Content-Type: text/html
<url> malformed
I've tried putting the URL in " " in the HTTPService, but that didn't do anything. Any help would be greatly appreciated!
The $_REQUEST['url'] value is being urlencoded as opposed to urlencoding just the querystring. Somewhere in your code and/or FLEX service is causing a "double urlencode". Simply url decode it and you should get the value you need. Also, I noticed line feeds and tabs so you might want to trim it as well.
<?php
$ch = curl_init();
$timeout = 30;
$userAgent = $_SERVER['HTTP_USER_AGENT'];
curl_setopt($ch, CURLOPT_URL, trim(urldecode($_REQUEST['url'])));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo curl_error($ch);
} else {
curl_close($ch);
echo $response;
}
?>
That's it.