Saturday, April 30, 2016

oAuth signature creation issue with PHP (posting photoset to Tumblr)

Leave a Comment

I've made a simple script that posts images on tumblr. everything is fine, but I've noticed some performance issues right after I've changed the host provider (my new host is limited and cheaper).

now, after debugging the script and after contacting the tumblr api helpdesk, I'm stuck on a problem:

there are 3 functions:

function oauth_gen($method, $url, $iparams, &$headers) {      $iparams['oauth_consumer_key'] = CONSUMER_KEY;     $iparams['oauth_nonce'] = strval(time());     $iparams['oauth_signature_method'] = 'HMAC-SHA1';     $iparams['oauth_timestamp'] = strval(time());     $iparams['oauth_token'] = OAUTH_TOKEN;     $iparams['oauth_version'] = '1.0';     $iparams['oauth_signature'] = oauth_sig($method, $url, $iparams);         $oauth_header = array();     foreach($iparams as $key => $value) {         if (strpos($key, "oauth") !== false) {             $oauth_header []= $key ."=".$value;         }     }      $str = print_r($iparams, true);     file_put_contents('data1-1.txt', $str);      $oauth_header = "OAuth ". implode(",", $oauth_header);     $headers["Authorization"] = $oauth_header; }  function oauth_sig($method, $uri, $params) {      $parts []= $method;     $parts []= rawurlencode($uri);        $iparams = array();     ksort($params);     foreach($params as $key => $data) {             if(is_array($data)) {                 $count = 0;                 foreach($data as $val) {                     $n = $key . "[". $count . "]";                     $iparams []= $n . "=" . rawurlencode($val);                     //$iparams []= $n . "=" . $val;                     $count++;                 }             } else {                 $iparams[]= rawurlencode($key) . "=" .rawurlencode($data);             }     }     //debug($iparams,"iparams");     $str = print_r($iparams, true);     file_put_contents('data-1.txt', $str);     //$size = filesize('data.txt');      $parts []= rawurlencode(implode("&", $iparams));     //debug($parts,"parts");     //die();     $sig = implode("&", $parts);     return base64_encode(hash_hmac('sha1', $sig, CONSUMER_SECRET."&". OAUTH_SECRET, true)); } 

these 2 functions above comes from an online functional example, they have always worked fine.

this is the function I use to call the APIs and the oAuth:

function posta_array($files,$queue,$tags,$caption,$link,$blog){     $datArr = array();     $photoset_layout = "";     foreach ($files as $sing_file){         $dataArr [] = file_get_contents($sing_file);         $photoset_layout .= "1";     }       $headers = array("Host" => "http://api.tumblr.com/", "Content-type" => "application/x-www-form-urlencoded", "Expect" => "");      $params = array(         "data" => $dataArr,         "type" => "photo",         "state" => $queue,         "tags"=>$tags,         "caption"=>$caption,         "photoset_layout" => $photoset_layout,         "link"=>str_replace("_","",$link)     );     debug($headers,"head");     oauth_gen("POST", "http://api.tumblr.com/v2/blog/$blog/post", $params, $headers);     debug($headers,"head 2");     $ch = curl_init();     curl_setopt($ch, CURLOPT_USERAGENT, "Tumblr v1.0");     curl_setopt($ch, CURLOPT_URL, "http://api.tumblr.com/v2/blog/$blog/post");     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );     curl_setopt($ch, CURLOPT_HTTPHEADER, array(         "Authorization: " . $headers['Authorization'],         "Content-type: " . $headers["Content-type"],         "Expect: ")     );     $params = http_build_query($params);     $str = print_r($params, true);     file_put_contents('data_curl1.txt', $str);       curl_setopt($ch, CURLOPT_POST, 1);     curl_setopt($ch, CURLOPT_POSTFIELDS, $params);     $response = curl_exec($ch);     debug($response,"response");     return $response;  } 

this is the function with some problems, I try to explain:

I called the oauth_gen passing the parameters array to it, the oauth_gen creates the oauth header that I later used here: "Authorization: " . $headers['Authorization'],.

As I stated, everything is working smoothly, until I have tried to post a gif photoset of 6 files for a total of 6Mb (tumblr permit 2Mb each file and 10Mb total).

PHP runs out of memory and return an error, here it starts my debugging, after a while I contacted the tumblr api helpdesk, and they answer in this way:

You shouldn't need to include the files in the parameters used for generating the oauth signature. For an example of how this is done, checkout one of our official API clients.

This changes everything. Untill now, I passed the entire parameters array to the oauth_gen, which, calling the oauth_sig, will rawencode everything into the array (binary strings of gif files inlcuded), with a result of a binary file of about 1Mb becomes at least 3Mb of rawurlencoded string.

and that's why I had memory issues. Nice, so, as the helpdesk say, I've changed the call to the oauth_gen in this way:

$new_array = array(); oauth_gen("POST", "http://api.tumblr.com/v2/blog/$blog/post", $new_array, $headers);  

seams legit to me, I passed a new array to the function, the function then generate the oAuth, the headers are passed back and I can use them into the posting call, the result was:

{"meta":{"status":401,"msg":"Unauthorized"},"response":[]} 

asking more to tumblr api helpdesk leads only to more links to their documentation and their "tumblr php client" which I can't use, so it isn't a option.

Does anyone has experience with oAuth and can explain me what I'm doing wrong? as far as I understand, the trick is into the encrypted data the oauth_sig create, but I can't figure out how to proceed.

I really want to understand the oauth, but more I read about it and more the tumblr helpdsek seams right to me, but... the solution doesn't work, and works only if I let the oauth function to encrypt the entire data array (with the images and everything) but I can understand that this is wrong... help me.

UPDATE 1 I've tried a new thing today, first I created the empty array, then passed by reference to the oauth_genand only after generating the signature, I've added to the same array all the other fields about the post itself, but the result is the same.

UPDATE 2 reading here: http://oauth.net/core/1.0a/#signing_process seems that the parameters of the request must all be used for the signature, but this is not totally clear (if someone could explain it better, I really appreciate). this is weird, because if it's true, it go against the words of the Tumblr help desk, while if it's not true, there is a little confusion in the whole process. by the way, at this time, I'm stile struck in the same point.

0 Answers

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment