Perl Tutorial



Perl Tutorial



(C) S Projects. Any distribution of any parts of this site is strictly prohibited, unless explicitly stated in text.

All contents of this site is provided strictly on the AS IS basis. The author should not be held responsible for any negative effects that may result from reading or applying the information or using software provided here. The author does not make any medical, financial or other claims - all statements are author's opinions ONLY. Use your own judgment.

|Link to us and make 20% commissions through our affiliate program |

Introduction

What is this book?

This is a "practical guide" to Perl. In part 1 I am going to provide some Perl basics and then - in part 2 - we will use them to create few practical applications, such as web counters.

The book will help you to get hands-on experience, as well as some working code that you can use on your own sites and for your own projects.

When you read different online Perl (not only Perl) tutorials, you might notice, that they are incomplete - one tutorial is missing something, while the other tutorial has this "something" - and missing something else.

It is inevitable, and I am not going to tell you that this tutorial is complete because it is not. However in this book I pulled together the bits and pieces that I consider most important, so that - being incomplete - it is nevertheless SUFFICIENT for 99 (OK, 95) percent of the tasks the average Perl programmer is solving daily.

What is Perl?

I cannot think of the language that would allow you to create web site "engine" faster, then Perl. You can, literally, create a CGI empowered site in a day. Match making site? A day or two. Counter for the Web site, that has all features YOU need? Two days. Email autoresponder? Few days. I am going to use some of these examples later in this book.

Perl was created as the simple alternative to low-level languages, such ac C++, and it is important to keep in mind its limitations. Perl is NOT a computational language (one day it may become fast enough, and this statement will not be true anymore). But - unlike C++ or other general-purpose languages - it was created with certain tasks in mind.

I prefer to think of Perl as the slow language with powerful and very Well-designed libraries. When you perform tasks that Perl was intended for, it is a great tool. When you do something else, it is not that great anymore.

Comments in Perl program

You can comment lines in Perl program, which means that the Perl interpreter will ignore commented information. To comment a line, use the pound sign, all information from the "#" till the end of the line will become commented:

# This line is commented

Variables

Scalars

Perl stores single values in so-called scalar variables. For example, if we want to introduce a variable "income" and to set a value for it, for example 10,000, we write: $income = 10000;

The $ sign is used to distinguish between scalar variable and other Perl constructions. The "=" sign is used for assignment. Finally, the semicolon is used to close the statement, you can use multiple statements in Perl program, on the same line or on different lines, separated with semicolons:

$income = 10000; $ x = 2;

$double_income = $x * $income;

Perl stores all values in the same internal format, and then - depending on what is stored in the variable and what is the context, it can interpret it as a string or number:

$x = 3;

$y = "Hi"; # always a string

$str = "$y$x"; # $str equals Hi3, x treated as string

$z = 2 * $x; # x treated as number

More about Strings

General information

Strings are very important in Perl, and we will find many advancements in the syntax used for handling strings.

Strings can be included in single or double quotes. In single quotes, the string in presented AS IS, no values substituted for the variables and no special characters inserted instead of the sequences like \n or \t.

When double quotes are used, Perl tries to perform all possible substitutions:

$str = '$x\n'; # $str equals $x plus \ plus n

$str = "$x\n"; # $str equals 3 plus a single "new line" symbol

To insert quotes inside the string, we have to precede them with backslash:

$str = "Hello, \"user\"";

Alternative quotation

Sometimes it is inconvenient, for example if the string contains many quoted sub strings. In this case we can use q and qq operators, to specify a separator, different from the quote:

$str = q[Hello, "user"];

$str = q{Hello, "user"};

Long strings

If the string is long, we can use a special format, specifying that the string is considered to be "everything from here and till this separator:

$str = ";

print ("$str_image");

}

}

else

{

print ("$count");

}

} # if not hidden

Finally, the lock() subroutine:

sub lock

{

my($file) = @_;

# exclusive lock

flock($file, 2);

# Make sure we are at the beginning seek($file, 0, 0);

}

Cron job

Cron job is a Unix task that is performed regularly by the timer. If we want to receive counter statistics by email, weekly, then we have to create a program that will do mailing and to set it one of our cron jobs. I am not going to explain details on setting up a cron job here, as it is very simple and there are many tutorials in the Internet.

Let's take a look at the code, instead. We presume, that the program is located in the cron_job directory on our server. It is better, of course, to make it not accessible from the Internet.

Standard Perl header:

#!/usr/bin/perl

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

Specify the path to the directory, no trailing slash "/", to the file containing your email, and to the mail program:

$dir = "/home/snowseed/counter_data";

$email_file = "$dir/counter_mail.txt";

$mailprog = '/usr/sbin/sendmail';

Next, we need to read the statistics file, to open a pipe (a data feeding connection) to the Unix mailer, called sendmail, and to print data to this pipe. The moment we close the pipe, the sendmail will send a message to our mailbox.

if(open(MAIL_F, $email_file))

{

$email = ;

close(MAIL_F);

chomp($email);

$subject = "Counter report for my counters";

$body = "";

$counter_file = "$dir/counter.txt";

if(open(COUNTER_F, $counter_file))

{

@counters = ;

close(COUNTER_F);

for($i = 0; $i text. The program will read the text, insert a new link (received from the form) after the "link section" tag, thank the user and exit.

The HTML form itself looks like this (you may want to take a look at the source code as well). Note, that more than one sub domain can be specified, and therefore, you can manage more than one links.htm files, like for NLP - related links, for stock trading related links and so on.

Perl code

Standard Perl header:

#!/usr/bin/perl

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

Path information

$site_path = "";

$data_path = "/home/mydomain";

As we receive data from the form, we need to load it into a hash called FORM for further use. Note that some minimum security is also implemented.

read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});

@pairs = split(/&/, $buffer);

foreach $pair (@pairs)

{

($name, $value) = split(/=/, $pair);

$value =~ tr/+/ /;

$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

$FORM{$name} = $value;

}

Remove suspicious characters.

$link = &verify_url($FORM{'link'});

if($link ne $FORM{'link'}) # something was removed during verification

{

&wrong_url($link);

exit;

}

$backlink = &verify_url($FORM{'backlink'});

if($backlink ne $FORM{'backlink'}) # something was removed during verification

{

&wrong_url($backlink);

exit;

}

$label = &verify_text($FORM{'label'});

if($label ne $FORM{'label'}) # something was removed during verification

{

&wrong_text("text");

exit;

}

$legend = &verify_text($FORM{'legend'});

if($legend ne $FORM{'legend'}) # something was removed during verification

{

&wrong_text("additional text");

exit;

}

Now we need to read the file (one of the links.htm files) from a particular sub domain (specified by "category", and write it back, together with the new link that the visitor provided:

$category = $FORM{'category'};

$links_file_name = "$data_path/$category.$site_path/links.htm";

if(open(LINKS_F, "+ \n

Link added successfully\n

< p> Use your browser's BACK button to return\n

< /body> \n< /html> \n";

}

else

{

&no_url($links_file_name);

exit;

}

Finally, subroutines to lock files, verify data and so on. Notice, that the verification subroutines are simply removing all "dangerous" characters from the input.

sub lock

{

my($file) = @_;

# This locks the file so no other CGI can write to it at the same time...

flock($file, 2);

# Reset the file pointer to the end of the file, in case

# someone wrote to it while we waited for the lock...

seek($file, 0, 2);

}

####### verify_url($url)

sub verify_url

{

my($url) = @_;

$url =~ s/[\\"\'\%\;\)\(\s\&\+]//g;

return $url;

}

####### verify_text($text)

sub verify_text

{

my($text) = @_;

$text =~ s/[\\"\'\%\;\)\(\&\+]//g;

return $text;

}

########## Quit if wrong url

sub wrong_url

{

my($url) = @_;

print "< head> \n< /head> \n< body> \n

Unrecognized characters in URL: $url\n

< p> Please try again.\n

< p> < a href=\"$site_path/link_ex.htm\"> Link Exchange Page< /a> \n

< /body> \n";

}

########## Quit if wrong text

sub wrong_text

{

my($text) = @_;

print "< head> \n< /head> \n< body> \n

Unrecognized characters in $text\n

< p> Please try again.\n

< p> < a href=\"$site_path/link_ex.htm\"> Link Exchange Page< /a> \n

< /body> \n";

}

########## Quit if file not found

sub no_url

{

my($url) = @_;

print "< head> \n< /head> \n< body> \n

Cannot find URL: $url\n

< p> Please try again.\n

< p> < a href=\"$site_path/link_ex.htm\"> Link Exchange Page< /a> \n

< /body> \n";

}

About adding a reciprocal link

In the real life you would probably want to place someone else's link on your page only if they link to you first. To do so you need to modify the code above, so that it loads this "someone else’s" links page and looks for the link to your site. Perl has modules to read files using HTML protocol, so this task is not that difficult. However as this tutorial does not cover Perl modules, it is not dealing with reciprocal links either.

Uploading files

No mater if you are working with resume processing center, or designing a dating web site, at some point you might want to allow the visitor to upload files to your site. Using Perl together with HTML forms allows you to do it.

Design issues

First of all, we need a form of particular type, one that allows to send data as binary. To do it, use something like:

< form action="" method="POST" ENCTYPE="multipart/form-data" >

where the ENCTYPE="multipart/form-data" does the trick.

Let's say we need to upload an image. In the form, among other fields, include the following:

Photo 1 (there can be photo 2 and so on): < input type="file" name="photo_1" value="" size=50>

The input type = "file" will create a text field together with the file lookup button.

Let's take a look at the Perl code that works with this form.

Perl code

Standard Perl header:

#!/usr/bin/perl

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

We are going to use Perl module called CGI - it makes easier working with the forms. We also need to make sure that the visitor does not upload a 10-megabyte file, so we set the limit to 30 K and we also set a CGI::POST_MAX variable (the CGI:: simply means that we look in CGI module for this variable) to this limit.

Let's also provide some useful path information:

use CGI;

$MAX_SIZE_UPLOAD = 30; # Max size of image, Kb

$CGI::POST_MAX = 1024 * $MAX_SIZE_UPLOAD;

$site_path = "";

$data_path = "/home/mydomain/data";

$data_site_path = "/home/mydomain/subdomain.";

$site_url = "";

$FORM_ADD_URL = '';

# upload only these extensions

$extensions = "(\.gif|\.jpg|\.png)";

Now we need to create an object of type CGI, called query. By doing so we gain access to the functions of this object. The syntax for this access changes, compared to what you already know, it will be query->function() instead of simply function(). Other than that, their is no difference:

my $query = new CGI;

"Action" is specified in the form, on HTML file, it is associated with the submit button.

First of all, we do not want our CGI to process data from the wrong form. Second, sometimes it is convenient to process more than one form in the same CGI (for example, add image and delete image). We need a way to distinguish.

In our form, the submit button looks like this:

< input type="submit" Name="action" value="add">

The value equals "add".

$action = $query->param('action');

if($action eq "add") # only image upload code provided

{

### Uploading image with the name stored in $photo_1

if(($photo_1_ex = &verify_file_name($query->param('photo_1'))) ne "")

{

&upload($query, 'photo_1', "$data_site_path/photos/$photo_1");

}

#### End of image upload

} # end of if("add")

What happens here? First, we make sure that file name has proper extension. Then we call an upload() subroutine:

sub verify_file_name

{

my($src_file_name) = @_;

$subs = substr($src_file_name, length($str_file) - 4);

if(($src_file_name =~ /[\\"\'\%\;\)\(\s\&\+]/) || ($subs !~ /$extentions/))

{

return "";

}

else

{

return $subs;

}

}

###

sub upload

{

my($query, $src_file_name, $dst_file_name) = @_;

$size = $bytes = 0;

$_ = $file_query = $query->param($src_file_name);

s/\w://;

s/([^\/\\]+)$//;

$_ = $1;

s/\.\.+//g;

s/\s+//g;

$file_name = $_;

if (! $file_name)

{

&error("Bad file name : $file_name", 1);

}

open(FILE, ">$dst_file_name") ||

&Error("Error opening file $dst_file_name, error $!", 1);

binmode FILE;

while($bytes = read($file_query, $buff, 2096))

{

$size += $bytes;

print FILE $buff;

}

close(FILE);

if ((stat $dst_file_name)[7] ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download