Programming in Perl

Programming Republic of Perl

This page just lists some non-CGI.pm scripts for web development, written in Perl 5:

Micro CMS

A very simple file-based Content Management System (CMS) that can be used without CGI.pm. CGI::Carp is optional and only used to print warnings and errors to the browser. There is also a PHP script with the same functionality.

The template is parsed and the string [% content %] will be replaced with the contents of the accessed page. Open http://www.example.com/index.pl?page=main to show page main.html.

Just follow this file structure and copy the source code to index.pl:

Source Code

#!/usr/bin/perl
# Micro CMS in Perl 5
# Licence: Public Domain

package micro;

our $content_dir   = "./content/";                  # Directory with HTML files.
our $file_ext      = ".html";                       # File ending.
our $page_404      = "404";                         # Name of 404 page.
our $page_default  = "index";                       # Name of default page.
our $template_file = "./template/template.html";    # Path to template file.
our %param_of;                                      # Parameters in template file.

use strict;
use warnings;

use CGI::Carp qw(fatalsToBrowser warningsToBrowser); warningsToBrowser(0);
use encoding qw(utf8);
use utf8;

&read_params();
print &get_html();

sub get_html {
    my ($content, $html, $page, $param);

    $param = &get_param("p");
    $page  = ($param ne qq{}) ? $param : $page_default;
    $page  =~ s/[^\w]//xms;

    $html = qq{Content-Type: text/html; charset=utf-8\n\n};

    if (-e $content_dir . $page . $file_ext) {
        $content .= &open_file($content_dir . $page . $file_ext);
    } else {
        $content .= &open_file($content_dir . $page_404 . $file_ext);
    }

    my %value_of = (
        content => $content,
    );

    my $template = &open_file($template_file);

    &parse_template(
        template_ref => \$template,
        value_of_ref => \%value_of,
    );

    $html .= $template;

    return $html;
}

sub get_param {
    my $key = shift;

    return $param_of{$key};
}

sub read_params {
    my $query;

    if ($ENV{'REQUEST_METHOD'} eq 'GET') {
        $query = $ENV{'QUERY_STRING'};
    } elsif ($ENV{'REQUEST_METHOD'} eq 'POST') {
        read(STDIN, $query, $ENV{'CONTENT_LENGTH'});
    }

    my @params = split(/&/, $query);
    my ($key, $value);

    foreach my $param (@params) {
        ($key, $value) = split(/=/, $param);
        $value =~ tr/+/ /;
        $value =~ s/%([\w].)/pack("C", hex($1))/eg;
        $param_of{$key} = $value;
    }
}

sub open_file {
    my $file = shift;
    my $result;

    open(my $fh, "<", $file) or croak("$!\n");
    binmode($fh, ":utf8");

    local $/;

    $result = <$fh>;
    close($fh) or croak("$!\n");

    return $result;
}

sub parse_template {
    my %arg_of = @_;

    my $template = $arg_of{'template_ref'};
    my $value_of = $arg_of{'value_of_ref'};

    my $pre_delim  = '[%';
    my $post_delim = '%]';

    local ($1, $2);

    ${$template} =~ s/
        (
            \Q$pre_delim\E
            \s* \$ (\S+?) \s*
            \Q$post_delim\E
        )
    /
        exists $value_of->{$2} ? $value_of->{$2} : $1;
    /gexms;
}

Static Site Generator

This Perl script creates static webpages by concatenating header, content, and footer into HTML files. Use it to generate websites offline. You can then upload the HTML files by SFTP or rsync.

The pages are stored in directory $input_dir in HTML format and will be extended by the header and the footer automatically. The output files are saved to $output_dir.

You can set the <title> of a webpage to the text of the <h2> heading by inserting [% title %] into it, for example:

<title>[% title %] - My Website</title>

Source Code

#!/usr/bin/perl
# Static Site Generator in Perl 5
# Licence: Public Domain

use strict;
use warnings;

use encoding qw(utf8);
use utf8;

our $header_file = "./template/header.html";
our $footer_file = "./template/footer.html";
our $input_dir   = "./input/";
our $output_dir  = "./output/";
our $file_ext    = ".html";

sub open_file {
    my $file = shift;
    my $result;

    open(my $fh, "<", $file) or die("$!\n");
    binmode($fh, ":utf8");

    local $/;

    $result = <$fh>;
    close($fh) or die("$!\n");

    return $result;
}

sub save_file {
    my $file = shift;
    my $content = shift;

    open(my $fh, ">", $file) or die("$!\n");
    binmode($fh, ":utf8");

    print $fh $content;
    close($fh) or die("$!\n");
}

# open header and footer
my $header = &open_file($header_file);
my $footer = &open_file($footer_file);

# get HTML file names
opendir(DIR, $input_dir);
my @filenames = grep { /^.*(\Q$file_ext\E$)/i } readdir(DIR);
closedir(DIR);

# concatenate header, content, and footer
for my $filename (@filenames) {
    print $filename . "\n";

    my $content = &open_file($input_dir . $filename);

    # use page heading (h2) as HTML title
    local $1;
    $content =~ m/<h2>(.*)<\/h2>/;
    my $title = $1;
    my $temp_header = $header;
    $temp_header =~ s/\$title/$title/;

    # output generated page
    my $page = $temp_header . $content . $footer;
    &save_file($output_dir . $filename, $page);
}
camel

back