[prev in list] [next in list] [prev in thread] [next in thread]
List: apache-modperl
Subject: QML
From: Kevin Hutchinson <kev () frontierworld ! com>
Date: 1998-08-29 19:44:02
[Download RAW message or body]
Hi
I implemented a high level web page language called QML
(http://www.qml.org) a couple of months ago in plain old Perl/CGI, then
I heard about mod_perl so I spent today turning it into QML.pm and wow -
I can't believe what a speed improvement it gives. I hope you don't mind
me forwarding it to you (it's only 20k) but I was hoping someone on the
mod_perl list might be able to give me some pointers as to improvements
etc.
Thanks
Kev
["QML.pm" (text/plain)]
#!/usr/bin/perl
# QML - Quick Markup Language (information at http://www.qml.org)
# Copyright (C) 1998 Kevin Hutchinson (mailto:kev@quicka.com)
# This program is free software; you may redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
package Apache::QML;
use Apache();
use Apache::Constants qw(:common OPT_EXECCGI);
sub handler
{
# Prepare the name space
# ----------------------
&cleanup;
&setup;
# Get and check the request
# -------------------------
$REQUEST = shift;
if (!($REQUEST->allow_options & OPT_EXECCGI))
{
$REQUEST->log_reason("Options ExecCGI is off in this directory", $filename);
return FORBIDDEN;
}
# Get the env, path and page
# --------------------------
%ENV = $REQUEST->cgi_env;
$PATH = $REQUEST->filename;
$PATH =~ s/(\w*\.\w*)$//;
$PAGE = $1;
# Parse the QML and write it as HTML
# ----------------------------------
&fields;
&cookies;
&read("$PATH$PAGE");
&write;
# Send any mail messages then finish
# ----------------------------------
&mailer;
return OK;
}
sub cleanup
{
my $symbol;
foreach $symbol (keys %Apache::QML::)
{
if (defined($$symbol))
{
undef $$symbol;
}
if (defined(@$symbol))
{
undef @$symbol;
}
if (defined(%$symbol))
{
undef %$symbol;
}
}
}
sub setup
{
# Your configuration
# ------------------
$_EMAIL = 'mailserver@qml.org';
$_DOMAIN = '.qml.org';
$_MAILPROGRAM = 'sendmail';
# Public properties
# -----------------
$VERSION = "2.6";
$NEWLINE = "<br>";
$PAGETITLE = "";
$PAGECOLOR = "";
$PAGEIMAGE = "";
$PAGETARGET = "";
$PAGEBASE = "";
$HEADCODE = "";
$BODYTAGS = "";
$ONLOAD = "";
$FONTFACE = "times";
$FONTSIZE = 3;
$FONTCOLOR = "black";
$TABLEBORDER = 1;
$TABLECOLOR = "";
$TABLETAGS = "";
$CELLCOLOR = "";
$CELLWIDTH = "";
$CELLHEIGHT = "";
$CELLALIGN = "";
$CELLVALIGN = "";
$CELLPADDING = "";
$CELLSPACING = "";
$CELLTAGS = "";
$IMAGEBORDER = 0;
$IMAGEWIDTH = "";
$IMAGEHEIGHT = "";
$IMAGENAME = "";
$IMAGETAGS = "";
$LINKCOLOR = "";
$VISITCOLOR = "";
$ACTIVECOLOR = "";
$LINKTARGET = "";
$LINKTAGS = "";
$ONCLICK = "";
$ONMOUSEOVER = "";
$ONMOUSEOUT = "";
$FORMACTION = "";
$FORMMETHOD = "post";
$FORMTAGS = "";
$ONSUBMIT = "";
$FIELDWIDTH = 40;
$FIELDTAGS = "";
$TEXTCOLS = 40;
$TEXTROWS = 5;
$TEXTWRAP = "virtual";
$SUBJECT = "";
$ADDRESS = "";
# Private properties
# ------------------
$_LASTFACE = "";
$_LASTSIZE = "";
$_LASTCOLOR = "";
$_LASTALIGN = "";
$_LASTLIST = "";
$_LISTTYPE = "";
$_LISTITEM = "";
$_LISTDEPTH = 0;
$_LISTNAME = "";
$_SELECTED = "";
$_FONTEND = "";
$_LIST = "_BODYCODE";
$_SECTION = 0;
$_SUBSECTION = 0;
$_INCLUDE = 0;
@_PARSING = (1);
@_MACROS = ();
# Tag translations
# ----------------
%TAGS = (
"BOLD" => "b",
"ITALIC" => "i",
"HEADER1" => "h1",
"HEADER2" => "h2",
"HEADER3" => "h3",
"HEADER4" => "h4",
"HEADER5" => "h5",
"BULLETS" => "ul",
"NUMBERS" => "ol",
"BIG" => "big",
"SMALL" => "small",
"BLINK" => "blink",
"STRIKE" => "strike",
"CENTER" => "center",
"MONOSPACE" => "tt",
"SUBSCRIPT" => "sub",
"SUPERSCRIPT" => "sup",
);
# Global lists
# ------------
@_HEADCODE = ();
@_CONTENTS = ();
@_BODYCODE = ();
@_PERLCODE = ();
@_FOOTCODE = ();
# Global hashes
# -------------
%EXPIRES = ();
%COOKIE = ();
%FIELD = ();
%META = ();
}
# QML subroutines
# ---------------
sub fields # Read any input fields into the %FIELD hash
{
my ($request_method, $query_string, @key_value_pairs, $key_value, $key, $value);
$request_method = $ENV{'REQUEST_METHOD'};
if ($request_method eq "GET")
{
$query_string = $ENV{'QUERY_STRING'};
}
elsif ($request_method eq "POST")
{
read(STDIN, $query_string, $ENV{'CONTENT_LENGTH'});
}
else
{
return;
}
@key_value_pairs = split(/&/, $query_string);
foreach $key_value (@key_value_pairs)
{
($key, $value) = &unescape($key_value);
if (defined($FIELD{$key}))
{
$FIELD{$key} = join("\0", $FIELD{$key}, $value);
}
else
{
$FIELD{$key} = $value;
}
}
}
sub cookies # Read any cookies into the %COOKIE hash
{
my (@key_value_pairs, $key_value, $key, $value);
@key_value_pairs = split(/;\s/, $ENV{'HTTP_COOKIE'});
foreach $key_value (@key_value_pairs)
{
($key, $value) = &unescape($key_value);
$COOKIE{$key} = $value;
}
}
sub escape # Escape special characters to format for "eval"
{
my ($text) = @_;
$text =~ s/\^/\\\^/g;
$text =~ s/\`/\\\`/g;
$text =~ s/\@/\\\@/g;
return $text;
}
sub unescape # Unescape HTTP "%" character encodings
{
my ($key_value) = @_;
my ($key, $value) = split(/=/, $key_value);
$key =~ tr/+/ /;
$value =~ tr/+/ /;
$key =~ s/%(..)/pack ("C", hex($1))/eg;
$value =~ s/%(..)/pack ("C", hex($1))/eg;
return ($key, $value);
}
sub read # Read a QML file one line at a time
{
my ($file) = @_;
local(*FILE);
open (FILE, "$file");
READ:
while (<FILE>)
{
last READ if /^__END__$/;
chomp $_;
&qml($_);
}
close FILE;
}
sub qml # Read a QML line
{
my ($_line) = @_;
if ($_LIST eq "_PERLCODE" && $_line !~ /^\s*sub=/i)
{
push @_PERLCODE, $_line;
}
elsif ($_LIST !~ /^_/ && $_line !~ /^\s*macro=/i)
{
if ($_LIST eq "MAILER" || $_LIST eq "JAVASCRIPT")
{
&html($_line);
}
else
{
push @$_LIST, $_line;
}
}
elsif ($_line =~ /^\s*if=(.*)/i)
{
&IF($1);
}
elsif (! $_PARSING[-1])
{
# Don't parse
}
elsif ($_line =~ /^\s*([\$\w{}\[\]]*)=(.*)/)
{
my ($_lhs, $_rhs) = ($1, $2);
if ($_lhs eq "")
{
# Comment line
}
elsif ($_lhs =~ s/^\$//)
{
$_rhs = &escape($_rhs);
eval "\$$_lhs = qq^$_rhs^";
}
else
{
$_lhs =~ tr/a-z/A-Z/;
my $tag = $TAGS{$_lhs};
if (defined &$_lhs)
{
&$_lhs($_rhs);
}
elsif ($tag ne "")
{
&font("");
push @$_LIST, "<$tag>";
&qml("$_rhs");
$$_LIST[-1] .= "</$tag>";
}
else
{
$_rhs = &escape($_rhs);
eval "\$$_lhs = qq^$_rhs^";
}
}
}
else
{
my $_newline = 1;
if ($_LISTITEM ne "")
{
$_newline = 0;
$_line =~ s/^\s*//;
$_SELECTED = $_LISTITEM eq "<option\$_SELECTED>" && $FIELD{$_LISTNAME} eq $_line ? \
" selected" : ""; $_line = "$_LISTITEM$_line";
}
elsif ($_line =~ s/_$// || $NEWLINE eq "")
{
$_newline = 0;
}
if ($_line ne "")
{
&font("");
&html("$_line");
}
&html("$NEWLINE") if $_newline;
}
}
sub html # Store some HTML in a list
{
my ($_html) = @_;
$_html = &escape($_html);
eval "\$_html = qq^$_html^";
push @$_LIST, "$_html";
}
sub font # Set the font if wrapping HTML, or face/size/color has changed
{
my ($html) = @_;
if ($html || $FONTFACE ne $_LASTFACE || $FONTSIZE ne $_LASTSIZE || $FONTCOLOR ne \
$_LASTCOLOR) {
push @$_LIST, "" unless scalar @$_LIST;
$$_LIST[-1] .= "$_FONTEND";
$$_LIST[-1] .= "$html" if $html;
$$_LIST[-1] .= "<font face=\"$FONTFACE\" size=\"$FONTSIZE\" color=\"$FONTCOLOR\">";
$_LASTFACE = $FONTFACE;
$_LASTSIZE = $FONTSIZE;
$_LASTCOLOR = $FONTCOLOR;
$_FONTEND = "</font>";
}
}
sub write # Write cookies, header, sections, body and footer
{
&footer;
if ($_SECTION > 0)
{
push @HEADER, "header3=Contents";
push @HEADER, "<ol>_";
push @HEADER, @_CONTENTS;
push @HEADER, "</ol>_";
push @HEADER, "line=100%";
}
&header;
my $key;
foreach $key (keys %COOKIE)
{
$EXPIRES{$key} = "Thu, 20 Feb 2020 20:20:20 PDT" unless $EXPIRES{$key};
$REQUEST->header_out("Set-cookie" => "$key=$COOKIE{$key}; domain=$_DOMAIN; path=/; \
expires=$EXPIRES{$key}"); }
$REQUEST->content_type("Content-type: text/html");
&writelist("_HEADCODE");
&writelist("_BODYCODE");
&writelist("_FOOTCODE");
}
sub writelist # Write some stored HTML
{
my ($list) = @_;
print join("\n", @$list);
}
sub header # Store the page header in a list
{
$_LIST = "_HEADCODE";
&html("<html>");
&html("<head>");
&html(" <title>$PAGETITLE</title>");
my $base = "";
$base .= " target=\"$PAGETARGET\"" if $PAGETARGET;
$base .= " href=\"$PAGEBASE\"" if $PAGEBASE;
&html(" <base$base>") if $base;
my $key;
foreach $key (keys %META)
{
&html(" <meta http-equiv=\"$key\" content=\"$META{$key}\">");
}
&html("$HEADCODE") if $HEADCODE;
if (defined(@JAVASCRIPT))
{
&html("<script language=JavaScript>");
push @$_LIST, @JAVASCRIPT;
&html("</script>");
}
&html("</head>");
my $body = "body";
$body .= " bgcolor=\"$PAGECOLOR\"" if $PAGECOLOR;
$body .= " background=\"$PAGEIMAGE\"" if $PAGEIMAGE;
$body .= " link=\"$LINKCOLOR\"" if $LINKCOLOR;
$body .= " vlink=\"$VISITCOLOR\"" if $VISITCOLOR;
$body .= " alink=\"$ACTIVECOLOR\"" if $ACTIVECOLOR;
$body .= " onLoad=\"$ONLOAD\"" if $ONLOAD;
$body .= " $BODYTAGS" if $BODYTAGS;
&html("<$body>");
$FORMACTION = $PAGE unless $FORMACTION;
my $form = "form";
$form .= " method=\"$FORMMETHOD\"";
$form .= " action=\"$FORMACTION\"";
$form .= " onSubmit=\"$ONSUBMIT\"" if $ONSUBMIT;
$form .= " $FORMTAGS" if $FORMTAGS;
&html("<$form>");
if (defined(@HEADER))
{
$_LASTFACE = $_LASTSIZE = $_LASTCOLOR = $_FONTEND = "";
&INCLUDE("HEADER");
$_FONTEND = "</font>";
&html($_FONTEND);
}
}
sub footer # Store the page footer in a list
{
$_LIST = "_FOOTCODE";
&font("");
&INCLUDE("FOOTER") if defined(@FOOTER);
&ALIGN("");
&html("</font>");
&html("</form>");
&html("</body>");
&html("</html>");
}
sub mailer # Mail a stored message to an email address
{
return unless $ADDRESS && defined(@MAILER) && scalar @MAILER;
if ($_MAILPROGRAM eq "sendmail")
{
open (MSG, "| sendmail -t -n");
print MSG "To: $ADDRESS\n";
print MSG "From: $_EMAIL\n";
print MSG "Subject: $SUBJECT\n\n";
}
else
{
open (MSG, "| $_MAILPROGRAM -s \"$SUBJECT\" $ADDRESS");
}
print MSG join("\n", @MAILER);
close MSG;
}
# QML commands
# ------------
sub SECTION # Add a new section to the page
{
$_SECTION++;
$_SUBSECTION = 0;
my ($section) = @_;
push @_CONTENTS, "<li><a href=\"#$_SECTION\">$section</a>_";
&font("");
&html("<h3>$_SECTION <a name=\"$_SECTION\">$section</a></h3>");
}
sub SUBSECTION # Add a new subsection to the page
{
$_SUBSECTION++;
my ($subsection) = @_;
push @_CONTENTS, "<br>$_SECTION.${_SUBSECTION} <a \
href=\"#$_SECTION.$_SUBSECTION\">$subsection</a>_"; &font("");
&html("<h4>$_SECTION.$_SUBSECTION <a \
name=\"$_SECTION.$_SUBSECTION\">$subsection</a></h4>"); }
sub IMAGE # Add an image and its description to the page
{
my ($image) = @_;
if ($image =~ /(\S+)\s*(.*)/)
{
my $tags = "";
$tags .= " width=$IMAGEWIDTH" if $IMAGEWIDTH ne "";
$tags .= " height=$IMAGEHEIGHT" if $IMAGEHEIGHT ne "";
$tags .= " name=\"$IMAGENAME\"" if $IMAGENAME ne "";
$tags .= " $IMAGETAGS" if $IMAGETAGS;
&html("<img src=\"$1\" alt=\"$2\" border=$IMAGEBORDER$tags>");
}
}
sub EMAIL # Add an email address link to the page
{
my ($email) = @_;
if ($email =~ /(\S+)\s*(.*)/)
{
my $line = $2;
$line = $1 unless $line;
my $link = $1;
$link =~ s/_$//;
my $subject = "";
$subject = "?subject=$SUBJECT" if $SUBJECT;
&font("");
&html("<a href=\"mailto:$link$subject\">");
&qml("$line");
$$_LIST[-1] .= "</a>";
}
}
sub LINK # Add a hyperlink to the page
{
my ($link) = @_;
if ($link =~ /(\S+)\s*(.*)/)
{
my $line = $2;
$line = $1 unless $line;
my $link = $1;
$link =~ s/_$//;
my $tags = "";
$tags .= " target=\"$LINKTARGET\"" if $LINKTARGET;
$tags .= " onClick=\"$ONCLICK\"" if $ONCLICK;
$tags .= " onMouseOver=\"$ONMOUSEOVER\"" if $ONMOUSEOVER;
$tags .= " onMouseOut=\"$ONMOUSEOUT\"" if $ONMOUSEOUT;
$tags .= " $LINKTAGS" if $LINKTAGS;
&font("");
&html("<a href=\"$link\"$tags>");
&qml("$line");
$$_LIST[-1] .= "</a>";
}
}
sub TABLE # Add a table, row or cell to the page
{
my ($table) = @_;
$table =~ tr/a-z/A-Z/;
$CELLWIDTH = "" if $table eq "ROW";
my $cell = "";
$cell .= " align=\"$CELLALIGN\"" if $CELLALIGN;
$cell .= " valign=\"$CELLVALIGN\"" if $CELLVALIGN;
$cell .= " bgcolor=\"$CELLCOLOR\"" if $CELLCOLOR;
$cell .= " width=\"$CELLWIDTH\"" if $CELLWIDTH ne "";
$cell .= " height=\"$CELLHEIGHT\"" if $CELLHEIGHT ne "";
$cell .= " $CELLTAGS" if $CELLTAGS;
if ($table eq "" || $table eq "END")
{
&font("</td></tr></table>");
}
elsif ($table eq "ROW")
{
&font("</td></tr><tr><td$cell>");
}
elsif ($table eq "CELL")
{
&font("</td><td$cell>");
}
else
{
my ($width, $height) = split (/\s+/, $table);
my $tags = " border=\"$TABLEBORDER\"";
$tags .= " width=\"$width\"" if $width ne "";
$tags .= " height=\"$height\"" if $height ne "";
$tags .= " bgcolor=\"$TABLECOLOR\"" if $TABLECOLOR;
$tags .= " cellpadding=\"$CELLPADDING\"" if $CELLPADDING ne "";
$tags .= " cellspacing=\"$CELLSPACING\"" if $CELLSPACING ne "";
$tags .= " $TABLETAGS" if $TABLETAGS;
&font("<table$tags><tr><td$cell>");
}
}
sub LIST # Add a number or bullet list to the page
{
my ($list) = @_;
$list =~ tr/a-z/A-Z/;
if ($list eq "" || $list eq "END")
{
&html("</$_LISTTYPE>");
$_LISTITEM = "" unless --$_LISTDEPTH;
$_LISTDEPTH = 0 if $_LISTDEPTH < 0;
}
else
{
$_LISTTYPE = $TAGS{$list};
$_LISTTYPE = $list unless $_LISTTYPE;
&html("<$_LISTTYPE>");
$_LISTITEM = "<li>";
$_LISTDEPTH++;
}
}
sub LINE # Add a horizontal line to the page
{
my ($width) = @_;
$width="100%" unless $width;
&html("<hr width=$width>");
}
sub ALIGN # Add an alignment to the page
{
my ($align) = @_;
$align =~ tr/a-z/A-Z/;
if ($_LASTALIGN eq "CENTER")
{
&html("</center>");
}
elsif ($_LASTALIGN eq "RIGHT")
{
&html("</p>");
}
if ($align eq "CENTER")
{
&html("<center>");
}
elsif ($align eq "RIGHT")
{
&html("<p align=right>");
}
$_LASTALIGN = $align;
}
sub IF # Conditionally process furthur QML commands
{
my ($if) = @_;
if ($if eq "" || $if =~ /^end$/i)
{
pop @_PARSING if scalar @_PARSING > 1;
}
elsif ($if =~ /^else$/i)
{
my $i = 0;
my $j = 1;
while ($i < $#_PARSING)
{
$j *= $_PARSING[$i++];
}
$_PARSING[$i] = $j * !$_PARSING[$i];
}
elsif ($_PARSING[-1])
{
$if = &escape($if);
push @_PARSING, !!eval qq^$if^;
}
else
{
push @_PARSING, 0;
}
}
sub MACRO # Define a macro of QML commands
{
my ($macro) = @_;
$macro =~ tr/a-z/A-Z/;
if ($macro eq "" || $macro eq "END")
{
$_LIST = pop @_MACROS;
$_LIST = "_BODYCODE" unless $_LIST;
}
else
{
push @_MACROS, $_LIST;
$_LIST = $macro;
}
}
sub INCLUDE # Include a macro or file of QML commands
{
my ($include) = @_;
return if $_INCLUDE++ > 100;
my $macro = $include;
$macro =~ tr/a-z/A-Z/;
if (defined(@$macro))
{
my $line;
foreach $line (@$macro)
{
&qml($line);
}
}
elsif (-f "$PATH$include")
{
&read("$PATH$include");
}
elsif (-f "$PATH$include.qml")
{
&read("$PATH$include.qml");
if (defined(@$macro))
{
my $line;
foreach $line (@$macro)
{
&qml($line);
}
}
}
$_INCLUDE--;
}
sub SUB # Define a Perl subroutine as a new QML command
{
my ($sub) = @_;
$sub =~ tr/a-z/A-Z/;
if ($sub eq "" || $sub eq "END")
{
push @_PERLCODE, "}";
eval join "\n", @_PERLCODE;
@_PERLCODE = ();
$_LIST = $_LASTLIST;
}
else
{
$_LASTLIST = $_LIST;
$_LIST = "_PERLCODE";
push @_PERLCODE, "sub $sub";
push @_PERLCODE, "{";
}
}
sub EVAL # Evaluate a Perl expression
{
my ($eval) = @_;
eval "$eval";
}
# QML form fields
# ---------------
sub extract # Extract a value and arguments from a QML form field
{
my ($text) = @_;
return ($1, $2) if $text =~ /(\S*)\s*(.*)/;
}
sub TEXTFIELD # Add a text field to the page
{
my ($field) = @_;
my ($name, $value) = &extract($field);
$value = $FIELD{$name} unless $value;
&html("<input type=\"text\" name=\"$name\" value=\"$value\" size=\"$FIELDWIDTH\" \
$FIELDTAGS>"); }
sub PASSWORD # Add a password field to the page
{
my ($field) = @_;
my ($name, $value) = &extract($field);
$value = $FIELD{$name} unless $value;
&html("<input type=\"password\" name=\"$name\" value=\"$value\" size=\"$FIELDWIDTH\" \
$FIELDTAGS>"); }
sub TEXTAREA # Add a text area to the page
{
my ($field) = @_;
my ($name, $value) = &extract($field);
$value = $FIELD{$name} unless $value;
&html("<textarea name=\"$name\" cols=\"$TEXTCOLS\" rows=\"$TEXTROWS\" \
wrap=\"$TEXTWRAP\" $FIELDTAGS>$value"); &html("</textarea>");
}
sub PUSHBUTTON # Add a push button to the page
{
my ($field) = @_;
my ($name, $value) = &extract($field);
my $type = $name;
$type = "SUBMIT" unless $type eq "RESET";
$value = $name unless $value;
&html("<input type=\"$type\" name=\"$name\" value=\"$value\" $FIELDTAGS>");
}
sub RADIOBUTTON # Add a radio button to the page
{
my ($field) = @_;
my ($name, $value) = &extract($field);
my $checked = "";
$checked = " checked" if $FIELD{$name} eq $value;
&html("<input type=\"radio\" name=\"$name\" value=\"$value\"$checked $FIELDTAGS>");
}
sub CHECKBOX # Add a check box to the page
{
my ($field) = @_;
my ($name, $value) = &extract($field);
my $checked = "";
$value = "on" unless $value;
$checked = " checked" if $FIELD{$name} eq $value;
&html("<input type=\"checkbox\" name=\"$name\" value=\"$value\"$checked \
$FIELDTAGS>"); }
sub LISTBOX # Add a list box (drop down list) to the page
{
my ($field) = @_;
my ($name, $size) = &extract($field);
$size = 1 unless $size;
$_LISTNAME = $name;
if ($name eq "" || $name =~ /^end$/i)
{
&html("</select>");
$_LISTITEM = "";
}
else
{
&html("<select name=\"$name\" size=\"$size\" $FIELDTAGS>");
$_LISTITEM = "<option\$_SELECTED>";
}
}
sub HIDDENFIELD # Add a hidden field to the page
{
my ($field) = @_;
my ($name, $value) = &extract($field);
&html("<input type=\"hidden\" name=\"$name\" value=\"$value\" $FIELDTAGS>");
}
__END__
=head1 NAME
Apache::QML - High-level web page langauge supporting embedded HTML, Perl and \
JavaScript
=head1 SYNOPSIS
DirectoryIndex index.html index.htm index.shtml index.cgi index.qml
PerlModule Apache::QML
<Files *.qml>
Options +ExecCGI
SetHandler perl-script
PerlHandler Apache::QML
</Files>
=head1 DESCRIPTION
Apache::QML translates QML pages into HTML (and cookies). QML is a high-level
web page language supporting embedded HTML, Perl and JavaScript. For complete
details about the language, please see http://www.qml.org/.
=head2 Installation and Configuration
First you have to install Apache::QML so that Apache/mod_perl can find it.
The file QML.pm should be placed in your "site_perl" directory, typically:
/usr/lib/perl5/site_perl
Second, you have to add the following config snippet to Apache's F<httpd.conf>
file:
DirectoryIndex index.html index.htm index.shtml index.cgi index.qml
PerlModule Apache::QML
<Files *.qml>
Options +ExecCGI
SetHandler perl-script
PerlHandler Apache::QML
</Files>
This forces all files with the extension .qml to be processed by Apache::QML.
The DirectoryIndex line should incude index.qml so that QML files may be index
files for directories.
=head1 AUTHOR
Kevin Hutchinson
kev@quicka.com
www.quicka.com
=head1 HISTORY
QML was first developed as a documentation preprocessor akin to perldoc but
soon grew to become a fully-fledged web language. QML was first run as cgi-bin
programs, then as an apache content handler, and now as an Apache Perl module.
=head1 SEE ALSO
Web-References:
QML: http://www.qml.org/
Perl: perl(1), http://www.perl.com/
mod_perl: mod_perl(1), http://perl.apache.org/
Apache: httpd(7), http://www.apache.org/
=cut
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic