<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>API &#8211; Johnny Morano&#039;s Tech Articles</title>
	<atom:link href="https://jmorano.moretrix.com/tag/api/feed/" rel="self" type="application/rss+xml" />
	<link>https://jmorano.moretrix.com</link>
	<description>Ramblings of an old-fashioned space cowboy</description>
	<lastBuildDate>Wed, 20 Apr 2022 07:17:15 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.2</generator>

<image>
	<url>https://jmorano.moretrix.com/wp-content/uploads/2022/04/cropped-jmorano_emblem-32x32.png</url>
	<title>API &#8211; Johnny Morano&#039;s Tech Articles</title>
	<link>https://jmorano.moretrix.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Perl: SSL Communication in web applications</title>
		<link>https://jmorano.moretrix.com/2014/11/perl-ssl-communication-in-web-applications/</link>
					<comments>https://jmorano.moretrix.com/2014/11/perl-ssl-communication-in-web-applications/#respond</comments>
		
		<dc:creator><![CDATA[Johnny Morano]]></dc:creator>
		<pubDate>Thu, 06 Nov 2014 10:27:34 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[OpenSSL]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=1142</guid>

					<description><![CDATA[The following demonstrates how to create a strict SSL communication between client and server, using HTTP.This setup could&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The following demonstrates how to create a strict SSL communication between client and server, using HTTP.<br />This setup could used when creating a web API which requires strong encryption and only allows clients which have a properly signed certificate.</p>



<p>The Apache configuration in the below example will actually require 2 web servers:</p>



<ul class="wp-block-list"><li>one proxy host, which will accept the SSL connection, verify, check for ACLs and then forward the connection unencrypted internally</li><li>one internal web server which will actually contain the WebAPI scripts</li></ul>



<p>This article explains how to use <a href="http://mojolicio.us/" target="_blank" rel="noopener">Mojolicious</a> for the WebAPI side and <a href="http://search.cpan.org/~mschilli/libwww-perl-6.08/lib/LWP/UserAgent.pm" target="_blank" rel="noopener">LWP::UserAgent</a> to send and receive the WebAPI calls. We will furthermore use <a href="http://search.cpan.org/~makamaka/JSON-2.90/lib/JSON.pm" target="_blank" rel="noopener">JSON</a> to send and receive information.</p>



<p>First we need to have or create a set of OpenSSL certificates.<br />The below example uses self signed certificates, since they don&#8217;t cost any money and suit perfect for the purpose of this example.<br />There a million howto&#8217;s on the internet which explains these steps very thoroughly, so I won&#8217;t reinvent the wheel. I&#8217;m just going to post the steps I took to create:</p>



<ul class="wp-block-list"><li>a CA certificate</li><li>a client certificate</li><li>a server certificate</li></ul>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cd /path/to/SSL
cp /etc/ssl/openssl.cnf example.cnf
vim example.cnf  # Edit the file to your needs
openssl genrsa -aes256 -out private/example_com_ca.key 4096
openssl req -config example.cnf -new -x509 -extensions v3_ca -key private/example_com_ca.key -out certs/example_com_ca.crt -days 3650
openssl req -config example.cnf -new -nodes -keyout private/client01.key -out client01.csr -days 365
openssl ca -config example.cnf -policy policy_anything -out certs/client01.crt -infiles client01.csr
openssl req -config example.cnf -new -nodes -keyout private/server.key -out server.csr -days 365
openssl ca -config example.cnf -policy policy_anything -out certs/server.crt -infiles server.csr</pre>



<p>Next we will need to configure our web server (this example uses the Apache web server) in order to use our self signed certificates, and to proxy forward our WebAPI calls.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="apache" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">SSLEngine on
SSLCertificateFile       /path/to/SSL/certs/server.crt
SSLCertificateKeyFile    /path/to/SSL/private/server.key
SSLCertificateChainFile  /path/to/SSL/certs/example_com_ca.crt
SSLCACertificateFile     /path/to/SSL/certs/example_com_ca.crt
SSLVerifyClient require

ProxyPass /send/         http://internal-host/send.pl/
ProxyPassReverse /send/  http://internal-host/send.pl/

&lt;Proxy *>
            Options FollowSymLinks MultiViews
            AllowOverride All
            Order deny,allow
            allow from localhost
            allow from 8.8.8.8 # The client IP address
            deny from all
&lt;/Proxy></pre>



<p>The above the configuration for the external proxy server. The internal web server should have a pretty straight-forward configuration:</p>



<ul class="wp-block-list"><li>a cgi-handler for the Perl extension &#8216;.pl&#8217;</li></ul>



<p>I could have also send those proxy requests to an internal Mojolicious application, listening on a specific port. I&#8217;ll leave that for another article.</p>



<p>The test client script is going to make a SSL connection to the external web server, send some JSON and wait for the server to send some JSON data back. The interesting part in the below script is how to set up the SSL connection.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#!/usr/bin/perl
use strict; use warnings;

use HTTP::Request;
use LWP::UserAgent;
use IO::Socket::SSL;
use JSON;

my $data = {
    username  => 'skipper',
    password  => 'secret',
    variable  => 'value',
};

my $uri = 'https://example.com/send/event';
my $json = encode_json( $data );
my $req = HTTP::Request->new( 'POST', $uri );
$req->header( 'Content-Type' => 'application/json' );
$req->content( $json );
 
my $lwp = LWP::UserAgent->new(
    ssl_opts => {
        SSL_use_cert    => 1,
        SSL_version     => 'TLSv12',
        SSL_verify_mode => SSL_VERIFY_PEER,
        SSL_ca_file     => "/path/to/SSL/certs/example_com_ca.crt",
        SSL_cert_file   => "/path/to/SSL/certs/client01.crt",
        SSL_key_file    => "/path/to/SSL/private/client01.key",
    },
) or die "SSL Connection failed: $!";
my $res = $lwp->request( $req );
if ($res->is_success) {
    print "RESPONSE:", $res->content . "\n";
} 
else {
    print "ERROR: ", $res->status_line . "\n";
}</pre>



<p>The server example uses the Mojolicious frame work. Mojolicious is the porn for every Perl WebAPI developer. If you don&#8217;t know it, you should be ashamed and start reading about it right away.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="shell" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#!/usr/bin/env perl
 
use Mojolicious::Lite;

# A helper to identify visitors
helper whois => sub {
    my $c               = shift;
    my $headers         = $c->req->headers;
    my $agent           = $c->req->headers->user_agent || 'Anonymous';
    my $local_ip        = $c->tx->remote_address;
    my $remote_ip       = $headers->header('x-forwarded-for');

    return { 
        agent      => $agent, 
        local_ip   => $local_ip,
        remote_ip  => $remote_ip,
   };
};

any '/' => sub {
  my $c = shift;
  $c->render( text => "There is nothing to see here, move along" );
};
 
post '/event' => sub {
    my $c = shift;
    my $json = $c->req->json;
    my $data = {
        username        => $json->{username},
        password        => $json->{password},
        whois           => $c->whois,
    };
    $c-&amp;gt;render( json => $data );
};



### IMPORTANT
app->secret('some_cool_secret');
app->start;
</pre>



<p>Example output of the test client script:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">$ perl test_send.pl 
RESPONSE:
{"whois":{"remote_ip":"176.9.64.17","agent":"libwww-perl\/6.04","local_ip":"176.9.64.17"},"password":"secret","username":"skipper"}</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2014/11/perl-ssl-communication-in-web-applications/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Datatables and Perl (and a little bit of jQuery)</title>
		<link>https://jmorano.moretrix.com/2013/10/datatables-perl-and-bit-jquery/</link>
					<comments>https://jmorano.moretrix.com/2013/10/datatables-perl-and-bit-jquery/#comments</comments>
		
		<dc:creator><![CDATA[Johnny Morano]]></dc:creator>
		<pubDate>Wed, 09 Oct 2013 14:05:45 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=1014</guid>

					<description><![CDATA[Recently I&#8217;ve stumbled on a pretty cool OpenSource project called &#8221;datatables&#8221; (http://datatables.net/), which allows to easily create tables&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Recently I&#8217;ve stumbled on a pretty cool OpenSource project called &#8221;datatables&#8221; (<a title="Datatables" href="http://datatables.net/" target="_blank" rel="noopener">http://datatables.net/</a>), which allows to easily create tables in HTML that can be:</p>



<ul class="wp-block-list"><li>sorted</li><li>searched</li><li>paginated</li><li>scroll infinitely</li><li>themed</li><li>&#8230;</li></ul>



<p>And most important: it&#8217;s for free! I&#8217;ve always wanted to create an infinite scrolling table and now it&#8217;s just too easy:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">$(document).ready( function() {
    oTable = $('#ip_data').dataTable( {
        "bProcessing":     true,
        "bServerSide":     true,
        "bPaginate":       true,  
        "bScrollInfinite": true,
        "bScrollCollapse": true,
        "sScrollY":        "200px",
        "sAjaxSource":     "get_ip_data.pl",
    } );
} );
</pre>



<p>And that&#8217;s it! Well, ok, you need to include the Javascript file and CSS files of the Datatables Project of course and you need to create the table in HTML.</p>



<p>For instance:</p>



<figure id="ip_data" class="wp-block-table"><table><thead><tr><th>IP</th><th>Country</th><th>City</th><th>Latitude</th><th>Longitude</th></tr></thead><tbody><tr><td>Loading data from server</td></tr></tbody><tfoot><tr><th>IP</th><th>Country</th><th>City</th><th>Latitude</th><th>Longitude</th></tr></tfoot></table></figure>



<pre class="wp-block-preformatted">&nbsp;</pre>



<p>And then you will need a Perl script providing you the data for the table.<br />The below example allows to</p>



<ul class="wp-block-list"><li>search the tables</li><li>scroll infinitely</li><li>sort on the columns</li></ul>



<p>It also supplies the Datatables table with a total amount or rows in the database table.</p>



<p>This following script will be saved as &#8221;get_ip_data.pl&#8221;</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#!/usr/bin/perl
use strict; use warnings;
use DBI;
use JSON;
use CGI;

my @columns = qw/ip country_name city latitude longitude/;

my $q = CGI-&amp;gt;new;
my $db = DBI-&amp;gt;connect("dbi:mysql:host=localhost;db=testdb", 'testuser', 'xxxsecret');

my $params = $q-&amp;gt;Vars;

# Get the total count of rows in the table
my $sql_count = "select count(id) from geo_data";
my $count = $db-&amp;gt;selectrow_arrayref($sql_count)-&amp;gt;[0];

# Start building up the database query
my @values;
my $sql = "select ip,country_name,city,latitude,longitude from geo_data";

# if a search parameter was supplied in the AJAX call, build the WHERE part in the SQL statement
if( $params-&amp;gt;{sSearch} ){
    $sql .= ' WHERE ';
    $sql .= 'ip LIKE ? OR country_name LIKE ? or city LIKE ? or latitude LIKE ? or longitude LIKE ?';
    push @values, ('%'.$params-&amp;gt;{sSearch}.'%','%'.$params-&amp;gt;{sSearch}.'%','%'.$params-&amp;gt;{sSearch}.'%','%'.$params-&amp;gt;{sSearch}.'%','%'.$params-&amp;gt;{sSearch}.'%');
}

# if a sorting parameter was supplied in the AJAX call, build up the ORDER BY part in the SQL statement
if( $params-&amp;gt;{iSortingCols} ){
    $sql .= ' ORDER BY';
    foreach my $c (0 .. ( $params-&amp;gt;{iSortingCols} -1 )){
        $sql .= ' ' . $columns[ $params-&amp;gt;{"iSortCol_$c"} ] . ' ' . $params-&amp;gt;{"sSortDir_$c"};
        $sql .= ','
    }
    $sql =~ s/,$//;
}

# Limit the output and also allow to paginate or scroll infinitely
$sql .= " LIMIT ? OFFSET ?";
push @values, (($params-&amp;gt;{iDisplayLength} &amp;gt; 0 ? $params-&amp;gt;{iDisplayLength} : 25), ( $params-&amp;gt;{iDisplayStart} // 0));

# Fetch the data from the database
my $data = $db-&amp;gt;selectall_arrayref($sql, { Slice =&amp;gt; [] }, @values);

# Return the JSON object
print $q-&amp;gt;header('application/json');
my $json = encode_json({ aaData =&amp;gt; $data, iTotalRecords =&amp;gt; $count, iTotalDisplayRecords =&amp;gt; $count, sEcho =&amp;gt; int($params-&amp;gt;{sEcho}) });
print $json;
</pre>



<p>An example can be found overhere: <a title="Charon Map" href="http://www.moretrix.com/~insaniac/map/map.pl" target="_blank" rel="noopener">http://www.moretrix.com/~insaniac/map/map.pl</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2013/10/datatables-perl-and-bit-jquery/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Google GeoChart, JSON and Perl</title>
		<link>https://jmorano.moretrix.com/2013/10/google-geochart-json-perl/</link>
					<comments>https://jmorano.moretrix.com/2013/10/google-geochart-json-perl/#comments</comments>
		
		<dc:creator><![CDATA[Johnny Morano]]></dc:creator>
		<pubDate>Wed, 09 Oct 2013 09:33:48 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[MySQL]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=1006</guid>

					<description><![CDATA[The Google API GeoChart Map (https://developers.google.com/chart/interactive/docs/gallery/geochart) is pretty nice widget to generate nice maps based on certain values.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>The Google API GeoChart Map (<a title="Google GeoChart Map" href="https://developers.google.com/chart/interactive/docs/gallery/geochart" target="_blank" rel="noopener">https://developers.google.com/chart/interactive/docs/gallery/geochart</a>) is pretty nice widget to generate nice maps based on certain values. It has quite a lot of features and it is very easy to use.</p>



<p>Before we look at the Google API for GeoChart, let&#8217;s first set up a script which will get data out of a database and return it in a JSON formatted object.<br />In this example we will use Perl and three Perl modules:</p>



<ul class="wp-block-list"><li>DBI</li><li>JSON</li><li>CGI</li></ul>



<p>When converting database values to a JSON object (or text string), it is very important that all data is properly type-casted.<br />In the following example you will see that we do:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">$_-&amp;gt;[1] = int($_-&amp;gt;[1]) foreach @$data;
</pre>



<p>This snippet will actually make our INTEGER value into a real integer. The DBI module had returned it as a normal string (that&#8217;s just how DBI works).</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">#!/usr/bin/perl
use strict; use warnings;
use DBI;
use JSON;
use CGI;

my $q = CGI-&amp;gt;new;
my $db = DBI-&amp;gt;connect("dbi:mysql:host=localhost;db=testdb", 'testuser', 'xxxsecret');

my $sql = "SELECT country_name, count(id) as total from geo_data group by country_name";
my $data = $db-&amp;gt;selectall_arrayref($sql);
$_-&amp;gt;[1] = int($_-&amp;gt;[1]) foreach @$data;
unshift(@$data, ['Country', 'Attacks']);

print $q-&amp;gt;header('application/json');
my $json = encode_json($data);
print $json;
</pre>



<p>The above Perl script will be saved as &#8221;get_countries_data.pl&#8221;.</p>



<p>In the below Javascript example, we will use the Google API for the GeoChart Map and <a title="jQuery" href="http://www.jquery.com/" target="_blank" rel="noopener">jQuery</a> for making the AJAX call to our Perl script. Since the Perl script already provides the data in a JSON format, we do not need to convert or parse it.<br />Furthermore the Javascript code is pretty straightforward and based on the example found at https://developers.google.com/chart/interactive/docs/gallery/geochart, except for the AJAX part.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">    google.load('visualization', '1', {packages: ['geochart']});
    google.setOnLoadCallback(drawVisualization);

    function drawVisualization() {
        var options = {
            height: '500',
            width: '1200',
            colorAxis: {minValue: 0,  colors: ['#FFC26B', 
                                               '#FFAF3B', 
                                               '#FF9700', 
                                               '#C1852F', 
                                               '#A86400']},
            datalessRegionColor: '#FAFAFA',
            backgroundColor: '#F4EFE7',
        };
    
        $.ajax({
            type: 'POST',
            url: "get_countries_data.pl",
            dataType: "json",
            async: false,
            success: function(json_data) {
                var data = google.visualization.arrayToDataTable(json_data);
                var chart = new google.visualization.GeoChart(
                                   document.getElementById('visualization') );

                chart.draw(data, options);
            }
        });
    }</pre>



<p>An example of this setup can be found at <a title="Charon Map" href="http://www.moretrix.com/~insaniac/map/map.pl" target="_blank" rel="noopener">http://www.moretrix.com/~insaniac/map/map.pl</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2013/10/google-geochart-json-perl/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Perl/Ajax with JSON</title>
		<link>https://jmorano.moretrix.com/2011/03/perlajax-with-json/</link>
					<comments>https://jmorano.moretrix.com/2011/03/perlajax-with-json/#respond</comments>
		
		<dc:creator><![CDATA[insaniac]]></dc:creator>
		<pubDate>Tue, 29 Mar 2011 14:18:42 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=555</guid>

					<description><![CDATA[I just discovered this very interesting article about Perl, CGI, Template and Ajax using JSON. I&#8217;m going to&#8230;]]></description>
										<content:encoded><![CDATA[<p>I just discovered this very interesting article about Perl, CGI, Template and Ajax using JSON.</p>
<p>I&#8217;m going to use to beef up my image browser which I quickly wrote to simply the contents of directory full with images. (can be found overhere <a href="http://yamamoto.moretrix.com/~insaniac/grtp/">http://yamamoto.moretrix.com/~insaniac/grtp/</a></p>
<p>Here&#8217;s the link to the <a href="http://rohan.almeida.in/archives/get-started-with-jquery-ajax-and-json-in-your-perl-web-applications">article</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2011/03/perlajax-with-json/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Perl, Facebook and GMail Contacts</title>
		<link>https://jmorano.moretrix.com/2011/02/perl-facebook-and-gmail-contacts/</link>
					<comments>https://jmorano.moretrix.com/2011/02/perl-facebook-and-gmail-contacts/#comments</comments>
		
		<dc:creator><![CDATA[insaniac]]></dc:creator>
		<pubDate>Mon, 28 Feb 2011 16:19:57 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Dev]]></category>
		<category><![CDATA[Facebook]]></category>
		<category><![CDATA[GMail]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<guid isPermaLink="false">http://jmorano.moretrix.com/?p=494</guid>

					<description><![CDATA[There are probably already 13 in a dozen applications or websites that can do this, but I wanted&#8230;]]></description>
										<content:encoded><![CDATA[<p>There are probably already 13 in a dozen applications or websites that can do this, but I wanted to write one on my own, in the programming language I like: <a href="http://www.perl.org/">Perl</a>.</p>
<p>Nowadays writing programs for tasks concerning <a href="http://en.wikipedia.org/wiki/Web_2.0">Web 2.0</a> alike websites, is rather simple and easy. The only thing you will have to do, is learn their <a href="http://en.wikipedia.org/wiki/API">API</a>. These API are mostly XML based requests and replies.</p>
<p>Most programming languages then write wrapper classes that call and access those API&#8217;s, like was done in Perl.<br />
Thanks to the following modules, which can be found on <a href="http://search.cpan.org/">CPAN</a>, I wrote a small script which loads my contacts on <a href="http://www.facebook.com/">Facebook</a> and then updates or creates my contacts in <a href="http://www.gmail.com/">GMail</a>.<br />
<span id="more-494"></span><br />
The script will retrieve some contact information, like the birthday, email addresses, status messages, and website information from Facebook as well as the profile picture of the contact. Then it will search your GMail Contact list for the user and will update the contact if it is found. Non-existing contacts will be ignored.</p>
<p>The modules used in the script are:</p>
<pre class="brush:perl">
use WWW::Facebook::API;
use WWW::Google::Contacts;
use HTTP::Request;
use LWP;
</pre>
<p>All these modules can be downloaded from CPAN.</p>
<p>You will need to <a href="http://developers.facebook.com/">create a Facebook application</a>, or you can use the application I have added. Before you can use the Facebook API, your application needs to be registered and known to Facebook. If you are not sure how to create and register an application at Facebook, please use mine. (No worries, I won&#8217;t do evil stuff)</p>
<p>After the module have been called in the script, we need to initialize some variables:</p>
<pre class="brush:perl">
my $TMP    = $ENV{HOME}.'/tmp';
my %MONTHS = (
        January => '01',      February => '02',     March     => '03',
        April   => '04',      May      => '05',     June      => '06',
        July    => '07',      August   => '08',     September => '09',
        October => '10',      November => '11',     December  => '12',
);

my $facebook_api      = 'dad7ea6af99ba4ee11d6007f0a27cc6a';
my $facebook_secret   = '19d45131916886ffdad8d0a6899d6794';
my $facebook_clientid = '141446449211973';
my $facebook_browser  = '/usr/bin/firefox';
my $gmail_user        = 'user@gmail.com';
my $gmail_password    = 'secret';
</pre>
<ul>
<li>$TMP = we need to save the profile pics from Facebook and GMail somewhere on disk</li>
<li>%MONTHS = conversion table for updating birthdates on GMail</li>
<li>$facebook_ variables = numbers you get when you register an application on Facebook</li>
<li>$gmail_ variables = obviously you will need a GMail account to update your contacts</li>
</ul>
<pre class="brush:perl">
my $client = WWW::Facebook::API->new(
    desktop         => 1,
    api_version     => '1.0',
    api_key         => $facebook_api,
    secret          => $facebook_secret,
);
$client->app_id($facebook_clientid);

local $SIG{INT} = sub {
    print "Logging out of Facebookn";
    my $r = $client->auth->logout;
    exit(1);
};

my $token = $client->auth->login(browser => $facebook_browser);
$client->auth->get_session($token);

my $google = WWW::Google::Contacts->new( username => $gmail_user, password => $gmail_password );
my $http   = LWP::UserAgent->new();
</pre>
<p>In the above part a Facebook object is created and a Facebook session will be created. If this is the first run that the program runs, it will ask on a Facebook page in your browser, to allow this application. Once allowed, the Facebook page can be closed.</p>
<p>The script will then also create a GMail object and a LWP object. The LWP object is needed to download the profile picture from the Facebook friend page.</p>
<p>In the next part, the friends list will be downloaded from Facebook, binded with the fields of information we are searching for.</p>
<pre class="brush:perl">
print "About to get friends from Facebook...n";
my $friends_info = $client->users->get_info(
        uids   => $client->friends->get, 
        fields => [ qw/name first_name last_name status pic_big birthday email website about_me/ ] 
);

foreach my $friend (@{$friends_info}){
</pre>
<p>Ok, now we are ready to start taking the information from Facebook and updating it in GMail. The next part is the full content of the foreach loop, that was started above.</p>
<pre class="brush:perl">
    # search google contact
    print "Searching for $friend->{name}...n";
    my @contacts = $google->contacts->search({full_name => $friend->{name}});
    if(not scalar @contacts){
        print "- $friend->{name} not found in Gmail Contacts Listn";
        next;
    }

    my $contact = pop @contacts;
    next unless defined $contact;

    if( defined $friend->{birthday} and $friend->{birthday} ne ''){
        my ($month, $day, $year) = ($friend->{birthday} =~ /^(D+) (d+)(?:, (d+))/);
        if(defined $year and defined $month and defined $day){
            $day   = sprintf '%02d', $day;
            $contact->birthday("${year}-$MONTHS{$month}-$day");
        }
    }

    if( defined $friend->{about_me} and $friend->{about_me} ne ''){
        $contact->notes($friend->{about_me});
    }

    if( defined $friend->{website} and $friend->{website} ne ''){
        my $websites = $contact->website;
        $websites ||= [];
        $contact->website($friend->{website}, @$websites) 
                        unless grep /Q$friend->{website}E/, @$websites;
    }

    if( defined $friend->{email} and $friend->{email} ne ''){
        my $emails = $contact->email;
        $emails ||= [];
        $contact->email($friend->{email}, @$emails) 
                        unless grep /Q$friend->{email}E/, @$emails;
    }

    if( defined $friend->{status}->{message} and $friend->{status}->{message} ne ''){
        my $jots = $contact->jot;
        $jots ||= [];
        $contact->jot($friend->{status}->{message}, @$jots)
                        unless grep /Q$friend->{status}->{message}E/, @$jots;
    }

    eval {
        $contact->update();
        print "- Contact information updatedn";
    };
    print "- Updating ".$contact->full_name." failed: $@n" if $@;

    # First update the contact information and then update the profile photo
    if( defined $friend->{pic_big} and $friend->{pic_big} ne ''){
        my $req = HTTP::Request->new('GET', $friend->{pic_big});
        my $file = $http->request($req);

        if($file->is_success){
            my $fpic = $TMP.'/fpic'.$friend->{uid}.'.jpg';
            my $gpic = $TMP.'/gpic'.$friend->{uid}.'.jpg';

            # save the Facebook profile pic to disk
            open my $fh, '>', $fpic or die "ERROR: $!n";
            print $fh $file->decoded_content;
            close $fh;

            # create a backup of the existing profile pic and then
            # delete it from Gmail Contacts
            if ( $contact->photo->exists ) {
                eval {
                    $contact->photo->to_file($gpic);
                };
                print "- Save of GMail profile pic failed: $@n" if $@;
            }

            # if a Facebook profile pic was downloaded, now upload it to 
            # Gmail Contacts
            if ( -f $fpic ) {
                eval {
                    $contact->photo->from_file($fpic);
                    $contact->photo->update;
                    print "- Profile pic ".$contact->full_name." updatedn";
                };
                print "- Failed to update profile pic: $@n" if $@;
            }
        }
        else {
            print "Failed to download profile picture of ". $friend->{name} ."n";
        }
    }
</pre>
<p><strong>Set Permissions on Facebook</strong>:<br />
The Facebook application needs more permissions than the basic permissions which are granted the first time you use the application. Copy paste the following URL into browser and you will presented a Facebook to allow or disallow the extended permissions for this application:</p>
<p><a href="http://www.facebook.com/dialog/oauth?client_id=141446449211973&#038;redirect_uri=https://jmorano.moretrix.com&#038;scope=email,read_stream,user_birthday,friends_birthday,user_website,friends_website,export_stream,friends_online_presence,friends_status,sms,user_status,friends_about_me,friends_hometown,friends_location,publish_stream,read_stream,status_update">http://www.facebook.com/dialog/oauth?client_id=141446449211973&#038;redirect_uri=https://jmorano.moretrix.com&#038;scope=email,read_stream,user_birthday,friends_birthday,user_website,friends_website,export_stream,friends_online_presence,friends_status,sms,user_status,friends_about_me,friends_hometown,friends_location,publish_stream,read_stream,status_update<br />
</a></p>
<p><strong>References</strong>:</p>
<ul>
<li><a href="http://developers.facebook.com/docs/reference/api/user/">http://developers.facebook.com/docs/reference/api/user/</a></li>
<li><a href="http://developers.facebook.com/docs/authentication/">http://developers.facebook.com/docs/authentication/</a></li>
<li><a href="http://search.cpan.org/~merixzon/WWW-Google-Contacts-0.28/lib/WWW/Google/Contacts.pm">http://search.cpan.org/~merixzon/WWW-Google-Contacts-0.28/lib/WWW/Google/Contacts.pm</a></li>
<li><a href="http://search.cpan.org/~unobe/WWW-Facebook-API-0.4.18/lib/WWW/Facebook/API.pm">http://search.cpan.org/~unobe/WWW-Facebook-API-0.4.18/lib/WWW/Facebook/API.pm</a></li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://jmorano.moretrix.com/2011/02/perl-facebook-and-gmail-contacts/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
