Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Markup::Perl Review / Demo (Basic CGI Shell)

by usemodperl (Beadle)
on Jul 03, 2018 at 17:13 UTC ( [id://1217834]=CUFP: print w/replies, xml ) Need Help??

There are many ways to embed Perl in HTML. One of my favorites that gets something in a browser rapidly is the module Markup::Perl. Once imported with "use" the script behaves like an HTML document with an excellent new <perl> tag that enables perl embeds! It automatically imports param, cookie and header functions from the CGI distribution to handle input, memory, and output tasks. It can also recursively include files with more <perl> tags.

Markup::Perl has been around since 2006 with only 1 revision. The module code is miniscule and powerful. The documentation is brief yet complete. Super Search can't find any mention of it in The Monastery so it must be time for a review! 12 years after release this remains a mature and stable distribution.

This 240 line demo requires the CPAN modules Markup::Perl and HTML::Entities.

Edit: Changed URL from http:// to file:// in POD USAGE CLI.



#!/usr/bin/perl #!__________________________________________.###@ #! ## #! Markup::Perl -> Review/Demo by usemodperl 07/01/2018 # #! | #! "For some problems, particularly in the presentation layer, | #! thinking of the solution as a webpage that can run perl is | #! more natural than thinking of it as a perl script that can | #! print a webpage." <- All quotes from Markup::Perl pod. .# #!____________________________________________________________.## #! # use strict; # Avoid dreaded traps. | use warnings; # Bug removal machine. | use ExtUtils::Installed; # CORE | use Pod::Simple::HTML; # CORE | use HTML::Entities; # CPAN .# #!____________________________________________________________.## #! # #! "It's a perl script when it starts. But as soon as the | #! following line is encountered the rules all change": | #! .# #! use Markup::Perl; # CPAN .## #!__________________________________________________________.###@ =head1 NAME Markup::Perl -> Review/Demo by usemodperl =head1 DESCRIPTION Markup::Perl promises to "turn your CGI inside-out" and the results are web programming paradise. This demo is a basic CGI shell. When not supplied with parameters it reads and prints its own pod as HTML and displays its source code in a textarea. It also prints the pod from Markup::Perl and displays its source in a textarea. Markup::Perl is extremely useful for rapid prototyping and creating single user CGI utilities. It parses and evals <perl> tags embedded in HTML in scripts that use the module, and recursively from external files. =head1 USAGE Run this demo as CGI to render HTML; or command line for raw output. =over =item CGI HTML form, and query string: ?cmd=pwd =item CLI perl this.pl cmd=pwd perl this.pl > that.html; open file:///path/to/that.html =back =head1 POWERS Recursive includes! Handle params and cookies! fatalsToBrowser built-in! =head1 QUIRKS For more about running code with eval see: perldoc -f eval. Recursive self-referential includes will result in busy zombies so try not to do anything like: <perl>src($0)</perl> Includes should not include themselves (or files that include them). Watch out for unclosed loops and <perl> tags. It's only an issue during development. =head1 TEMPLATE #!/usr/bin/perl use strict; use warnings; use Markup::Perl; <!DOCTYPE html><html lang=en><head> <title></title></head><body> <perl> print "Perl $^V" </perl> </body> </html> =head1 CONCLUSION =over =item Markup::Perl is powerful, productive and fun! L<https://metacpan.org/pod/Markup::Perl> =back =head1 AUTHOR =over =item usemodperl L<https://perlmonks.org/?node_id=1216830> =back =cut # HERE COMES EVERYONE (PERL/HTML/CSS/JS): use Markup::Perl; <!DOCTYPE html> <html lang=en> <perl> # DEFINE PERL VARIABLES my $cmd = param('cmd') || ''; my $cfg = param('cfg') || ''; my $form = HTML::Entities::encode_entities($cmd) || ''; my $CPAN = 'https://metacpan.org/pod/Markup::Perl'; my $time = time; </perl> <!-- GENERATE DOCUMENT TITLE --> <head><title><perl> print $form ? "Perl $^V" : 'Markup::Perl CGI Demo'; </perl></title></head> <body onload=document.getElementById("cmd").focus()> <a name=top></a> <div class=d> <!-- COMMAND INPUT FORM --> <span class=y><FORM><input type=text name=cmd value="<perl> print $form </perl>" id=cmd size=32 class=darkform title="enter shell command">&nbsp;&nbsp;<a title=Reset class=c href=?cmd=>&#128042;</a></FORM></span> <br clear=all> <perl> # RUN SHELL COMMAND if ($cmd) { # TAINT A THING $_ = `$cmd`; print '<br><ul><pre>', HTML::Entities::encode_entities($_), '</pre></ul>' } # GENERATE DEFAULT DISPLAY else { # FIND MODULE FILE $_ = ExtUtils::Installed->new; @_ = $_->files("Markup::Perl"); @_ = grep/\.pm$/, @_; # READ MODULE AND SELF my $module = do{local(@ARGV,$/)=$_[0];<>}; my $self = do{local(@ARGV,$/)=$0;<>}; # SELF POD TO HTML my $spod = Pod::Simple::HTML->new; $spod->output_string(\my $shtml); $spod->parse_string_document($self); $shtml =~ s\^.*?(<h1>.*?)</body></html>\$1\s; # INSERT DEMO LINK INTO PERLDOC $shtml =~ s\(perldoc....eval)\<a href="$ENV{REQUEST_SCHEME}://$ENV{SERVER_NAME}$ENV{SCRIPT_NAME}?cmd=pe +rldoc+-f+eval"> $1</a>\sx; # NOT USUALLY POSSIBLE! :-) $shtml =~ s\(basic.....shell)\<a href="$ENV{REQUEST_SCHEME}://$ENV{SERVER_NAME}$ENV{SCRIPT_NAME}?cmd=ls ++-l"> $1</a>\sx; # PRINT SELF POD print $shtml, '<h1>SOURCE</h1>', "<h4><a href='file://$0'>$0</a></h4>", # PRINT SELF SOURCE '<FORM><textarea cols=80 rows=20 class=darkform>', HTML::Entities::encode_entities($self), '</textarea></FORM><br><br><hr>'; # MODULE POD TO HTML my $mpod = Pod::Simple::HTML->new; $mpod->output_string(\my $mhtml); $mpod->parse_string_document($module); $mhtml =~ s\^.*?(<h1>.*?)</body></html>\$1\s; # REMOVE POD FROM SOURCE $module =~ s\__END__.*$\\s; # PRINT MODULE POD print $mhtml, '<h1>SOURCE</h1>', "<h4><a href='file://$_[0]'>$_[0]</a></h4><FORM>", # PRINT MODULE SOURCE '<FORM><textarea cols=80 rows=20 class=darkform>', HTML::Entities::encode_entities($module), '</textarea></FORM>', # PRINT PERL INFO '<h1>perl -v</h1><div class=s><pre>', `perl -v`, '</pre></div>'; } # ADD HTTP HEADER header('X-Powered-By' => 'Perl'); # KISS PERL GOODBYE, FOR NOW </perl> <!-- DARK THEME --> <style> textarea { width:100%; } .darkform { background-color:#666666; color:#FFFFFF; } html, body { max-width:100%; overflow-x:hidden; } body { background-color:black; color:#cccccc; margin:0 auto; } a { text-decoration:none; } a:link{ color: #CFF } a:visited { color: #FFC } #dark theme :-) .tt { font-family:monospace; } .c { font-size:48px; } .s { font-size:small; } .y { float:right; margin:0px; padding:0px; } .d { width:95%; margin:0 auto; } </style> <!-- FOOTER --> <h1 align=center><a href=#top>&#8682;</a><br><br><h4 align=center><b> STOP REINVENTING WHEELS, START BUILDING SPACE ROCKETS! </b>&mdash;<a href="https://www.cpan.org/">CPAN</a>&nbsp;&#128042;</h4 +> </body> </html> <perl> #!_Markup::Perl -> Review/Demo________________________.usemodperl #! # #! "It's a perl script when it starts. But as soon as the | #! following line is encountered the rules all change": .# #!___________________________________________________________.### #! .# #! use Markup::Perl: https://metacpan.org/pod/Markup::Perl .## #!__________________________________________________________.###@ </perl>


STOP REINVENTING WHEELS, START BUILDING SPACE ROCKETS!CPAN 🐪

Replies are listed 'Best First'.
Re: Markup::Perl Review / Demo (Basic CGI Shell)
by marto (Cardinal) on Jul 04, 2018 at 08:58 UTC

    "12 years after release this remains a mature and stable distribution."

    It's never passed a build on windows, because of a test which really doesn't make much sense. It is dependant on CGI, which states:

    "The rationale for this decision is that CGI.pm is no longer considered good practice for developing web applications, including quick prototyping and small web scripts. There are far better, cleaner, quicker, easier, safer, more scalable, more extensible, more modern alternatives available at this point in time. These will be documented with CGI::Alternatives."

    User beware, running user submitted input via backticks

      Thank you for the information marto!

      I looked at that test and ran what it's doing with success on osx. Do you know why that fails on windows? If it has something to do with $^X (from the test) then it might install with force since it's not in the module source.

      Thanks for warning people again about the shell mentioned in the title and pod; you have an eye for danger! It's just a demo and much less powerful than a real shell since it only runs with the privs of the web server. This is a typical single user administrative script for us kids who run perl on our home computers and don't have to worry about the perils of exposing it to the internet.

      I wouldn't use Markup::Perl in production on the net. It's been tested with perlrun under mod_perl and that didn't work but was not persued because, even though any handler can be made to work eventually, it's not necessary since we're not going into production with a hobby module. Frankly I don't care for the rationalizations and considerations (or the policing) that discourage and cripple a legacy core module on CPAN that ~246 distributions depend on (some very popular): https://metacpan.org/requires/module/CGI

      The most recent Perl my review script was tested on:
      
      perl -le'print$^V'
      v5.26.2
      
      perl -MCGI -le'print$CGI::VERSION'
      4.38
      
      
      Markup::Perl can't be run from the command line AFAIK because of that magic but the version here is 0.5.

      STOP REINVENTING WHEELS, START BUILDING SPACE ROCKETS!CPAN 🐪

        The test fails because it doesn't know about how to run shell commands on Windows:

        `$perl -e'print 1;'`;

        On Windows, the shell only understands double quotes.

        "If it has something to do with $^X"

        $^X has no issues on windows. As Corion mentions the failure relates to not catering for windows quoting. You said this module "is extremely useful for rapid prototyping", the alternatives listed in CGI::Alternatives are a better choice in this (and in fact every) respect , because it's trivial to rapidly prototype and scale up without throwing away the code, which you'd be doing if you went down your recommended path.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://1217834]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (3)
As of 2024-04-24 23:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found