Twitter Oauth via PHP WITHOUT cURL - php

My server does not support cURL.
I want to update my status via php.
How to do that without cURL?
Again: WITHOUT CURL!

Here’s how you can tweet without using cURL with PHP.
We have two options-
With stream context
Php function stream_context_create has the magic. It creates and returns a stream context with any options passed.
<?php
set_time_limit(0);
$username = 'username';
$password= 'WHATEVER';
$message='YOUR NEW STATUS';
function tweet($message, $username, $password)
{
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => sprintf("Authorization: Basic %s\r\n", base64_encode($username.':'.$password)).
"Content-type: application/x-www-form-urlencoded\r\n",
'content' => http_build_query(array('status' => $message)),
'timeout' => 5,
),
));
$ret = file_get_contents('http://twitter.com/statuses/update.xml', false, $context);
return false !== $ret;
}
echo tweet($message, $username, $password);
?>
With socket programing
PHP has a very capable socket programming API. These socket functions include almost everything you need for socket-based client-server communication over TCP/IP. fsockopen opens Internet or Unix domain socket connection.
<?php
$username = 'username';
$password= 'WHATEVER';
$message='YOUR NEW STATUS';
$out="POST http://twitter.com/statuses/update.json HTTP/1.1\r\n"
."Host: twitter.com\r\n"
."Authorization: Basic ".base64_encode ("$username:$password")."\r\n"
."Content-type: application/x-www-form-urlencoded\r\n"
."Content-length: ".strlen ("status=$message")."\r\n"
."Connection: Close\r\n\r\n"
."status=$msg";
$fp = fsockopen ('twitter.com', 80);
fwrite ($fp, $out);
fclose ($fp);
?>
Taken from here: http://www.motyar.info/2010/02/update-twitter-status-with-php-nocurl.html
Hope htis helps.
If you need any more help let me know as i am a php programmer myself.
thanks
PK

<?php
/*
* using file_get_contents
*/
$key = '';
$secret = '';
$api_endpoint = 'https://api.twitter.com/1.1/search/tweets.json?q=news'; // endpoint must support "Application-only authentication"
// request token
$basic_credentials = base64_encode($key.':'.$secret);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Authorization: Basic '.$basic_credentials."\r\n".
"Content-type: application/x-www-form-urlencoded;charset=UTF-8\r\n",
'content' => 'grant_type=client_credentials'
)
);
$context = stream_context_create($opts);
// send request
$pre_token = file_get_contents('https://api.twitter.com/oauth2/token', false, $context);
$token = json_decode($pre_token, true);
if (isset($token["token_type"]) && $token["token_type"] == "bearer"){
$opts = array('http' =>
array(
'method' => 'GET',
'header' => 'Authorization: Bearer '.$token["access_token"]
)
);
$context = stream_context_create($opts);
$data = file_get_contents($api_endpoint, false, $context);
print $data;
}
?>

You can do that using the oauth pecl extension. See here for details.
EDIT: you need to install the pecl extension

Related

Using file_get_contents with basic auth and SSL

I'm attempting a GET request using SSL and basic auth using the file_get_contents function:
$username = "XXXXXXXXXX";
$password = "XXXXXXXXXX";
$url = "https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api";
$context = stream_context_create(array("http" => array("header" => "Authorization: Basic " . base64_encode("$username:$password"))));
$data = file_get_contents($url, false, $context);
echo $data;
Here's the error message I get:
Warning: file_get_contents(https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api): failed to open stream: HTTP request failed! HTTP/1.0 500 Server Error...
I've already confirmed that openssl is enabled:
And we might as well get this out of the way up-front:
Why don't you just use cURL?
I could. But I also want to figure out why file_get_contents isn't working. I like the relative simplicity of file_get_contents. Call me crazy.
Curiosity is a good thing so it's cool to dig this problem without falling back to cURL before fixing this problem.
<?php
$username = "XXXXXXXXXX";
$password = "XXXXXXXXXX";
$url = "https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api";
$context = stream_context_create(array(
"http" => array(
"header" => "Authorization: Basic " . base64_encode("$username:$password"),
"protocol_version" => 1.1, //IMPORTANT IS HERE
)));
$data = file_get_contents($url, false, $context);
echo $data;
The fact is the server does not support HTTP/1.0. So you haven't any problem with SSL/TLS nor with your user agent. It is just the server that support HTTP from 1.1.
As said in the stream_context_create documentation the default protocol_version used in stream_context_create is 1.0. That's why you got an error 500.
EDIT : My bad, don't see this is not curl. Try with this
$username = "XXXXXXXXXX";
$password = "XXXXXXXXXX";
$url = "https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api";
$context = stream_context_create(array(
"http" => array("header" => "Authorization: Basic " . base64_encode("$username:$password")),
"ssl"=>array(
"verify_peer"=>false,
"verify_peer_name"=>false,
)));
$data = file_get_contents($url, false, $context);
echo $data;

Call a PHP from another PHP (without cURL)

I have a HTML page that has to call a PHP on another domain. The "Same-Origin-Rule" of most browsers prohibits that call. So I want to call a PHP on my domain to call a PHP on the target domain. I want to avoid cURL so I decided to use fopen in that pass-through PHP using $context:
$params = array('http' => array('method'=>'POST',
'header'=>'Content-type: application/json',
'content'=>json_encode($_POST)));
$ctx = stream_context_create($params);
$fp = fopen('https://other_domain.com/test.php', 'rb', false, $ctx);
$response = stream_get_contents($fp);
echo $response;
But the incoming $_POST in test.php seems to be empty. Any ideas?
Try to build params with http_build_query()
$postdata = http_build_query(
array(
'json' => json_encode($_POST),
)
);
and then
$params = array('http' => array('method'=>'POST',
'header'=>'Content-type: application/x-www-form-urlencoded',
'content'=> $postdata));
On the other site get it via $_POST['json']
Unless you have a server that supports application/json as a POST content type, your code isn't going to work: HTTP servers expect POST data to always be one of application/x-www-form-encoded or multipart/form-data. You need to rewrite your code to send the POST data in one of the supported types.
I managed it this way:
$postData = file_get_contents('php://input');
$params = array('http' => array('method'=>'POST',
'header'=>'Content-type: application/x-www-form-urlencoded',
'content'=>$postData));
$ctx = stream_context_create($params);
$url = 'https://other_domain.com/test.php';
$fp = fopen($url, 'rb', false, $ctx);
$response = stream_get_contents($fp);
echo $response;
This easily hands trough all incoming POST data and also forwards any responses. Thanks for all your posts!

Issue with rest services

I am facing one issue while i am calling rest service using file_get_contents
its working fine when response is success but its giving blank result in case of failure or error response. while when I am checking it using rest client its giving me correct response for both case whether its success or failure.
can anyone please help? below is the source code which i have written.
<?php
$postdata = array(
'email' => $email,
'password' => $password
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => $headers = array(
'Accept: application/json',
'Content-Type: application/json'
)
//'content' => $postdata
)
);
$context = stream_context_create($opts);
//echo "<pre>"; print_r($context); exit;
$url = WS_URL . "issavvy-api/account/login?" . http_build_query($postdata);
$result = file_get_contents($url, false, $context);
echo "<pre>";
print_r(json_decode($result));
exit;
?>
If you wanna stick with file_get_contents use $http_response_header and parse it
You can use this
function httpStatusCode($headers){
$match = null;
$pattern = "!(?P<version>HTTP/\d+\.\d+) (?P<code>\d+) (?P<status>.*)!";
foreach($headers as $header){
if(preg_match($pattern, $header, $match)){
return $match['code'];
}
}
return null;
}
To check if request was successful run
$success = (200 == httpStatusCode($http_response_header));
https://eval.in/145906

Using curl instead of http request 2 in PHP

I'm trying to use curl instead of the http request 2 pear module in PHP to query the plivo api. They have an existing library for easily making calls to their API but it uses a pear module called http request2. I don't really know how to install a pear module on a server so I thought of just rewriting some parts of their library to just use curl.
Here's the part of their code that I specifically want to modify:
function __construct($auth_id, $auth_token, $url="https://api.plivo.com", $version="v1") {
if ((!isset($auth_id)) || (!$auth_id)) {
throw new PlivoError("no auth_id");
}
if ((!isset($auth_token)) || (!$auth_token)) {
throw new PlivoError("no auth_token");
}
$this->version = $version;
$this->api = $url."/".$this->version."/Account/".$auth_id;
$this->auth_id = $auth_id;
$this->auth_token = $auth_token;
}
private function request($method, $path, $params=array()) {
$url = $this->api.rtrim($path, '/').'/';
if (!strcmp($method, "POST")) {
$req = new HTTP_Request2($url, HTTP_Request2::METHOD_POST);
$req->setHeader('Content-type: application/json');
if ($params) {
$req->setBody(json_encode($params));
}
} else if (!strcmp($method, "GET")) {
$req = new HTTP_Request2($url, HTTP_Request2::METHOD_GET);
$url = $req->getUrl();
$url->setQueryVariables($params);
} else if (!strcmp($method, "DELETE")) {
$req = new HTTP_Request2($url, HTTP_Request2::METHOD_DELETE);
$url = $req->getUrl();
$url->setQueryVariables($params);
}
$req->setAdapter('curl');
$req->setConfig(array(
'timeout' => 30,
'ssl_verify_peer' => FALSE,
));
$req->setAuth($this->auth_id, $this->auth_token, HTTP_Request2::AUTH_BASIC);
$req->setHeader(array(
'Connection' => 'close',
'User-Agent' => 'PHPPlivo',
));
$r = $req->send();
$status = $r->getStatus();
$body = $r->getbody();
$response = json_decode($body, true);
return array("status" => $status, "response" => $response);
}
public function get_account($params=array()) {
return $this->request('GET', '', $params);
}
And here's the code that I have so far:
<?php
$curl = curl_init();
$curl_options = array(
CURLOPT_URL => 'https://api.plivo.com/v1/Account/',
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_USERPWD => 'auth_id:auth_token',
CURLOPT_HTTPHEADER => array("Connection: close", "User-Agent: PHPPlivo"),
CURLOPT_TIMEOUT => 30
);
curl_setopt_array($curl, $curl_options);
$response = curl_exec($curl);
curl_close($curl);
?>
I don't really know what's going on behind the scenes but this specific code is telling me that its using basic authentication using the values for the auth id and auth token:
$req->setAuth($this->auth_id, $this->auth_token, HTTP_Request2::AUTH_BASIC);
So I also set it using curl:
CURLOPT_USERPWD => 'auth_id:auth_token',
I'm pretty much stuck. All I get as a respose is the following:
{
"error": "not found"
}
It doesn't really make much sense into what I have missed or done wrong. Please help. Thank you in advance!
Below are the things you need to handle to sync your new code with old one:
If you are using GET method
CURLOPT_URL => 'https://api.plivo.com/v1/Account/'.http_build_query($params),
CURLOPT_HTTPHEADER => array("User-Agent: PHPPlivo"),
If you are using POST method
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_HTTPHEADER => array("Content-type: application/json", "User-Agent: PHPPlivo"),
Yea... The PEAR dependency is definitely overkill for Plivo's wrapper. So that was one of the first modifications I made to the code.
Check out:
https://github.com/ashbeats/Plivo-Curl-Based-Wrapper/
Only difference is the RestAPI::request() method.

Google Services OAuth requests returns HTTP 400 Bad Request Error

I'm trying to build a basic app where I can modify my own google calendar using Google's RESTful api, but I'm having trouble getting the oAuth token. I've chosen to do it using the Services Application oAuth flow - I don't want to have to constantly re-agree to letting my own app use my calendar, but if there's a better way to do this please let me know.
Every time I make the http request I get a Bad Request error. Any ideas/help?
Here's the code:
<?php
$payload = array(
"iss"=>"services client email",
"scope"=>"https://www.googleapis.com/auth/calendar",
"aud"=>"https://accounts.google.com/o/oauth2/token",
"iat"=>date("U"),
"exp"=>date("U")+3600
);
$key = "Simple API key";
$jwt = encode_header($payload,$key);
print_r(request_g_token($jwt));
function request_g_token($jwt)
{
$data = array(
'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion' => $jwt
);
$data = http_build_query($data);
$url = "https://accounts.google.com/o/oauth2/token";
//echo $data;
$opts = array('http' =>
array(
'protocol_version' => '1.1',
'method' => 'POST',
'header' => "Host: accounts.google.com\r\n" .
"Content-Type: application/x-www-form-urlencoded\r\n",
'content' => $data
)
);
$context = stream_context_create($opts);
return (file_get_contents($url, false, $context));
}
function urlsafeb64encode($input){
return str_replace('=','',strtr(base64_encode($input),'+/','-_'));
}
function encode_header($payload, $key, $algo = 'RS256'){
$header = array('typ' => 'JWT', 'alg' => $algo);
$segments = array();
$segments[] = urlsafeb64encode(json_encode($header));
$segments[] = urlsafeb64encode(json_encode($payload));
$signing_input = implode('.',$segments);
$sig = sign_encode($signing_input,$key);
$segments[]=urlsafeb64encode($sig);
return implode('.',$segments);
}
function sign_encode($msg, $key){
return hash_hmac('sha256', $msg, $key, true);
}
?>
Any help would be greatly appreciated
UPDATE
So I went through the service process again and realized I need to use a private key, which I'm now doing. My major question is whether or not to include the "private-key.p12" part of what I downloaded from google or not. I'm still receiving a Bad Request error unfortunately...
UPDATE 2
Realized I needed to pull the key from the pk12 file, and I did so with this code:
function getKey($file){
$p12cert = array();
$fd = fopen($file, 'r');
$p12buf = fread($fd,filesize($file));
fclose($fd);
if ( openssl_pkcs12_read($p12buf, $p12cert, 'notasecret') )
{
//worked
$temp = $p12cert['pkey'];
$temp = str_replace("-----BEGIN PRIVATE KEY-----","",$temp);
$temp = str_replace("-----END PRIVATE KEY-----","",$temp);
return $temp;
}
else
{
//failed
return "failed";
}
}
However, it's still giving me a bad request error and I think it's to do with the fact that the key comes back in multiple lines. Any ideas?
For anyone experiencing this issue, I've basically come to the conclusion that google hasn't interfaced calendar with their service accounts yet, and am using a refresh token to achieve similar results without having to log in all the time.

Categories