Welcome, Guest :: Blog Home | Login | Register

Articles
Deploying Catalyst Apps via mod_perl
2011-09-19 22:58:11 Permalink

Tags: catalyst apache mod_perl


Here's a simple method to deploying your Catalyst MVC Web Framework applications using mod_perl.

First make sure you have mod_perl Apache module installed and are calling the module in your Apache config file.

Open Apache config file:

Code:
vim /etc/httpd/conf/httpd.conf


Add the following line, if not present:

Code:
LoadModule perl_module modules/mod_perl.so


Now, in your "Virtual Host" file:

Code:
vim /etc/httpd/conf.d/domain.conf


Add the following. Change "server.ip.address" to your server's real ip address, "ServerAdmin" to your email address, "ServerName" and "ServerAlias" to your domain name, "domain.name" in the paths to your apps location and "myapp" to the real name of your Catalyst application.

Code:
<VirtualHost server.ip.address:80>
     ServerAdmin user@domain.name
     ServerName domain.name
     #ServerAlias www.domain.name

     ErrorLog /var/www/domain.name/logs/error.log
     CustomLog /var/www/domain.name/logs/access.log combined

         DocumentRoot /var/www/domain.name/root

         PerlSwitches -I/var/www/domain.name/lib
         <Perl>
            use lib '/var/www/domain.name/lib';
         </Perl>

         PerlModule myapp
         <Location />
            SetHandler          modperl
            PerlResponseHandler myapp
         </Location>

         <Location /static>
            SetHandler default-handler
         </Location>
         <Location /images>
            SetHandler default-handler
         </Location>
         <Location /media>
            SetHandler default-handler
         </Location>
</VirtualHost>


Restart Apache and you should be good to go!

~Stephen


[ Comments (0) ]


Perl Cron Script for Astroslacker.com
2011-09-18 14:55:28 Permalink

Tags: perl


So how does Astroslacker.com find all that great news? Well, I programmed several cron scripts to fetch XML feeds, find and create images, and create a wav file for descriptions. Here's how it's done...

Perl Code:
#!/usr/bin/perl -w
use strict;

use LWP::Simple;
use XML::Simple;
use Image::Magick;
use Data::Dumper;

use lib "/var/www/astroslacker.com/lib";
#use DB::Main;
use DB::MySQLDB;

my $schema = DB::MySQLDB->connect(
    'dbi:mysql:astroslacker:localhost',
    'user', 'password'
);

my $content = LWP::Simple::getstore("http://www.physorg.com/xml-feed/space-news/astronomy/", "/var/www/astroslacker.com/space-feed/store-space-feed.xml");

my $xml  = new XML::Simple;
my $data = $xml->XMLin("/var/www/astroslacker.com/space-feed/store-space-feed.xml");

print Dumper($data->{item});

foreach my $item (@{$data->{item}}) {
    my $rs_exist = $schema->resultset('Feeds')->find({ 'link' => $item->{'link'} });
    
    unless ($rs_exist) {
        my $image = '';
        my $link  = $item->{'link'};
        
        $link =~ s/\<link\>//;
        $link =~ s/\<\/link\>//;
        
        my $feed_image = _get_image($link) || '';
        
        if ($feed_image) {
            # sub out src url only
            $feed_image =~ s{^.*src}{src}i;
            $feed_image =~ s{src\=\"}{};
            $feed_image =~ s{(align+).*}{$1}i;
            $feed_image =~ s{\"\salign}{}g;
            
            my ($filename, $dummy, $extension) = File::Basename::fileparse($feed_image, qr{\.[^.]*$});
            
            my $upload_dir = '/var/www/astroslacker.com/root/feed_images';
            my $localimage = "$filename$extension";
            my $contentx   = LWP::Simple::getstore($feed_image, "$upload_dir/$localimage");
            my $imageurl   = "root/feed_images/thumb_$localimage";
            my $thumbnail  = new Image::Magick;
            my $full       = "$upload_dir/$localimage";
            my $thumb      = "$upload_dir/thumb_$localimage";
            
            $thumbnail->Read($full);
            $thumbnail->Resize('140x140');
            $thumbnail->Write(filename => $thumb);
            
            $image = $imageurl;
        }
        
        my $rc = $schema->resultset('Feeds')->create({
            id             => undef,
            title          => $item->{'title'} || undef,
            description => $item->{'description'} || undef,
            link           => $item->{'link'} || undef,
            image       => $image,
            category    => $item->{'category'} || undef,
            date         => $item->{'dc:date'} || undef,
            active       => 1,
        });
	
	# TTS descriptions
	my $wav_file  = time. '.wav';
	my $form_text = $item->{'description'};
	my $tts_file  = _generate_wav($wav_file,$form_text);
	
	print "$tts_file\n";
	
	my $wavs = $schema->resultset('Wav')->create({
	    id => undef,
	    feed_id => $rc->id(),
	    wav => $tts_file,
	});
    } else {
	print "Already stored.\n";
    }
}

my $time = localtime(time);

open FILE, ">", "/var/www/astroslacker.com/lastcron.txt";
print FILE $time;
close FILE;

sub _generate_wav {
    my $wav_file  = shift;
    my $form_text = shift;
    
    print qq(Wave File: $wav_file\n);
    print qq(Form Text: $form_text\n);
    
    my $user_dir  = '/var/www/astroslacker.com/root/feed_wav';
    my $temp_dir  = '/var/www/.astroslacker.com/root/feed_wav/temp';
    
    mkdir($temp_dir) unless (-d $temp_dir);
    
    my $temp_file = time. '.txt';
    
    my $text = $temp_dir. '/' .$temp_file;
    my $wave = $user_dir. '/' .$wav_file;
    
    open F, "> $text";
    print F $form_text;
    close F;
    
    my $convert = system("cat $text | text2wave -o $wave");
    
    print "System: cat $text | text2wave -o $wave\n";
    print "Sleeping for 2 seconds\n";
    
    sleep 2;
    
    unlink($text);
    
    return $wav_file;
}

sub _get_image {
    my $link = shift;
    
    my $ua = LWP::UserAgent->new;
       $ua->agent("Mozilla/8.0");
    
    my $req = HTTP::Request->new(GET => $link);
       $req->header('Accept' => 'text/html');
    
    my $res = $ua->request($req);
    
    my $feed_image = '';
    
    if ($res->is_success) {
	my @lines = split("\n", $res->content);
	
	my $count = 0;
	foreach my $line (@lines) {
	    $count++;
	    if ($line =~ /\<\!\-\- google\_ad\_section\_start \-\-\>/) {
		last;
	    }
	}
	
	$count = ($count + 2);
	
        my $enlarge = '';
	my $n_count = 0;
	foreach my $line (@lines) {
	    $n_count++;
	    if ($n_count == $count and $line =~ /.(png|jpg|gif)/) {
		$feed_image = $line;
	    }
	}
    }
    
    my $ilink = '';
    if ($feed_image) {
	my @linker = split(' />', $feed_image);
	
	$ilink  = $linker[0];
	$ilink .= ' />';
    }
    
    return $ilink;
}


I have programmed the main site using CGI::Application, a Perl MVC web framework. Here's a look at the source code.

Perl Code:
package Index;

#use lib '/usr/local/lib/perl5/site_perl/5.10.0:/usr/local/share/perl5';

use base 'CGI::Application';
use strict;

use CGI::Application::Plugin::TT;
use CGI::Session;
use Email::Valid;
use Email::MIME;
use Email::MIME::Creator;
use Email::Send;
use DateTime;
use Data::Dumper;

use lib "/var/www/astroslacker.com/lib";
#use DB::Main;
use DB::MySQLDB;

sub cgiapp_init
{
    my $self    = shift;
    my $query   = $self->query;
    my $sid     = $query->cookie( 'CGISESSID' ) || undef;
    my $session = CGI::Session->new("driver:File", $sid, {Directory=>'/tmp'});
    
    $self->param( 'session' => $session );
    
    if ( !$sid or $sid ne $session->id )
    {
       my $cookie = $query->cookie(
          -name    => 'CGISESSID',
          -value   => $session->id,
          -expires => '+1y'
       );
       
       $self->header_props( -cookie => $cookie );
    }
    
    # Configure the template
    $self->tt_config(
	TEMPLATE_OPTIONS => {
	INCLUDE_PATH => '/var/www/astroslacker.com/templates',
	#POST_CHOMP   => 1,
	#FILTERS => {
	#    'currency' => sub { sprintf('$ %0.2f', @_) },
	#},
	},
    );
}

sub setup
{
    my $self = shift;
    
    $self->start_mode('index');
    $self->run_modes(
	'index'               => 'index',
	'loginrequest'        => 'loginrequest',
	'clientlogin'         => 'clientlogin',
	'category'            => 'category',
	'clientregistration'  => 'clientregistration',
	'registrationrequest' => 'registrationrequest',
	'clienthome'          => 'clienthome',
	'logout'              => 'logout'
    );
}

sub index
{
    my $self = shift;
    
    my $query   = $self->query();
    my $session = $self->param('session');
    my $schema  = DB::MySQLDB->connection;
    
    my $rc = $schema->resultset('Hits')->create({
	id         => undef,
	ip         => $ENV{REMOTE_ADDR}     || undef,
	cookie     => $ENV{HTTP_COOKIE}     || undef,
	referer    => $ENV{HTTP_REFERER}    || undef,
	hostname   => $ENV{REMOTE_HOST}     || undef,
	method     => $ENV{REQUEST_METHOD}  || undef,
	user_agent => $ENV{HTTP_USER_AGENT} || undef,
	page       => 'index',
    });
    
    my $stardate     = $self->_stardate();
    my $stardate_mp3 = $self->_stardate_mp3();
    
    my $lastupdate = '';
    open (CRON, "/var/www/astroslacker.com/lastcron.txt");
    while (my $record = <CRON>) {
       $lastupdate = $record;
    }
    close(CRON);
    
    # Mon Nov  1 21:00:06 2010
    my ($cweek, $cmonth, $cblank, $cday, $ctime, $cyear) = split(/\s/, $lastupdate);
    my ($nweek, $nmonth, $nblank, $nday, $ntime, $nyear) = split(/\s/, localtime(time));
    
    my ($chours, $cminutes, $cseconds) = split(/\:/, $ctime);
    my ($nhours, $nminutes, $nseconds) = split(/\:/, $ntime);
    
    my $expiredtime = ($nminutes - $cminutes);
    my $nextupdate = (60 - $expiredtime);
    
    my $showupdate = '';
    if ($nextupdate > 0) {
	if ($nextupdate == 1) {
	    $showupdate = qq(| next update in $nextupdate minute);
	} else {
	    $showupdate = qq(| next update in $nextupdate minutes);
	}
    }
    
    # articles
    my $page = $query->param("page");
    
    $page = 1 if( defined $page and $page !~ /^\d+$/ );
    
    my $rs = $schema->resultset('Feeds')->search(
	undef,
	{
	    page => $page || 1,
	    rows => 15,
	    prefetch => 'wav',
	    order_by => 'date DESC',
	}
    );
    
    #use Data::Dumper;
    #print STDERR Dumper($rs);
    
    my $pager = $rs->pager;
    
    use URI::Escape;
    
    my @feeds;
    while (my $rec = $rs->next) {
	# truncate title
	my $title = substr($rec->title, 0, 76);
	
	if ($ENV{'HTTP_USER_AGENT'} =~ 'Android' or $ENV{'HTTP_USER_AGENT'} =~ 'iPhone OS') {
	    if (length($rec->title) > 36) {
		$title .= '...';
	    }
	} else {
	    if (length($rec->title) > 76) {
		$title .= '...';
	    }
	}
	
	my @date = split(" ", $rec->date);
	my @time = split("-", $date[1]);
	
	my $encent = uri_escape($rec->category);
	
	my $link_cat = $self->_scruburl($rec->category);
	
	my $feed_ref = {};
	
	$feed_ref->{link}     = $rec->link;
	$feed_ref->{title}    = $title;
	$feed_ref->{category} = $rec->category;
	$feed_ref->{lcat}     = $link_cat;
	$feed_ref->{date}     = $date[0];
	$feed_ref->{time}     = $time[0];
	$feed_ref->{image}    = $rec->image;
	
	my $medium = $rec->image;
	   $medium =~ s/thumb\_/medium\_/g;
	   
	$feed_ref->{medium_image} = $medium;
	
	$feed_ref->{description} = $rec->description;
	$feed_ref->{wav}         = $rec->wav->wav;
	
	push @feeds, $feed_ref;
    }
    
    my $t_page      = $pager->current_page;
    my $t_pages     = $pager->last_page;
    my $t_show_page = qq($t_page of $t_pages);
    
    my $prevpage = '<< <';
    my $nextpage = '>> >';
    
    if ($pager->previous_page) {
	my $ppage = $pager->previous_page;
	my $fpage = $pager->first_page;
	$prevpage = qq(<a href="?page=$fpage"><<</a> <a href="?page=$ppage"><</a>);
    }
    
    if ($pager->next_page) {
	my $npage = $pager->next_page;
	my $lpage = $pager->last_page;
	$nextpage = qq(<a href="?page=$npage">></a> <a href="?page=$lpage">>></a>);
    }
    
    my %params = (
	loggedin     => $session->param('profile'),
	stardate     => $stardate,
        stardatemp3  => $stardate_mp3,
	lastupdate   => $lastupdate,
	showupdate   => $showupdate,
	feeds        => \@feeds,
	page         => $t_show_page,
        previouspage => $prevpage,
        nextpage     => $nextpage,
    );
    
    if ($ENV{'HTTP_USER_AGENT'} =~ 'Android' or $ENV{'HTTP_USER_AGENT'} =~ 'iPhone OS') {
	return $self->tt_process('index_android.tmpl', \%params);
    } else {
	return $self->tt_process('index.tmpl', \%params);
    }
}

sub category
{
    my $self = shift;
    
    my $query   = $self->query();
    my $session = $self->param('session');
    my $schema  = DB::MySQLDB->connection;
    
    my $cat = $query->param("cat");
    
    my $hitpage = qq(category::$cat);
    
    my $rc = $schema->resultset('Hits')->create({
	id         => undef,
	ip         => $ENV{REMOTE_ADDR}     || undef,
	cookie     => $ENV{HTTP_COOKIE}     || undef,
	referer    => $ENV{HTTP_REFERER}    || undef,
	hostname   => $ENV{REMOTE_HOST}     || undef,
	method     => $ENV{REQUEST_METHOD}  || undef,
	user_agent => $ENV{HTTP_USER_AGENT} || undef,
	page       => $hitpage,
    });
    
    my $stardate     = $self->_stardate();
    my $stardate_mp3 = $self->_stardate_mp3();
    
    my $lastupdate = '';
    open (CRON, "/var/www/astroslacker.com/lastcron.txt");
    while (my $record = <CRON>) {
       $lastupdate = $record;
    }
    close(CRON);
    
    # Mon Nov  1 21:00:06 2010
    my ($cweek, $cmonth, $cblank, $cday, $ctime, $cyear) = split(/\s/, $lastupdate);
    my ($nweek, $nmonth, $nblank, $nday, $ntime, $nyear) = split(/\s/, localtime(time));
    
    my ($chours, $cminutes, $cseconds) = split(/\:/, $ctime);
    my ($nhours, $nminutes, $nseconds) = split(/\:/, $ntime);
    
    my $expiredtime = ($nminutes - $cminutes);
    my $nextupdate = (60 - $expiredtime);
    
    my $showupdate = '';
    if ($nextupdate > 0) {
	if ($nextupdate == 1) {
	    $showupdate = qq(| next update in $nextupdate minute);
	} else {
	    $showupdate = qq(| next update in $nextupdate minutes);
	}
    }
    
    # articles
    my $page = $query->param("page");
    
    $page = 1 if( defined $page and $page !~ /^\d+$/ );
    
    my $put_cat = '';
    if ($cat eq 'Space_Exploration') {
	$put_cat = 'Space & Earth - Space Exploration';
    } elsif ($cat eq 'Environment') {
	$put_cat = 'Space & Earth - Environment';
    } elsif ($cat eq 'Astronomy') {
	$put_cat = 'Space & Earth - Astronomy';
    } elsif ($cat eq 'Earth_Sciences') {
	$put_cat = 'Space & Earth - Earth Sciences';
    } else {
	$put_cat = $cat;
    }
    
    my $rs = $schema->resultset('Feeds')->search(
	category => $put_cat,
	{
	    page => $page || 1,
	    rows => 15,
            prefetch => 'wav',
	    order_by => 'date DESC',
	}
    );
    
    my $pager = $rs->pager;
    
    use URI::Escape;
    
    my @feeds;
    while (my $rec = $rs->next) {
	# truncate title
	my $title = substr($rec->title, 0, 76);
	
	if ($ENV{'HTTP_USER_AGENT'} =~ 'Android' or $ENV{'HTTP_USER_AGENT'} =~ 'iPhone OS') {
	    if (length($rec->title) > 36) {
		$title .= '...';
	    }
	} else {
	    if (length($rec->title) > 76) {
		$title .= '...';
	    }
	}
	
	my @date = split(" ", $rec->date);
	my @time = split("-", $date[1]);
	
	my $encent = uri_escape($rec->category);
	
	my $link_cat = $self->_scruburl($rec->category);
	
	my $feed_ref = {};
	
	$feed_ref->{link}        = $rec->link;
	$feed_ref->{title}       = $title;
	$feed_ref->{category}    = $rec->category;
	$feed_ref->{lcat}        = $link_cat;
	$feed_ref->{date}        = $date[0];
	$feed_ref->{time}        = $time[0];
	$feed_ref->{image}       = $rec->image;
	$feed_ref->{description} = $rec->description;
	$feed_ref->{wav}         = $rec->wav->wav;
	
	push @feeds, $feed_ref;
    }
    
    my $t_page      = $pager->current_page;
    my $t_pages     = $pager->last_page;
    my $t_show_page = qq($t_page of $t_pages);
    
    my $prevpage = '<< <';
    my $nextpage = '>> >';
    
    if ($pager->previous_page) {
	my $ppage = $pager->previous_page;
	my $fpage = $pager->first_page;
	$prevpage = qq(<a href="?rm=category&cat=$cat&page=$fpage"><<</a> <a href="?rm=category&cat=$cat&page=$ppage"><</a>);
    }
    
    if ($pager->next_page) {
	my $npage = $pager->next_page;
	my $lpage = $pager->last_page;
	$nextpage = qq(<a href="?rm=category&cat=$cat&page=$npage">></a> <a href="?rm=category&cat=$cat&page=$lpage">>></a>);
    }
    
    my %params = (
	loggedin     => $session->param('profile'),
	stardate     => $stardate,
        stardatemp3  => $stardate_mp3,
	lastupdate   => $lastupdate,
	showupdate   => $showupdate,
	feeds        => \@feeds,
	page         => $t_show_page,
        previouspage => $prevpage,
        nextpage     => $nextpage,
    );
    
    if ($ENV{'HTTP_USER_AGENT'} =~ 'Android' or $ENV{'HTTP_USER_AGENT'} =~ 'iPhone OS') {
	return $self->tt_process('index_android.tmpl', \%params);
    } else {
	return $self->tt_process('index.tmpl', \%params);
    }
}


sub _scruburl {
    my $self = shift;
    
    my $link_cat = shift;
    
    my $put_cat = '';
    if ($link_cat eq 'Space & Earth - Space Exploration') {
	$put_cat = 'Space_Exploration';
    } elsif ($link_cat eq 'Space & Earth - Environment') {
	$put_cat = 'Environment';
    } elsif ($link_cat eq 'Space & Earth - Astronomy') {
	$put_cat = 'Astronomy';
    } elsif ($link_cat eq 'Space & Earth - Earth Sciences') {
	$put_cat = 'Earth_Sciences';
    } else {
	$put_cat = $link_cat;
    }
    
    return $put_cat;
}

sub _stardate {
    my $self = shift;
    # sub used to format proper date string for daily stardate mp3
    
    # use local version of module
    use lib '/var/www/astroslacker.com/cpan';
    use Time::Format qw(%time %strftime %manip);
    
#     http://stardate.org/radio/program/2010-10-09
#     http://stardate.org/sites/default/files/audio/radio/sd20101008_0.mp3
    
    return $time{'yyyy-mm-dd', time-24*60*60};
}

sub _stardate_mp3 {
    my $self = shift;
    # sub used to format proper date string for daily stardate mp3
    
    # use local version of module
    use lib '/var/www/astroslacker.com/cpan';
    use Time::Format qw(%time %strftime %manip);
    
#     http://stardate.org/radio/program/2010-10-09
#     http://stardate.org/sites/default/files/audio/radio/sd20101008_0.mp3
    
    return 'sd' .$time{'yyyymmdd', time-24*60*60}. '_0.mp3';
}


~Stephen

[ Comments (0) ]


Private SMS Perl Script
2011-09-18 13:17:38 Permalink

Tags: perl sms apache


So I needed a way to text my Android phone from home and came up with this solution. Here's an overview on the setup.

First, we need apache to have sudo powers, as we are getting email files from a users home directory. Linux by default frowns upon this behaviour so we need to modify our server to allow aphache to have sudo powers. Specically, we need to turn off tty and add apache with no password.

From the command line we issue:
Code:
visudo


Find this line:
Code:
Defaults requiretty


Now change that to show:
Code:
Defaults requiretty
Defaults:%apache !requiretty
Defaults:apache !requiretty


We also have to add the sudo powers for apache user to this file:
Code:
apache   ALL = (root) NOPASSWD: ALL


Now save and close the file by using shift+z twice. Here is the magical Perl script I wrote, with changes made to protect my server and mobile number! ;)

Perl Code:
#!/usr/bin/perl -w
use strict;


use Email::MIME;
use Email::MIME::Creator;
use Email::Send;
use Data::Dumper;

use CGI qw/:standard/;

my $q = CGI->new;

my $rm = $q->param('rm') || 'default';

print "Content-type: text/html\n\n";

print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>SMS Server</title>';

if ($rm eq 'send_sms') {
    print qq(<meta HTTP-EQUIV="REFRESH" content="5; url=http://domain.name/sms-server.pl">);
} else {
    print qq(<meta HTTP-EQUIV="REFRESH" content="60; url=http://domain.nameg/sms-server.pl">);
}

print '</head>
<body>';

print "<fieldset style=\"font-size:10px; width:600px;\">\n";

if ($rm eq 'send_sms') {
    
    my $sms_body = $q->param('sms_body') || '...';
    
    my $mobile_email_to = '5555555555@vmobl.com';
    
    # Compose E-Mail To Me...
    my @mobile_headers = (
	From    => 'me@domain.name',
	Subject => '',
	To      => $mobile_email_to,
    );
    my $mobile_mailer = Email::Send->new({
	mailer => 'SMTP',
	mailer_args => [ Host => 'localhost' ],
    });
    my $mobule_result = $mobile_mailer->send(
	Email::MIME->create(
	    header => \@mobile_headers,
	    parts => [
		Email::MIME->create(
		    body => $sms_body,
		),
	    ],
	)
    );
    
    my $send_file = time . '.Vca00I3e38cM' .time. '.domain.name';
    
    open FILE, ">", "/var/www/domain.name/sms-messages/new/$send_file";
    print FILE "From: SERVER\n\n" .$sms_body;
    close FILE;
    
    print qq(<span style="font-size: 12px;">Message sent. Refreshing in 5 seconds...</span>);
    
} else {
    
    my $cmd1 = "sudo cp -rf /home/username/Maildir/new /var/www/domain.name/sms-messages/";
    `$cmd1`;
    
    my $cmd2 = "sudo chown -R apache:apache /var/www/domain.name/sms-messages";
    `$cmd2`;
    
    opendir(SMS, "/var/www/domain.name/sms-messages/new") || die("Cannot open directory - " .$!);
    my @emails = readdir(SMS);
    closedir(SMS);
    
    @emails = sort {$b cmp $a} @emails;
    
    open FILE, ">", "/var/www/domain.name/sms-messages/sms.txt";
    
    my $allcnt = 0;
    foreach my $f (@emails) {
	unless ($f eq '.' or $f eq '..') {
	    my $from_me = '';
	    
	    open (SMS, "/var/www/domain.name/sms-messages/new/$f");
	    while (my $record = <SMS>) {
		if ($record =~ 'From' and $record =~ '5555555555@yrmobl.com') {
		    $from_me = 'MOBILE';
		} elsif ($record =~ 'From' and $record =~ 'SERVER') {
		    $from_me = 'SERVER';
		}
	    }
	    close(SMS);
	    
	    if ($from_me eq 'MOBILE' or $from_me eq 'SERVER') {
		$allcnt++;
		my $cnt   = 0;
		open (SMS, "/var/www/domain.name/sms-messages/new/$f");
		while (my $record = <SMS>) {
		    $cnt++;
		}
		close(SMS);
		
		my $cnt2 = 0;
		open (SMS, "/var/www/domain.name/sms-messages/new/$f");
		while (my $record = <SMS>) {
		    $cnt2++;
		    if ($cnt2 == $cnt) {
			
			my @time = split(/\./, $f);
			my $localtime = $time[0];
			
			chomp($from_me);
			chomp($localtime);
			
			chomp($record);
			print FILE "$from_me||$localtime||$record\n";
		    }
		}
		close(SMS);
		
	    } else {
		next;
	    }
	}
    }
    
    close FILE;
    
    print qq(<legend>Text Messages: $allcnt</legend>\n);
    print qq(<div style="height: 500px; overflow:scroll;"><ul>\n);
    
    open (SMS, "/var/www/domain.name/sms-messages/sms.txt");
    while (my $record = <SMS>) {
	my @line = split(/\|\|/, $record);
	
	my $from    = $line[0];
	my $message = $line[2];
	
	my @time = split(/ /, localtime($line[1]));
	
	my $hour = $time[3];
	
	print "<li>\n";
	print qq(<span style="font-size: 14px;">$from [$hour] - $message</span>);
	print "</li>\n";
    }
    close(SMS);
    
    print "</ul></div>\n";
    
    print qq(<p><form action="/sms-server.pl" method="GET">);
    print qq(<input type="hidden" name="rm" value="send_sms">);
    print qq(<hr>Enter message: <input type="text" size="50" name="sms_body">);
    print qq(<input type="submit" value="Send Message">);
    print qq(</form></p>);
    
}

print "</fieldset>";

print '</body>
</html>';


That's it, a perfect SMS solution for private home computer to mobile phone communication.

~Stephen

[ Comments (0) ]


Linux Mobile Media Converter
2010-04-04 17:08:49 Permalink

Tags: linux mobile media converter


Need to convert your mobile phone 3gp video files under Linux OS? Well, here's the perfect tool for the job - Mobile Media Converter

You can download the Linux binary directly, or follow the steps below from your command line.

Code:
wget http://www.miksoft.net/products/mmc-lin.tar.gz


Code:
tar -zxvf mmc-lin.tar.gz


Code:
cd MobileMediaConverter/


Code:
./MobileMediaConverter


Once the GUI is up and running select the in file, out file format, quality and then click convert!

~Stephen

[ Comments (0) ]


Mono 2.6 + MonoDevelop 2.2 on openSUSE 11.2
2009-12-16 11:00:21 Permalink

Tags: opensuse mono asp .net


Mono 2.6 has been released this morning. This is great news for those of us interested in developing .NET web framework on dedicated Linux workstations, such as the most excellent OpenSuse 11.2.

Installation is simple using zypper from the command line, as follows.

Code:
zypper ar -f -n Mono http://download.opensuse.org/repositories/Mono/openSUSE_11.2 repo-mono

Code:
zypper mr -p 10 repo-mono

Code:
zypper refresh

Code:
zypper dup -r repo-mono




To run asp.NET applications on your Linux box, you will need to install mod_mono for Apache2.

On OpenSuse you can run:

Code:
zypper install apache2-mod_mono


[ Comments (0) ]


Forcing Git To Ignore File Mode Changes
2009-11-22 18:54:22 Permalink

Tags: git


Quick note on Git file mode changes...

In situations which require you to change the file mode on your local git repository (example: if you mount a local machine and need to set mode to 777 for user to be able to write file modifications), Git will recognize all files as modified (git status) after mode changes. Here's how we can force Git to ignore mode changes.

Code:
git config core.filemode false


Simple!

`Stephen

[ Comments (0) ]


Jquery Ajax Forms For Catalyst Apps
2009-10-11 16:28:02 Permalink

Tags: catalyst jquery ajax


I've been working on a private, personal project for a few weeks now and would like to share some simple steps for slick, "in-place" form submissions via Jquery. For an example, you can click on either the "Resume" or "Code Samples" links to the left. Both screens require the user to enter a valid email address in order to view the main content.

The form used for this task will validate input data, submit validated data to a catalyst controller, and then either, depending on the response from the controller, display the main content or show an error. All this is done "dynamically" from the same screen. The main effect of this setup is very much like a native desktop client application, rather than the classic web based application work flow.

In my private (unreleased) application I am taking this process much farther, resulting in an extremely powerful and efficient web base application than runs similar to many desktop applications.

First we set up the jQuery script:

Code:
<script type="text/javascript">

$(document).ready(function(){
  $('#emailLoading').hide();
  $('#saving_settings').hide("fast");
  $('#email_valid').hide("fast");
  
  $('#email').blur(function(){
    $('#emailLoading').show();
    if( !$('#email').val() ) {
      $('#emailResult').html('
<span style="color:#f00;font-weight: bold;font-size:12px;">Required field</span>');
      $('#emailLoading').hide();
    } else {
      $.post("[% Catalyst.uri_for('/formvalidation/email_session') %]", {
	  email: $('#email').val()
      }, function(response){
	if( response == 'FAIL' ) {
	  $('#emailResult').html('
<span style="color:#f00;font-weight: bold;font-size:12px;">E-mail not valid</span>');
	  $('#emailLoading').hide();
	} else {
	  $('#emailResult').html('<img src="[% Catalyst.uri_for('/static/images/accepted.png') %]">
<span style="color:#0c0;font-weight: normal;font-size:10px;">E-mail valid</span>');
	  $('#emailLoading').hide();
	}
      });
    }
  });
  
  $("#email_session").bind('submit', function(event){
    $('#email_form').hide("fast");
    $("#saving_settings").show('fast');
    $.post("[% Catalyst.uri_for('/formvalidation/email_session') %]", {
	email: $('#email').val(),
	store: 1
    }, function(response){
      if( response == 'FAIL' ) {
	$('#email_form').show("fast");
        $("#saving_settings").hide('fast');
	$('#emailResult').html('
<span style="color:#f00;font-weight: bold;font-size:12px;">E-mail not valid</span>');
	$('#emailLoading').hide();
      } else {
	$('#email_valid').show("fast");
        $("#saving_settings").hide('fast');
      }
    });
    return false;
  });
  
});

</script>


Next we setup the form:

Code:
<fieldset>
  <legend>jQuery Catalyst Forms</legend>
  
[% IF Catalyst.session.email.valid %]
  
  <!-- User has access, show protected screen -->
  Main content...
  
[% ELSE %]
  
  <div id="email_form" style="height: 500px;">
    <form id="email_session">
  <table border=0>
    <tr>
      <td colspan=3>Please enter e-mail address to continue:</td>
    </tr>
    <tr>
      <td colspan=3> </td>
    </tr>
    <tr>
      <td><input type="text" name="email" id="email">
          <span id="emailLoading"><img src="[% Catalyst.uri_for('/static/images/loader.gif') %]" alt="..." /></span>
      <span id="emailResult"></span></td>
      <td style="text-align: left;vertical-align: top;"><button id="x_submit">Submit</button></td>
      <td>  </td>
    </tr>
  </table>
    </form>
  </div>
  <div id="saving_settings">Saving Settings <img src=[% Catalyst.uri_for('/static/images/ajax-loader.gif') %]></div>
  
[% END %]
  
  <div id="email_valid">
    <!-- User has access, show protected screen -->
    Main content...
  </div>

</fieldset>


Next we setup a new Catalyst controller, mine is called FormValidation.pm, and add the following code:

Perl Code:
package stephensykes::Controller::FormValidation;

use strict;
use warnings;

use parent 'Catalyst::Controller';

=head1 NAME

stephensykes::Controller::FormValidation - FormValidation Controller

=head1 DESCRIPTION

Used to validate forms via jQuery.

=head1 METHODS

$.post("[% Catalyst.uri_for('/formvalidation/email_session') %]", {
    email: $('#email').val()
}

=cut

=head2 index

=cut

sub email_session : Local {
    my ( $self, $c ) = @_;
    
    my $email = $c->req->param('email');
    my $store = $c->req->param('store');
    
    my $response;
    
    use Email::Valid;
    
    my $email_valid = Email::Valid->address( -address => $email, -mxcheck => 1 );
    
    if( !$email_valid )
    {
        $response = 'FAIL';
    }
    else
    {
        if( $store )
        {
            $c->session->{email}->{valid} = 1;
            
            $c->model('StephenSykesDB::EmailSessions')->create({
                session_id => undef,
                email      => $email_valid,
            });
        }
        
        $response = 'OK';
    }
    
    $c->res->content_type('application/text');
    $c->res->body($response);
}

=head1 AUTHOR

Stephen Sykes

=head1 LICENSE

This library is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

1;


It's that simple.

[ Comments (0) ]


Remote Git Repository Setup
2009-08-23 20:14:59 Permalink

Tags: git linux


I've been doing a lot of work moving from SVN to Git for source code version control. The following is a quick and easy how-to for setting up a remote git repository. This example shows how to import an existing SVN repo into a new git repo.

1) [Local machine] Export clean code base from remote SVN repository:

Code:
cd /var/git/
svn export http://svn.domain.com/trunk myapp.git
cd myapp.git
git init
git add .
git commit -m "initial import"


2) [Remote server]: Make remote git repository:

Code:
ssh user@ipaddress
mkdir /var/git/myapp.git && cd /var/git/myapp.git
git --bare init


3) [Local machine] Add/push local repo to remote repo:

Code:
git remote add origin user@ipaddress:/var/git/myapp.git
git push origin master


4) Give out git repo info to developers:

Code:
git clone user@ipaddress:/var/git/myapp.git


That's all that's required for source code versioning via Git. Each developer can now clone from the master branch of the remote server (see step 4) and go to work! More on how to commit revisions soon.

~Stephen

[ Comments (0) ]