Mobile Device Detection and Redirection with Perl and CGI

Last month, I took some time and wrote about Mobile Device Detection and Redirection with PHP. Well, it turns out that some folks can’t (or choose not to) make use of PHP and favor the Perl/CGI approach to web development. This article covers the same bases and presents a set of examples implemented using Perl and Lincoln Stein’s great CGI.pm module.

Download Code and Examples Here:
From Github: http://github.com/mrlynn/MobileBrowserDetectionExample

or locally:
Version 0.3 (Latest – includes perl/cgi AND PHP examples)
[download id=”2″]

Version 0.2 (Older version – PHP examples only)
[download id=”1″]

View the working example using Perl/CGI here: http://mlynn.org/uatest/cgi-bin/index.cgi

Redirecting a user based on the type of device they are using is not rocket science. In fact, it can be accomplished quite simply using an apache redirect in a .htaccess file.

RewriteCond %{HTTP_USER_AGENT} ^.*iPad.*$
RewriteRule ^(.*)$ http://ipad.yourdomain.com [R=301]

The issue with this approach is that users coming to your site using an iPad will never have the ability to see the other versions of your site. for many, that may be a satisfactory solution. However, if you want users to have the ability to view a version of your site designed specifically for their type of mobile device by default – but have the option to click a link and either view or optionally set a preference for another version of the site, this article is for you.

Perl and CGI have been around for many years and are in wide use on the web. Perl is extremely extensible and using the very popular CGI.pm Perl Module written by Lincoln Stein, it’s very easy to write code to dynamically manage your web site.

Where PHP has built-in variables designed to expose the server and apache session environment ($_SERVER, $_SESSION), Perl and CGI.pm make use of %ENV and module variables such as param(). Consider the following table which contrasts PHP and Perl/CGI.

User Agent

PHP

$_SERVER['HTTP_USER_AGENT']

Perl/CGI

$ENV{HTTP_USER_AGENT}

Reading Cookies

PHP

$cookievalue = $_COOKIE['COOKIENAME']

Perl/CGI

use CGI;
$query=new CGI;
$cookievalue = $query->cookie('COOKIENAME');

Setting Cookies

PHP

setcookie(name, value, expire, path, domain);

Perl/CGI

$cookie = $query->cookie(-name=>'COOKIENAME',
			 -value=>'COOKIEVALUE',
			 -expires=>'+4h',
			 -path=>'/');
print $query->header(-cookie=>$cookie);

Now that we have the basics down, the rest is easy. We’ll want to check the users’ device type by querying the user agent, check the value of a cookie to see if they’ve specified a preference for something other than the site designed for their specific device and redirect accordingly.

The initial landing page does most of the heavy lifting.

index.cgi

#!/usr/bin/perl
require 'includes/config.inc.pl';
require 'includes/functions.inc.pl';

use CGI;
$query = new CGI; 

$useragent = $ENV{HTTP_USER_AGENT};
$sitepref = $query->cookie( 'SITEPREF' );

if ( ismobile( $useragent ) ) {
        if ( !$sitepref ) {
          if ( isipad( $useragent ) ) {
                  print $query->redirect( "$IPADURL" );
          } else {
              if ( isiphone( $useragent ) ) {
                          print $query->redirect( "$IPHONEURL" );
                  } else {
                          print $query->redirect( "$MOBILEURL" );
                  }
          }
        } else {
          if ( $sitepref=='MOBILE' ) {
                  print $query->redirect( "$MOBILEURL" );
          } else {
                  if ( $sitepref=='IPHONE' ) {
                          print $query->redirect( "$IPHONEURL" );
                  } else {
                          if ( $sitepref=='IPAD' ) {
                                  print $query->redirect( "$IPADURL" );
                          } else {
                                  print $query->redirect( "$NORMALURL" );
                          }
                  }
            }
        }
} else {
    if ( !$sitepref ) {
          print $query->redirect( "$NORMALURL" );
    } else {
      if ( $sitepref=='MOBILE' ) {
          print $query->redirect( "$MOBILEURL" );
      } else {
          if ( $sitepref=='IPAD' ) {
              print $query->redirect( "$IPADURL" );
          } else {
              if ( $sitepref=='IPHONE' ) {
                  print $query->redirect( "$IPHONEURL" );
              } else {
                  print $query->redirect( "$NORMALURL" );
              }
          }  
      }
    }
}

And the included files… which set the URL values and contain many of the functions.

functions.inc.pl

sub setcookiealive() {
        my ($name,$value,$expires,$redirect) = @_;
        $cookie = $query->cookie(-name=>"$name",
                         -value=>"$value",
                         -expires=>'+5d',
                         -path=>'/');
        if ($redirect) {
                print $query->redirect("$redirect","-cookie=>$cookie");
        } else {
                print $query->header(-cookie=>$cookie);
        }
}

sub in_array {
     my ($arr,$search_for) = @_;
     my %items = map {$_ => 1} @$arr; # create a hash out of the array values
     return (exists($items{$search_for}))?1:0;
}

sub ismobile {
        $useragent=lc(@_);
        $is_mobile = '0';

        if($useragent =~ m/(android|up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone)/i) {
                $is_mobile=1;
        }

        if((index($ENV{HTTP_ACCEPT},'application/vnd.wap.xhtml+xml')>0) || ($ENV{HTTP_X_WAP_PROFILE} || $ENV{HTTP_PROFILE})) {
                $is_mobile=1;
        }

        $mobile_ua = lc(substr $ENV{HTTP_USER_AGENT},0,4);
        @mobile_agents = ('w3c ','acs-','alav','alca','amoi','andr','audi','avan','benq','bird','blac','blaz','brew','cell','cldc','cmd-','dang','doco','eric','hipt','inno','ipaq','java','jigs','kddi','keji','leno','lg-c','lg-d','lg-g','lge-','maui','maxo','midp','mits','mmef','mobi','mot-','moto','mwbp','nec-','newt','noki','oper','palm','pana','pant','phil','play','port','prox','qwap','sage','sams','sany','sch-','sec-','send','seri','sgh-','shar','sie-','siem','smal','smar','sony','sph-','symb','t-mo','teli','tim-','tosh','tsm-','upg1','upsi','vk-v','voda','wap-','wapa','wapi','wapp','wapr','webc','winw','winw','xda','xda-');

        if(in_array(@mobile_agents,$mobile_ua)) {
                $is_mobile=1;
        }

        if ($ENV{ALL_HTTP}) {
                if (index(lc($ENV{ALL_HTTP}),'OperaMini')>0) {
                        $is_mobile=1;
                }
        }

        if (index(lc($ENV{HTTP_USER_AGENT}),'windows')>0) {
                $is_mobile=0;
        }
    return $is_mobile;
}

sub isiphone {

        $useragent = @_;
        $iphone=0;
        if (lc($useragent) =~ m/iphone/) {
                $iphone=1;
        }
        return $iphone;
}

sub isipad {

        $useragent = @_;
        $ipad=0;
        if (lc($useragent) =~ m/ipad/) {
                $ipad=1;
        }
        return $ipad;
}
1;

config.inc.pl

$SITEURL='http://mlynn.org/uatest/cgi-bin/index.cgi';
$LOGFILE='debug.log';
$MOBILEURL='http://mlynn.org/uatest/cgi-bin/mobile/index.cgi';
$IPHONEURL='http://mlynn.org/uatest/cgi-bin/iphone/index.cgi';
$IPADURL='http://mlynn.org/uatest/cgi-bin/ipad/index.cgi';
$NORMALURL='http://mlynn.org/uatest/cgi-bin/normal/index.cgi';
1;

Related Sites and Interesting Links

Have a site you’d like to add to this list? Send me an email or submit a comment.

Advertisements
Tagged , ,

5 thoughts on “Mobile Device Detection and Redirection with Perl and CGI

  1. […] Updated 07/20/2010 ** See also http://www.mlynn.org/2010/07/mobile-device-detection-and-redirection-with-perl-and-cgi/ for additional information on Mobile Browser Detection and Redirection using Perl / […]

  2. […] mobile phones to another site – check out this blog post I wrote on this very topic… Using Perl: Mobile Browser Device Detection and Redirection using Perl, CGI | Mike's Blog Using PHP Mobile Device Detection and Redirection using PHP | Mike's Blog I hope this […]

  3. This is terrific stuff, along with the paper on PHP mobile device detection. Thanks for doing both of them!

  4. brad andersen says:

    thank you for this. i’d like to point out that, while i believe it easier to set up a basic website using php, the differences in say, setting up cookies are not as stark as it might seem from this article. for example, while one may create a cookie with a php one-liner, try putting any of those arguments in the ‘wrong’ order, or leaving any one of them out. being verbose can be very helpful.

    again, very nice article, and, thank you!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: