connecting to flickr using PHP and PECL oAuth extension

flickr, one of the world dominant in photo sharing service, has added support to oAuth recently. Though their old authentication system still works (marked as deprecated but not discontinued) I find it’s wise to use their oAuth system for the better future proof application development.

PHP has a nice extension to perform oAuth dance in it’s pecl repository – pecl oAuth. Here is the code to connect to flickr using this extension. The only catch I found and took me more than 30 minutes to figure out a failed attempt, is you will have to append the permission flag in it’s oAuth authorization url. Pass either one of these permission flags “read”,”write” or “delete” as “&perms=” (flickr.php, line # 20) and then the redirection will be successful. Register your Flickr application from here, you will find your consumer key and secret key in next page in the App Garden.

While creating new application in flickr app garden, point the callback url to your flickr.php – thats it.

source code of config.php

<?php
$oauth['flickr']['consumerkey']="9e251c5bcc*********cac050bf50ef";
$oauth['flickr']['consumersecret']="d1c057904945****";
$oauth['flickr']['requesttokenurl']="http://www.flickr.com/services/oauth/request_token";
$oauth['flickr']['accesstokenurl']="http://www.flickr.com/services/oauth/access_token";
$oauth['flickr']['authurl']="http://www.flickr.com/services/oauth/authorize";
?>

And here is the source code of flickr.php

<?php
/**
 * flickr authentication script based on
 * pecl oauth extension
 */
session_start();
include_once("config.php");
/*
unset($_SESSION['frequest_token_secret']);
unset($_SESSION['faccess_oauth_token']);
unset($_SESSION['faccess_oauth_token_secret']);
 */
$oauthc = new OAuth($oauth['flickr']['consumerkey'],
        $oauth['flickr']['consumersecret'],
        OAUTH_SIG_METHOD_HMACSHA1,OAUTH_AUTH_TYPE_URI); //initiate
if(empty($_SESSION['frequest_token_secret'])) {
    //get the request token and store it
    $request_token_info = $oauthc->getRequestToken($oauth['flickr']['requesttokenurl']); //get request token
    $_SESSION['frequest_token_secret'] = $request_token_info['oauth_token_secret'];
    header("Location: {$oauth['flickr']['authurl']}?oauth_token=".$request_token_info['oauth_token']."&perms=read");//forward user to authorize url with appropriate permission flag
}
else if(empty($_SESSION['faccess_oauth_token'])) {
    //get the access token - dont forget to save it 
    $request_token_secret = $_SESSION['frequest_token_secret'];
    $oauthc->setToken($_REQUEST['oauth_token'],$request_token_secret);//user allowed the app, so u
    $access_token_info = $oauthc->getAccessToken($oauth['flickr']['accesstokenurl']);
    $_SESSION['faccess_oauth_token']= $access_token_info['oauth_token'];
    $_SESSION['faccess_oauth_token_secret']= $access_token_info['oauth_token_secret'];
}
if(isset($_SESSION['faccess_oauth_token'])) {
    //now fetch current users profile
    $access_token = $_SESSION['faccess_oauth_token'];
    $access_token_secret =$_SESSION['faccess_oauth_token_secret'];
    $oauthc->setToken($access_token,$access_token_secret);
    $data = $oauthc->fetch('http://api.flickr.com/services/rest/?method=flickr.test.login&api_key=ae29ce34e831937ac26483498e93f3e9&format=json');
    $response_info = $oauthc->getLastResponse();
    echo "<pre>";
    print_r(json_decode($response_info));
    echo "</pre>";
}
?>

You can download the complete package from here (Thanks Box.net)

Note: I have written a similar post to demonstrate connecting to twitter and linkedin via their oAuth protocol which you can find here :)

Box.net widget in MiproApps – why did it require special care…

In MiproApps, our Visual Facebook Fanpage Desiger from Leevio, everything is built on top of a scalable plugin based architecture. Every plugin manages it’s data using a central plugin manager. Most of these data are isolated from each other, stored and served by the plugin manager without any special coding required from plugin developers. That makes everything simple. As storage and serving is fully managed by Plugin Manager, it helps us to cache, validate and sanitize user data properly from a single place.

But when we decided to add support for box.net, there comes a challenge. We have asked for username and password for box.net account from our users to pull out the data from their shared folders and files. “PASSWORD” – and that is the thing everyone thinks twice before providing to a third party. Everyone cares about their personal data security.

In MiproApps every data collected from user are submitted to storage service via Ajax request. And we simply cant send plain password collected by users in an Ajax request. What we did in this case is we had signed user’s sensitive information using a 128 bit public key (RSA) in client side. The private key is stored securely in our server and that encrypted information is decrypted only in server side. So client application has just the public key.

Box.net widget in Facebook Fanpages powered by MiproApps

Box.net widget in Facebook Fanpages powered by MiproApps

There were other challenges as well, while we went to implement this encryption in client side by Javascript and Decryption by PHP. Unfortunately PHPs Mcrypt doesnt support RSA, and Zend Framework doesnt provide any component for that. And there was a trick when you encrypt your data in JS. You must add a null byte at the end of your data, otherwise PHP cant decrypt it.

We have used RSA library (a combination of RSA, BigInt and Barett Library) from Ohdave and used the Crypt_RSA library from PEAR. And it also required us to install bigint PECL extension.

You can see some example code at here and you can use the RSA public/private key pair either by openssl shell command or the RSA key generator from ohdave.

The service layer is working smooth. Plugin developers doesnt need to bother about encryption and decryption. Everything was managed transparently under the hood. And so far we are only developing our plugins, data is secured and safe. Users can add their publicly shared box.net files directly in their facebook fanpage. For a sample output, you can check out my page. You will find the box.net component at the bottom right corner.

Prelude to foundation: Its time to go for a better PHP Framework

I remember those old days when I had to write everything by myself. I wrote huge libraries to work with MySQL. Then I learned PostgreSQL and SQLite but didn’t rewrote my old library to work with those, I was running short of time. So I forsake the opportunity to write a db library which works with them. What I did was plain code relevant to database specific portions. Oh ya, that was a long time ago.

Soon after that I came to know adoDB which made my dream come true. I was so much happy getting my all db specific works done in a much more smarter way. I get rid of database portability issues. I was very happy that time.

I learned smarty soon after I realize that my codes are getting ugly with all the inline HTMLs and PHPs. Nothing could be smarter than separating the presentation logic from the business layer. I am a big smarty fan since that time. It saves my sleep for many nights.

But again I am recurrently suffering from maintainability issues. I was not surprised to find that my code is becoming huge unmanageable giant and it takes huge time for refactoring the application. I was very sad those days. Oh what a disaster that was.

When working with my team members located remote places, I fall into a deep shit. How can we manage and track the changes done by us? Even I was getting strange code in my routine which I bet was not written by me!! It was a terrific job Continue reading

Just PHP will give you nothing… unless you upgrade yourself

I have been working with PHP for more than 3yrs (I believe still I am beginner in this category) – I was present in several interview board. Which things disappointed me most is the “lack of eagerness” to learn what comes new. Sometime developers thinks that learning Only PHP will help them to get lucrative jobs!! OMG

Specially in BD most of the time PHP developers plays multiple roles in the companies, they are developer, they are template designers, they are HTML coders, they are DBA, they are PMs….what the heck. Only few companies have different people for these roles.

How far you can go just learning PHP (RAW code, in ancient style, that means PHP+HTML together, yak!!)? You have to have knowledge in CSS, JS, Frameworks, Multiple DBS

When it comes the question of CSS, you should maintain a list of websites where from you can get updates. Dont learn the CSS from book, but goto websites and see what is happening… If you are still using Tables to design Continue reading

Caching – Save visitors time and Balance the load

Caching is a major process of speeding up your application. By caching the output of a potentially large scale operation and displaying that output later from that cache saves a lot of time. First if you have cached output of a large scale operation, just check whether the cache is out-of-date or not. If it succeeds all the parameters, display the cache which saves that time consuming procedures. These large scale operation may include fetching content from an remote source using CURL or any stream wrapper, or a database operation, or even a time consuming graph/chart generation.

There are several types of caching, like opcode caching, output caching etc. Compiler level caching are out of scope in this article. We are simply talking about the output caching. In this step PEAR::Cache or PEAR::Cache_Lite may save really a great amount of time. Lets take a look how.

In the following example we are using PEAR::Cache. You can also use Cache_Lite which functions great by sacrificing a bit performance.

<?
include("Cache/Output.php");

$cache = new Cache_Output("file");
if (!$cache->start($cacheid, "samplegroup"))
{
	//perform large scale operation
        echo "Hello";
	$cache->end();
}
else 
{
	echo "Printing from Cache";
}

//display the cached content
echo $cache->get($cacheid);
?>

First time, the output is generated as usually. But from next time the output is displayed from cached bypassing the large scale operation.

You can flush content of any cached group by accessing it’s flush() method which looks like below

$cache->flush( “samplegroup”);

Thats it.