Parsing inbound emails with Mailgun, how to

Parsing incoming emails is a common task for many web application which deals with emails, and then take decision on the parsed contents. However, piping the incoming mail stream to an external script is not everyone’s food and it needs good knowledge on shell scripting and also you need to be good with your mail server to install/configure the pipe properly. So there are third party services out there which makes it easy for you by accepting your emails to predefined mailboxes. They also parse the email and post the content over HTTP to an external script (i.e webhook) which makes the whole process a lot easier. You just outsource the email parsing to these third party providers and spend time rather on analyzing the content of the email leveraging their email->http webhook. Cloudmailin, MailNuggets, and MailGun are one the few providers which I’ve tested and they work really good with very low latency. In this article I am going to show you how to configure your free Mailgun account to accept incoming mails, parse and then accept the mail content to your php script.

Step1: Register a free account with MailGun

Don’t worry – they dont charge. And Mailgun’s free plan is quite good with 200 mails/day which is pretty good during development phase. Once you are ready, you may opt in to purchase their plans which suit you best.

Step 2: Add a domain

Free accounts are restricted to use *.mailgun.org domain for now. So just log into you Mailgun control panel and create your own domain.

Configure your Mailgun Domain

Step 2: Create a mailbox to accept incoming mails

You need to configure a mailbox to start accepting inbound emails first, so you can process them later using different rules. Just go to your mailboxes tab in the Mailgun control panel and create a new mailbox.

Creating new Mailbox

Step 4: Link your incoming emails to your external script.

This step was a little confusing at first and I really didnt understand how to achieve the result. Mailgun will automatically parse these incoming mails, which you can filter by recipients or senders or by wildcard and then forward to your external script. To do that, just go to your Routes tab in the Mailgun control panel and create a new route, like the one shown in the screenshot below.

Configuring Routes and Linking to external scripts

See the forward() function does the job where my confusion began – I was almost clueless :P

Ok we are done. Mailgun will now accept all mails to this mailbox jobs@storyteller.mailgun.org and parse the mail content including attachments, and then post the parsed contents as an array to the external PHP script we have configured in step 4. In your php script just capture those data from $_POST and do whatever you want to.

Shameless Plug

We develop beautiful dashboard and admin panel templates for the web application developers, which you can plug into your application easily. These templates comes with well documented code, even better documentation of components and a pack of essential plugins. Check out one of our admin template “Utopia” and grab your copy if you like it

Utopia Dashboard Template by Themio

 

Here comes Postman, the tiny little app that connects Flickr and Facebook Groups together

Postman Flickr to Facebook Groups photo sharing service

We were working to develop a new utility web application for last couple of days which will help us, the photographers, to easily share photos from our flickr photostream to multiple Facebook groups that we are subscribed to. There was a reason why we wanted to develop this app in the first place. Every time we had to upload the same photo to each of these groups and needless to say that Facebook’s image compression routine still thinks that we live in medieval age, probably King Arthur’s reign. Anyway, the process is boring and time consuming. Another quick and dirty way was to share the photo by Facebook’s group email feature but not every group supports it. So we had to find a way to make it easy for the greater part who uses both Flickr and Facebook to share their photos.

So we’ve developed Postman, a nice little app which does the job very well. Here is what/how it works.

  • Authenticate users against Flickr and Facebook and gathers necessarily permissions (read for Flickr, publish_stream and user_groups for Facebook Connect)
  • Display last 100 photos from user’s Flickr stream in a selectable grid, with the option to load more.
  • Download the 1024px version of the selected photo from Flickr Stream to our server
  • Post that photo to selected Facebook groups using FB PHP-SDK one by one.
  • Delete the photo from server

It actually solved the big problem for us. Postman made it easy for everyone of us (the photographers) and everyone literally loved it. There is one more reason to love WordPress and that is Flickr’s compression algo is really good. So when we download the 1024px version of user’s photo and then push it to Facebook, luckily Facebook  doesn’t do much on that and the photo looks really good. And we used AppFog to host Postman which ultimately proved to be very good choice.

If you are a photographer who uses Flickr to host his photos and then share to multiple Facebook groups, please give POSTMAN a try and we are sure that you will love it.

And last but not the least, Postman can post photos to your Facebook pages too. So Postman is a handy application photographers, by photographers. Use it and enjoy. You can find postman at http://postman.im

Shameless Plug

We develop beautiful Admin Panel templates for the web application developers. Our recent product is “Bolt” which is responsive and built on top of Twitter’s bootstrap. Give it a try and let us know how do you like it.

Bolt Responsive Admin Panel Template for Developers

Bolt Responsive Admin Panel Template for Developers

Convert your reception area into an Interactive Kiosk with this nice little iPad App

My Friend Michal has developed a really cool app LoungePad for turning your reception area into an interactive Kiosk. You should really check out this app. Very interesting one.

If you have a Dental / Medical / Cosmetic Practice, Hair / Beauty Salon or even a Health spa, then Loungepad will allow you to turn your iPad into an innovative waiting room/reception area kiosk.

GO TO www.loungepad.com TO REGISTER FOR DEMO ACCESS + FREE 30 DAY TRIAL

** IMPORTANT: LOUNGEPAD IS NOT A STANDALONE APP (APART FROM THE DEMO) AND YOU WILL NEED A PC OR APPLE MAC TO INITALLY SETUP THE SYSTEM AND UPLOAD YOUR FILES **

WHAT CAN LOUNGEPAD DO FOR YOU AND YOUR BUSINESS?
- Markets your services whilst your customer is waiting in your reception area and keeps them entertained.
- Saves staff admin hours by automating all form-filling tasks.
- Tracks what your customer is interested in.
- Formatted and branded to have the look and feel of your business.

LOUNGEPAD ADMIN SECTION (SERVER SIDE)
- Setup your LoungePad on our server
- Choose layout from 4 pre-defined templates and then configure to make your own
- Configure background colour/image, text size/colour, upload your logo
- Select pre-defined icons, change their colour or upload your own icon designs
- Setup and save multiple layouts, and then downloaded to your iPad
- Preview your setup just as if it is on your iPad, allowing you to tweaks & changes

SELECTABLE FEATURES:
Setup as little or as many features as you need on our server then just download to your iPad.

a. UPLOAD VIDEOS and IMAGES
- Upload and store your MP4 videos.
- Upload your photos (jpeg and png) e.g. ‘Before and After’ pictures for Dentists or different hairstyle for your salon.

b. QUESTIONNAIRES and SURVEYS
- Create simple or complex survey and questionnaires such as medical or dental patient questionnaires or a hotel guest survey. Even use your created forms as a standalone feature. Create:
Simple Text Areas** Calendar**Radio Buttons** Check boxes**Yes/No answers** Drop down lists
- Survey/Questionnaire answers are emailed to you or multiple email addresses.
- A ‘CSV’ file is attached with each email allowing data to be imported into a database.
- Data stored on our server for up to 30 days allowing you to download all information in one go and then export to Excel or a database.

c. BROCHURES / PRICE LISTS
- Upload brochures and price lists (pdf format). Any ‘PDF’ document can be uploaded allowing users to see your brochure, price lists or even special offers.

d. WEBLINKS
- Create and direct users to your own website or websites that you choose, without customers leaving LoungePad.

e. UPLOAD YOUR HTML FILE
- Create/design an external HTML page (yourpage.html) and upload it to LoungePad e.g. upload a mini web page specifically designed for your Loungepad and incorporate linked images and videos from other websites or your own existing website.

F. ‘JOIN OUR MAILING LIST Feature
- Quickly setup and collect user name, address and emails and save it on LoungePad server for you to download as a CSV file. Generate Customer/client Loyalty.

G. STATISTICS
- Track what has been looked at on your LoungePad and for how long.
- Use statistics to Improve customer experience and more importantly improve your in-house marketing technique.

LOUNGEPAD – IPad ADMIN AREA
- Change the look and feel of your LoungePad at anytime by downloading any of your pre-configured setups, keeping your LoungePad looking fresh and new.

FREE 30 DAY TRIAL of full system (server side and iPad) +DEMO ACCESS
- Download Loungepad
- Go to www.loungepad.com to register
- Access to Demo site will also be provided

MiproApps – “The Release” and “The Story Behind”

It started in a funny way rather than a typical project plan, and finally turned into an important project for us in Leevio. Everyone in our team was so much excited to release our first flagship product, a web based service (mashup you can say) we called MiproApps. It is a visual designing tool for Facebook fanpages.

MiproApps

MiproApps

Facebook fanpages are popular media to publish your company information, portfolio or upcoming events on Facebook. To make your product outreach a massive amount of users, it is a popular tool that works good. While creating our fanpage for Leevio, we found that we are limited by available applications to decorate and present a page “really” well. What we could do is design our page in an ordinary way, like writing FBML tags and and embed those in a tab. Or we could develop an application and embed it’s tab to another tab on our page. Which one did we go with? NONE!

We thought that it would be really interesting if we can develop a service (some sort of a visual designer for such pages) by which everyone (anyone, seriously) can design and decorate their fanpage with some data they really want to deliver to their audience. So we did a quick meeting to find out if it was really possible by us, and the challenges we found are the followings

1. Limited canvas size,
2. Works with different data sources
3. Drag and drop friendly, with proper layering.
4. Compatible with major browsers (Firefox, Safari, IE, Opera and Chrome)
5. Proper caching and storing widget data

We decided to develop this project in a “release early, release often” fashion. We didnt want to deliver a HUGE giant bloated with too many widgets and services after working for tons of hours. Instead we wanted to deliver a working barebone skeleton for our users which performs it’s job pretty well, and then to add feature s gradually in a regular interval. It would also help us to decide quickly how users are reacting with our project.

We four developers worked really hard for next couple of weeks to make it work, in short sprints and milestones. And now it is available for your use – you can check it out at http://miproapps.com. There are more than 25 pretty useful widgets to help you designing your fanpage impressively. We’ve also added tutorials and screencasts for you. Lets see how did we work with all our challenges.

MiproApps Design Canvas

1. Limited Canvas Size
To make sure users still be able to design his page easily, we keep three pre defined size for each widgets. Width of these three sizes are designed in such a way so that anyone can design multi-column page, easily.

2. Works with different data sources.
The core of MiproApps are external data sources and a very well designed parser to parse those data source in an unified way. Guess what, most of these data source are ready to be pulled out. Almost all of them offers valid RSS/Atom feeds. And that saved us HUGE (GIGANTIC cud be more appropriate) amount of work to do by ourselves. We just collect username for each of these data sources (like twitter, youtube) and then we pulled out feeds for that specific user. Everything is about public data, and that also saved us from some pain about treating private and sensitive information. Except one widget (I will come to that later) we just asked for plain username from users. And for twitter, we had to deal with oath based authentication system so that we can pull out user’s timeline using their token. These tokens are for read-only access to be more trusted by our users. We set a caching time of 10 minutes so that we have to call only 6 times max for an user in an hour. Do you kno what is the current rate limit per user per hour in Twitter? it’s only 75!

Configuration Editor

Configuration Editor

3. Drag and drop friendliness
We choose jQuery UI as we are very good at jQuery. And I must confess, that was a very good decision indeed. The excellent support of managing draggable and droppable components in jQuery UI made our life really easier. The only thing we found tricky was to persist the draggable state of each component on “Design Canvas”. But anyway, it was done very effectively and is working really great. You should check this out at http://miproapps.com

And oh, by the way, the z-index layering was quite a UI challenge for us. On a Facebook page canvas area, the internal Facebook components has maximum z-ndex of “101″. So we had to deal with that to keep our components z-index lower than that, to avoid an overlay over any internal Facebook item (a dialog box, for example, or the notification dropdown :) )

4. Compatible with major browsers
Oh boy, we were doomed in hell with a monster called IE and that really made our day terrible every minute!. However, we tamed the beast quite good and now it works well with MiproApps. Another friendly monster betrayed us at last minute, has a name “Chrome”. we are working on that subtle UI issues and hope to deliver some updates pretty soon.

5. Proper caching and storing user data
Now that was a major challenge we dealt with. Each user can use hundreds of widgets, which colt actually pull data from hundreds of different data sources out there. So caching is a very important step we’d taken care of from the first day. We used Memcached. And we designed the architecture to cache data from every widget separately, not as a page in a whole. And it was challenging to deal with failsafe condition (you remember twitter’s fail whale, right?). Some widgets needed to be dealt with extra care for the caching technology of Facebook itself. But in overall it was a good architecture and worked impressively well. We are proud of it!

Useful set of widgets

Useful set of widgets

Lets have a look at the tools, libraries and services we use for MiproApps

1. Subversion, definitely a life saver version controlling system.
2. Springloops as a subversion repository and deploy manager. It’s deploy manager is really awesome!
3. Lighthouse for Issue Tracking
4. Netbeans as our IDE, Mac OSX and Ubuntu as development OS. PHP and ZendFramework. For oAuth, we used PECL oAuth library. Memcached was used for caching.
5. jQuery and jQuery UI. The image slider you see on the front page was done using the brilliant Coin Slider.
6. Screencast was recorded by Screenium. Tutorial screenshots were taken using Jing.
7. Icons came from MediaLoot and legendary Silk by Famfamfam.

So that’s It – have a look at MiproApps at http://miproapps.com. Currently the application is in beta mode (all plans are free during beta – beside that, there will always be a free plan for everyone) and we are adding exciting widgets everyday. Hope you will like it.

Dont forget to check the “Tutorial” and “Screencast” section :)

Some Sample Pages designed using MiproApps
1. Bangladesh at a glance
2. My personal page
3. Photographers Portfolio and One More

zembly is deadpooled – 2.5 yrs of effort went in vain :(

Zembly
I got a bad news this morning that zembly is shutting down their service from 30th next. that’s a very bad news because zembly was a nice service for developers. They’d started their business from june 2007, provided exciting APIs to developers to develop mashups on top of popular services like Facebook, MySpace, Flickr and so forth. I’ve seen another popular service like this , appJet, went down this year. Now it’s extremely frustrating that such types of services are shutting down. Why? most probably they’ve failed to secure funding, or may be they’ve some fight in their board of directors, or whatever, who knows and who cares.

But the point is, what happen to developers who has developed their app using services like zembly or appJet? all their efforts to learn these new technology, new tools and to develop some really cool applications using these services just became useless all at a sudden. That’s pathetic, and thats an utter lack-of-respect to your own developers community. These developers are your everything. They were your everything. If these developers didn’t put their efforts for you zembly, you will never survive a quarter, may be six months.

I really dont understand, If you dont have the guts to run your product thats fine. I have no problem with that. But before saying “All our service will be unavailable from blah blah blah” and “We are sorry and blah blah blah” , come on – show a minimal respect to your developer community. After 2.5 years of run, its not a small community after all. And grow up kiddo, before shutting down your company, at least make your project open source – as a sign of minimal respect and loyalty to the developers community who kept you running for so long.

I am sorry for Zembly But I am more sorry for the developer community.

Using iPaper API to convert office documents to flash movie on the fly :)

Embedding documents in web applications is a challenging work. Because you need to convert these documents into flash movie and only then you can embed them in your web applications. There are many converters available out their for use. Some of them are proprietary, Some of them comes for free. There are command line tools as well as web services also to perform these conversions and make your life easier. In this post I am going to introduce you to IPaper, an excellent service from Scribd. Using IPaper API you can upload and convert your documents to flash movie on the fly, and then you can embed them using Scribd’s excellent document viewer. Scribd offers a collection of client libraries and fortunately, we have a PHP lib in that collection.

Scribd API can convert numbers of document types including the followings

* Adobe PDF (.pdf)
* Adobe PostScript (.ps)
* Microsoft Word (.doc, .docx)
* Microsoft PowerPoint (.ppt, .pps, .pptx)
* Microsoft Excel (.xls, xlsx)
* OpenOffice Text Document (.odt, .sxw)
* OpenOffice Presentation Document (.odp, .sxi)
* OpenOffice Spreadsheet (.ods, .sxc)
* All OpenDocument formats
* Plain text (.txt)
* Rich text format (.rtf)

To use IPaper API, you need to create a developer account in ScribD and get your API key and secret key. Also, download the PHP client library from http://www.scribd.com/developers/libraries

You are ready to go once you get your Scribd api key and secret key. You can upload different types of files to scribd server and of course you can make them private or publicly accessible. After successful upload and conversion you will receive a doc_id and access_key from Scribd web service. Using those data you can embed your document in your web app. Lets have a look. In the following code examples, you may find the getEmbedUrl() and getEmbedCode() functions handy. You can also use SWFObject for quick embedding :)

<?php
include_once("scribd.php");

$UpdloadData = createIPaper("gpl.pdf","pdf","public");
$EmbedUrl = getEmbedUrl($UpdloadData);
echo $EmbedUrl;
$EmbedCode = getEmbedCode($UpdloadData);
echo $EmbedCode;

function createIPaper($File, $FileType, $Access="private")
{
    $scribd_api_key = "<your API key>";
    $scribd_secret = "<your Secret key>";

    if (empty($FileType))
    throw new Exception("Filetype cannot be empty");
    $Scribd = new Scribd($scribd_api_key,$scribd_secret);

    $UploadData = $Scribd->upload($File,$FileType,$Access,1);
    return $UploadData;
}

function getEmbedUrl($UploadData)
{
    if($UploadData){
        $EmbedUrl = "http://d1.scribdassets.com/ScribdViewer.swf?document_id={$UploadData['doc_id']}&access_key={$UploadData['access_key']}&page=1&version=1&viewMode=list";
        return $EmbedUrl;
    }
}

function getEmbedCode($UploadData, $Width=450, $Height=500)
{
    $EmbedCode = <<<EOD
<object codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" 
    id="doc_512761847372423" name="doc_512761847372423" 
    classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" 
    align="middle"	
    height="{$Height}" 
    width="{$Width}" >
<param name="movie" value="http://d1.scribdassets.com/ScribdViewer.swf?document_id={$UploadData['doc_id']}&access_key={$UploadData['access_key']}&page=1&version=1&viewMode=list">
<param name="quality" value="high">
<param name="play" value="true">
<param name="loop" value="true">
<param name="scale" value="showall">
<param name="wmode" value="opaque">
<param name="devicefont" value="false">
<param name="bgcolor" value="#ffffff">
<param name="menu" value="true">
<param name="allowFullScreen" value="true">
<param name="allowScriptAccess" value="always">
<param name="salign" value="">
<param name="mode" value="list">
<embed src="http://d1.scribdassets.com/ScribdViewer.swf?document_id={$UploadData['doc_id']}&access_key={$UploadData['access_key']}&page=1&version=1&viewMode=list" 
    quality="high" 
    pluginspage="http://www.macromedia.com/go/getflashplayer" 
    play="true" 
    loop="true" 
    scale="showall" 
    wmode="opaque" 
    devicefont="false" 
    bgcolor="#ffffff" 
    name="doc_512761847372423_object" 
    menu="true" 
    allowfullscreen="true" 
    allowscriptaccess="always" 
    salign="" 
    type="application/x-shockwave-flash" 
    align="middle" 
    mode="list" 
    height="{$Height}" 
    width="{$Width}">
</embed>	
</object>
EOD;
    return $EmbedCode;
}
?>

and here is how it will look after embedding

download the source code from here http://www.box.net/shared/5dav7hnkm9

By the way, IPaper PHP client library has some cool methods like uploadFromUrl() – Check them out )

Stay in touch, In next post I will show you how to use some other exciting tools which you can use and host in your own server :). that will be fun to host your own service like this :)

Thanks to Rana for helping me out with iPaper.

Using Google WorldMap visualization component in your applications

Its really hard to find a good flash based world map component to use in your web applications. They are either too complex to add or they cost quite a lot. And even sometime if you pay that, its tough to customize the chart as you want it to look like. But you know there is someone called “Uncle G” (i.e google) here who has almost all the components in his Pandora’s box. So lets see how can we use the geomap component from their Visualization Library.

First we need to create a datatable which will act as a data source for this world map, as usual like all other google visualization component.

var data = new google.visualization.DataTable();
data.addRows(5);
data.addColumn('string', 'Country');
data.addColumn('number', 'Number of ZCEs');
data.setValue(0, 0, 'Bangladesh');
data.setValue(0, 1, 19);
data.setValue(1, 0, 'India');
data.setValue(1, 1, 150);
data.setValue(2, 0, 'Pakistan');
data.setValue(2, 1, 4);
data.setValue(3, 0, 'Nepal');
data.setValue(3, 1, 5);
data.setValue(4, 0, 'Sri Lanka');
data.setValue(4, 1, 7);

now we will initialize the google visualization framework and draw this component using this data source

var geomap = new google.visualization.GeoMap(document.getElementById('<container_div_id>'));
geomap.draw(data, null);

but wait, we are not done yet – to make sure that everything works properly, we need to wrap all of these code inside a function (for example name this function as drawGeoMap) and we will use that function as a callback to draw this map. and of course, we need to load the google visualization library and geomap component first

so here is the complete code of this

<html>
<head>
  <script type="text/javascript" src="http://www.google.com/jsapi"></script>
</head>
<body>
<div id="map" style="width: 800px; height: 600px;"></div>
  <script type="text/javascript">
    google.load('visualization', '1', {packages: ['geomap']});

    function drawGeoMap() {
      var data = new google.visualization.DataTable();
	  data.addRows(5);
	  data.addColumn('string', 'Country');
	  data.addColumn('number', 'Number of ZCEs');
	  data.setValue(0, 0, 'Bangladesh');
	  data.setValue(0, 1, 19);
	  data.setValue(1, 0, 'India');
	  data.setValue(1, 1, 150);
	  data.setValue(2, 0, 'Pakistan');
	  data.setValue(2, 1, 4);
	  data.setValue(3, 0, 'Nepal');
	  data.setValue(3, 1, 5);
	  data.setValue(4, 0, 'Sri Lanka');
	  data.setValue(4, 1, 7);
      
      var geomap = new google.visualization.GeoMap(
          document.getElementById('map'));
      geomap.draw(data, null);
    }
    

    google.setOnLoadCallback(drawGeoMap);
  </script>
</body>
</html>

you can check the demo at http://sandbox.ofhas.in/geomapv1.php

it will display a world map with highlighted countries like below
Geomap V 1

but wait – lets make ca nifty change and add event listeners to it. we will add event listeners in such a way so that whenever users click on any country in the map, it will take you to zend yellow page corresponding to that country :) that will make it really an useful component :). here is the code

<html>
<head>
  <script type="text/javascript" src="http://www.google.com/jsapi"></script>
</head>
<body>
<div id="map" style="width: 800px; height: 600px;"></div>
  <script type="text/javascript">
  	var data, geomap;
  	var cids = [18,102,166,152,203]
    google.load('visualization', '1', {packages: ['geomap']});
    

    function drawGeoMap() {
      data = new google.visualization.DataTable();
	  data.addRows(5);
	  data.addColumn('string', 'Country');
	  data.addColumn('number', 'Number of ZCEs');
	  data.setValue(0, 0, 'Bangladesh');
	  data.setValue(0, 1, 19);
	  data.setValue(1, 0, 'India');
	  data.setValue(1, 1, 150);
	  data.setValue(2, 0, 'Pakistan');
	  data.setValue(2, 1, 4);
	  data.setValue(3, 0, 'Nepal');
	  data.setValue(3, 1, 5);
	  data.setValue(4, 0, 'Sri Lanka');
	  data.setValue(4, 1, 7);
      
      geomap = new google.visualization.GeoMap(
     	document.getElementById('map'));
     	 google.visualization.events.addListener(geomap, 'select', selectHandler);
      geomap.draw(data, null);
      
    }
    

    google.setOnLoadCallback(drawGeoMap);
   
    
    function selectHandler()
    {
        var selection = geomap.getSelection();
        var item = selection[0];
        var cid = cids[item.row];
        var url = "http://www.zend.com/en/yellow-pages#list-cid="+cid+"&firstname=&lastname=&orderby=name&sid=XX&company=&photo_first=&certtype=&ClientCandidateID="
        window.open(url);
        
    }
  </script>
</body>
</html>

check the demo at http://sandbox.ofhas.in/geomapv2.php

now you can click on any country and it will open a new tab with that particular country pre selected – and you can see who are the zend certified engineers from that country. i hope you’ve liked this :). Thanks goes the theam Visualization team at google for creating these awesome components and to make them free for use

For reference – check out geomap reference at google code at http://code.google.com/apis/visualization/documentation/gallery/geomap.html. you can do many other cool things like displaying only US states map or Canadian States map with this :)

expanding short url to original url using PHP and CURL

there are numbers of url shortening services available these days, including the good old tinyurl and something really short like u.nu. now when you get the short url shortened by using any of these services, you dont know where your browser is taking you! so if you are interested to figure out the original url hiding behind these short url, you need to have a little knowledge on how these services actually work. if you go to any of these short urls, they tell your browser “HTTP 30X: Object has moved” HTTP HEADER (optionally, some does it, some doesn’t) and then asks your browser to move to the original url using “Location” in HTTP HEADER. so all you have to do is just get the HTTP HEADER out first (PHP and Curl is pretty good at doing this, heh heh) and then parse the “Location” parameter from it.

lets see how that works in code

< ?php
$url = "http://tinyurl.com/2dfmty";
$ch = curl_init($url);
curl_setopt($ch,CURLOPT_HEADER,true);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,false);
$data = curl_exec($ch);
$pdata = http_parse_headers($data);
echo "Short URL: {$url}<br/>";
echo "Original URL: {$pdata['Location']}";


function http_parse_headers( $header )
    {
        $retVal = array();
        $fields = explode("\r\n", preg_replace('/\x0D\x0A[\x09\x20]+/', ' ', $header));
        foreach( $fields as $field ) {
            if( preg_match('/([^:]+): (.+)/m', $field, $match) ) {
                $match[1] = preg_replace('/(?< =^|[\x09\x20\x2D])./e', 'strtoupper("")', strtolower(trim($match[1])));
                if( isset($retVal[$match[1]]) ) {
                    $retVal[$match[1]] = array($retVal[$match[1]], $match[2]);
                } else {
                    $retVal[$match[1]] = trim($match[2]);
                }
            }
        }
        return $retVal;
    }
?>

now you see that the output of this code is

Short URL: http://tinyurl.com/2dfmty 
Original URL: http://ghill.customer.netspace.net.au/embiggen/

pretty interesting huh? if you analyze the full headers for each of these services you will find that most of them are using PHP in backend with Apache. only http://u.nu is using mod_rails (hence RoR) and bit.ly uses nginx :)

have fun in expanding!

Cropping any part of any website – thats fun!

after seeing the excellent jCrop this evening, i was thinking how to use it fro cropping any part of any website. Using a little bit CSS and Iframe – you can simulate the cropping of any webpage and thats what I did this evening

check out http://sandbox.ofhas.in/pagecrop/ – type any url in the “Url” box, load it and then select any part of it (that part is done using jCrop) – and then click “crop selection” – tada!

you can use this technology to add any particular part of any website to your website. it is done using javascript (jQuery and jCrop)- no PHP at all :)

check it out – you will definitely enjoy it :)

picture-21

develop your own gtalk/jabber/aim/yahoo bot using imified API

i’ve found http://bot.im (imified) few days ago and it’s a nice free service for creating your own messenger bots. it provides excellent API to develop bots for various platform like AIM/Yahoo/Gtalk/Jabber and interact with your bot users. To ease developing bots, I have written a wrapper class of imified API for php developers and made it open source under BSD license. You can download the wrapper from below

Download the wrapper with example

To see the example bots developed using this wrapper, please add “storyteller@bot.im” in your gtalk/jabber client or “storytellerbot” in your YM client. then type help and TADA!

please note that processing “help” is different. you need to type the response of “help” command in your bot settings page. also bots allows only one HTML tag which is <br>

example [the callback of this bot is set to http://bot.ofhas.in]

include_once("class.imified.php");
if(!isset($_REQUEST['msg']))
{
die ("This is Hasin's personal bot storyteller@bot.im to demonstrate the imified API - please add this bot from your gtalk/jabber client Or add storytellerbot@yahoo.com in your YM client. Source code is available from hasin's personal blog at http://hasin.wordpress.com");
}
//initiate
$im = new ImifiedHelper("7DCDECB6-C895-9643-909CDC85CBF09954 ","username@example.com","Oye!MyPassword!");
//callback
$im->setCallback("callback");
function callback($message, $step, $network, $userKey)
{
global $im;
$message = strtolower($message);
if("whois"==$message)
{
echo "about me";
}
else if("work"==$message)
{
echo "about my work";
}
elseif("status"==$message)
{
echo "my status";
}
elseif("quit"==$message)
{
echo "ok, bye";
}
else
{
echo "Sorry, I dont understand hierogliphics @^#%@*&#(&!*&@^!*&@#!!!";
}
$im->resetStep();
}

This class also supports fetching user info and sending message to a group of bot users. Check it out

Happy bot development