Thursday, June 21, 2012

A Simple Perl-Based RSS to Email Program


While many sites offer RSS feeds as a means of keeping up to date with new content, not everyone is as familiar with RSS and RSS feed readers as they are with Email and Email clients.  To deal with this issue, here is a small Perl code snippet which will download an RSS feed, parse out the title and the description associated with each RSS entry, and email out the extracted information.  In the interest of simplicity for the sample code, it extracts the item titles and description from every element in the feed, but with a little modification it could be adapted to only utilize the most recent feed entries.  Running the script periodically to check for new RSS entries could be easily handled via cron jobs or other job scheduler. 

The Email sending portion of the code was tested using Gmail.  

 #!usr/bin/perl

use Email::Sender::Simple qw(sendmail);
use Email::Sender::Transport::SMTP::TLS;
use Email::Simple;
use Email::Simple::Creator;
use XML::RSS::Parser;
use LWP;
use strict;
use warnings;

my $feedurl='http://feeds.feedburner.com/SansInstituteNewsbites?format=xml';

my $ua=LWP::UserAgent->new;
my $response=$ua->get($feedurl);
my $rss=$response->content;

my $parser= new XML::RSS::Parser;
my $feed=$parser->parse_string($rss);
my $feed_title = $feed->query('/channel/title');
my $message =  $feed_title->text_content;
my $count = $feed->item_count;
$message.=" ($count)\n";
foreach my $i ( $feed->query('//item') ) {
  my $node = $i->query('title');
  $message.= '  '.$node->text_content . "\n";
  $node = $i->query('description');
  $message.='  '.$node->text_content;
  $message.= "\n\n";
}
#strips out feed specific html tags because I chose to send plain text email
$message=~s/((<p>)|(<\/p>))//gio;

my $transport = Email::Sender::Transport::SMTP::TLS->new(
   host => 'smtp.gmail.com',
   port => 587,
   username => 'somebody@gmail.com',
   password => 'password'
);

my $email = Email::Simple->create(
    header => [
      To      => '"Somebody" <somebody@gmail.com>',
      From    => '"Somebody Else" <s_else@gmail.com>',
      Subject => "The Latest Updates",
    ],
    body => "$message",
);
sendmail($email, {transport => $transport});

Tuesday, June 19, 2012

Companies That Use Perl

I recently saw this site mentioned in one of the LinkedIn Perl forums and thought it provides an interesting way to promote Perl.  It is a listing of many of the companies in the Los Angeles area that make use of Perl for major product development- http://perl.la/ One thing that I think is also interesting about this site is the way they present the list of companies.  While I can think of many reasons a “text-like” list of hyperlinks (used by other such lists) can be advantageous, the graphical way perl.la displays its data is probably an interface with more marketing appeal. 

The list contains a number of companies that should be widely recognizable to those that are not already involved in the Perl community or even a computer related occupation – companies like CBS television, DreamWorks, Ticketmaster, and Experian. 

Seeing this site also made me think of some other lists of companies that use Perl such as these from the Perl 5 Wiki and other sources:


A list of applications written in Perl - https://www.socialtext.net/perl5/applications

A list of companies that use Catalyst - http://wiki.catalystframework.org/wiki/sitesrunningcatalyst

A list of companies that use Moose - http://moose.iinteractive.com/about.html


Perl is clearly still thriving!!!

Tuesday, June 12, 2012

A Perl PDL Demonstration Using the Hill Cipher Algorithm


PDL is an excellent Perl module for anyone seeking to do any type of numerical computing that involves matrix math.  As an illustration of this, let’s take a look at a PDL implementation of a simple encryption algorithm that uses matrix math, the Hill Cipher.  As a starting point, the Hill Cipher assigns each letter in the alphabet a numerical value (e.g. a=0, b=1, c=2, … z=25).  The cipher works by taking n plain text letters and converting them to their numeric representation.  In the example code a n of 3 is used. We will refer to this set of numerically represented plain text letters as P. It then takes an nXn matrix, which is used as an encryption key (K), and performs the following matrix math operation to yield the numerical representation of n cipher text letters (C).  

C=P x K mod 26

If you look at the Perl code below, notice how easy PDL makes this operation.  There is no need to loop through the elements of an array and perform mathematical operations on each element.   One can simply process entire matrices as a single entity and as such this is one of the features that makes PDL such a huge asset to anyone that performs numerical computing in Perl. 

The reverse of this process is performed by taking the inverse matrix (K1) and performing the following math operation:

P=C x K1 mod 26

As a means of testing the example code, a known set of values from the book “Cryptography and Network Security” by William Stallings are used.  If run as is, the sample code should result in the cipher text RRLMWBKASPDH after encryption and the decryption should return the original plain text value.  

#usr/bin/perl

use PDL;
use strict;
use warnings;

my @letters = ('a'..'z');
my (%encoding,%encoding2);
my $i=0;
foreach my $letter (@letters){
    $encoding{$letter}=$i;
    $encoding2{$i}=$letter;
    $i++;
}

#encryption
my $plaintext='paymoremoney'; #length=multiple of 3
$plaintext=lc($plaintext);
my $ciphertext='';

#encryption key
my $k = pdl [[17,17,5],[21,18,21],[2,2,19]];

while($plaintext=~/(\w)(\w)(\w)/g){
    my $x=$encoding{$1};
    my $y=$encoding{$2};
    my $z=$encoding{$3};
    my $p= pdl [$x,$y,$z];
    my $c= $p x $k % 26;
    foreach (0 .. $c->nelem-1){
        my $j=$c->flat->index($_);
        $ciphertext.=$encoding2{$j};
    }
}
print uc($ciphertext)."\n\n";

#decryption
$plaintext='';
#inverse matrix
#hardcoded and not computed to simplify example code
my $k1= pdl [[4,9,15],[15,17,6],[24,0,17]];
while($ciphertext=~/(\w)(\w)(\w)/g){
    my $x=$encoding{$1};
    my $y=$encoding{$2};
    my $z=$encoding{$3};
    my $c= pdl [$x,$y,$z];
    my $p= $c x $k1 % 26;
    foreach (0 .. $p->nelem-1){
        my $j=$p->flat->index($_);
        $plaintext.=$encoding2{$j};
    }
}
print $plaintext;

Friday, June 8, 2012

Retrieve Windows System Information with Perl


For anyone that has to troubleshoot Windows systems, being able to quickly and easily identify information about the computer such as OS info, drive information, network settings, and so on, can be a real time saver.  This Perl script makes use of several Win32 modules to determine information about the installed operating system, the computer name, processor information, RAM information, drive information, and computer network settings.  When running the script, you may want to take advantage of redirection to save the output to a file since it can be a bit on the lengthy side if the computer has multiple processors, multiple network adapters, etc.  To take advantage of redirection run the script as follows:

perl WinInfo.pl > output.txt

This will save the output of the script to a file called output.txt. 

use Win32;
use Win32::SystemInfo;
use Win32::DriveInfo;
use Win32::IPConfig;
use strict;
use warnings;

print "OS Information\n";
my $computer=Win32::NodeName();
print "The computer name is $computer\n";

my $domain=Win32::DomainName();
print "The computer is a member of the $domain domain/workgroup\n";

my $OS=Win32::GetOSDisplayName();
print "The OS is $OS\n";

my $fs=Win32::FsType();
print "The filesytem is $fs\n";

my $user=Win32::LoginName();
print "The current user is $user\n";

my $admin=Win32::IsAdminUser();
if($admin!=0){
    print "$user is running this script as admin\n\n\n";
}
else{
    print "$user is not running this script as admin\n\n\n";
}

print "Processor and RAM Information\n";
my %processor;
Win32::SystemInfo::ProcessorInfo(%processor);
for (my $i=0;$i<$processor{NumProcessors};$i++) {
    print "Processor$i\n";
    print "Processor Name: " . $processor{"Processor$i"}{ProcessorName} . "\n";
    print "Processor Info: " . $processor{"Processor$i"}{Identifier} . "\n";
    print "Processor Speed: " . $processor{"Processor$i"}{MHZ} . "MHz\n\n";
}

my %memory;
Win32::SystemInfo::MemoryStatus(%memory, 'GB');
print "The computer has $memory{TotalPhys} GB of RAM\n\n\n";

my %dtypes=(0 => "Undertmined",
1 => "Does Not Exist",
2 => "Removable",
3 => "Hardrive",
4 => "Network",
5 => "CDROM",
6 => "RAM Disk");

print "Drive Information\n";
my @drives = Win32::DriveInfo::DrivesInUse();
foreach my $drive (@drives){
    my $type=Win32::DriveInfo::DriveType($drive);
    print "Drive $drive is a $dtypes{$type}\n";
  
}

print "\n\nNetwork Information";
my $ipconfig = Win32::IPConfig->new($computer)
        or die "Unable to connect to $computer\n";
foreach my $adapter ($ipconfig->get_adapters) {
    print "\nAdapter '", $adapter->get_name, "':\n";

    print "Description=", $adapter->get_description, "\n";

    print "DHCP enabled=",
    $adapter->is_dhcp_enabled ? "Yes" : "No", "\n";

    my @ipaddresses = $adapter->get_ipaddresses;
    print "IP addresses=@ipaddresses (", scalar @ipaddresses, ")\n";

    my @subnet_masks = $adapter->get_subnet_masks;
    print "subnet masks=@subnet_masks (", scalar @subnet_masks, ")\n";

    my @gateways = $adapter->get_gateways;
    print "gateways=@gateways (", scalar @gateways, ")\n";

    print "domain=", $adapter->get_domain, "\n";

    my @dns = $adapter->get_dns;
    print "dns=@dns (", scalar @dns, ")\n";

    my @wins = $adapter->get_wins;
    print "wins=@wins (", scalar @wins, ")\n";
}

Kobo has over 2 million ebooks to choose from!

Wednesday, June 6, 2012

Using Data::Validate Modules to Validate Application Data


In an earlier approach I provided A Brief Introduction to Input Validation where the basic concepts of whitelisting and blacklisting were introduced to readers.  While every programmer should be familiar with the idea of writing input validation filters it can often be challenging to develop a filter that minimizes both the numbers of false positives as well as the number of false negatives, and thus it often pays to use well tested routines for input validation where feasible.   CPAN contains many such routines that can usually be located by searching CPAN for terms like Valid, Validate, Validator, and Validation.  One CPAN namespace in particular that has many useful routines is the Data::Validate namespace, which contains routines for validating numbers, IP addresses, email addresses, URLs and more.  In the code snippet below we will take a look at the Data::Validate::IP (http://search.cpan.org/~neely/Data-Validate-IP-0.14/lib/Data/Validate/IP.pm) and the Data::Validate::Email (http://search.cpan.org/~sonnen/Data-Validate-Email-0.04/Email.pm) Perl modules.  

 #!usr/bin/perl

use strict;
use warnings;

use Data::Validate::IP qw(is_ipv4);

my @IPs=('192.168.1.5','127.0.0.1','116.12.54.257','abc.123.123.123');
foreach my $IP (@IPs){
    if(is_ipv4($IP)){
        print "$IP is a valid ipv4 address\n";
    }
    else{
        print "$IP is invalid\n";
    }
}

use Data::Validate::Email qw(is_email);
my @Emails=('someone@example.com','someone&example.net','someone@example.123','someone@example.info');
foreach my $Email (@Emails){
    if(is_email($Email)){
        print "$Email is a valid Email address\n";
    }
    else{
        print "$Email is invalid\n";
    }
}

 
Once you select a validation method for your application it is also imperative that you take the time to test your validation routine to make sure that valid inputs are properly passed on to the application and that any invalid inputs are flagged as such.  Such testing should involve both use cases as well as “abuse” cases designed to try to bypass the filter.  The need for testing is especially true if you decide to implement your own validation routine as it is not always easy to think off all the possible ways somewhat could attempt to format an input string.  Remember that input validation is typically an application’s front line defense in that it exists to minimize the risk of improper or malicious data from ever being processed by the application.