SPUG: My two perl gizmos (CPAN module paralysis)

Fred Morris m3047 at inwa.net
Thu Dec 19 08:17:19 CST 2002


Very briefly, here are short synopses of the two modules which I have
contemplated submitting to CPAN. I know that left to my own devices, that
will never happen.

Both of these modules are utilized in a working application which gets
daily use.

Maybe this'll encourage others to share theirs, and we can get together and
at least get the peer review issue out of the way (there are a number of
impediments standing between me and CPAN, peer review is only one). Or,
maybe somebody will be interested enough to say "hey, I could use that!".
Be aware, neither of them is packaged for distribution at the moment
although anyone who's competent with Perl should have no problem getting
them to work; they do have POD.


A CANONICALIZED STRING CONSTANT RESOLVER

Problem:

Generally speaking, localization. This means for languages, but also for
different parts of an application, or different applications of reusable
parts.

Utility:

I find it useful, but mostly I just think it's cool. The overhead for this
might be somewhat large in a occasionally-used Perl script, but with
mod_perl a persistent hash is constructed of particular fully-qualified
names which have already been resolved.

Synopsis:

The constants are all retrieved with a function call which takes as a
parameter a key which will resolve to a constant (or filter, I lied).

So, you define something like

  Success => { 'string', 'Done!' }

You reference it in different places as

  $cliches->cliche( 'SomeModule.Frotzify.Success' )
  $cliches->cliche( 'ThisModule.Frappe.Success' )

You may decide that when you Frappe you want a different message or when
you Stir in SomeModule the same thing is needed, and so you define
overloads (overrides?):

  Frappe.Success => { 'string', 'Cheers!' }
  SomeModule.Stir.Success => { 'string', 'Mixed!' }



EMBEDDED SQL IN AN HTML REPORT TEMPLATE

Problem:

You need to make a web page which displays the result of a SQL query. You'd
use PHP for this, except you can't bring yourself to embed server code (an
application artifact) in a web page (presentation artifact). Obviously the
SQL is needed, but is anything else? No.

Utility:

Very. I've already stolen it from my app and used it elsewhere on other
projects. You end up with an HTML template which any web page editor will
load (there's an alternate syntax for the SQL statement due to vagaries in
the various WYSIWYG tools, and I would do the same for the liststart and
listend markers if I was packaging this for public consumption).

I looked around CPAN for something this elegant and didn't find it. I even
looked around with Google. Did I reinvent the wheel?

Synopsis:

You need to wrap it in some CGI code which validates parameters and access,
if you're paranoid like me. Then you create a template like the following
(which is an actual, real, live, working example; report, username and
magic are artifacts of my own paranoia handled with some pre and post
processing, and are not part of the module):

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
  <TITLE>Contacts by Name</TITLE>
</HEAD>
<BODY BGCOLOR="#ffffff" LINK="#000000" onload="form_load()">

<FORM NAME="fForm" METHOD="POST" ACTION="../perl/report.cgi">
<script language="JavaScript"><!--

/* Copyright (c) 2002 by Fred Morris, Seattle WA. e-mail: m3047 at inwa.net
 * telephone: 206.297.6344. All rights reserved.
 */

function form_load() {

    // Set the appropriate popup field selection on load.

    var o = "%%sqlp1%%";

    if (o == "companyname") document.fForm.sqlp1.selectedIndex = 0;
    if (o == "lastname")    document.fForm.sqlp1.selectedIndex = 1;
    if (o == "firstname")   document.fForm.sqlp1.selectedIndex = 2;

} // form_load

//--></script>
<H1><CENTER>Contacts by Name</CENTER></H1>

<H2><CENTER><FONT COLOR="#993399">contacts with name %%sqls2%%
for user %%username%%</FONT></CENTER></H2>

<P><HR ALIGN=LEFT><INPUT NAME="username" TYPE="hidden" VALUE="%%username%%">
<INPUT NAME="magic" TYPE="hidden" VALUE="%%magic%%"> <INPUT NAME="report"
TYPE="hidden" VALUE="contactname">

<!--SQL
SELECT Contact.type, Contact.companyname, Contact.lastname,
Contact.firstname, id
FROM Contact
WHERE userid = %%userid%% AND %%sqlp1%% LIKE CONCAT( %%sqls2%%, '%' )
ORDER BY Contact.type, Contact.companyname, Contact.lastname, Contact.firstname
--></P>

<P><B><SELECT NAME="sqlp1">
<OPTION VALUE="companyname" SELECTED>Company Name
<OPTION VALUE="lastname">Last Name
<OPTION VALUE="firstname">First Name
</SELECT> starts with</B>: <INPUT NAME="sqls2" TYPE="text" SIZE="16"
MAXLENGTH="16" VALUE="%%sqls2%%"> <SMALL>(Case-sensitive, starting
with..)</SMALL></P>

<P><CENTER><INPUT NAME="submit" TYPE="submit" VALUE="Submit Query"></CENTER></P>

<P><HR ALIGN=LEFT></P>

<P><I>Click the <U>Type</U> to go to the contact's record.</I></P>

<P><TABLE BORDER="1" CELLSPACING="3" CELLPADDING="1" WIDTH="100%">
  <TR>
    <TD BGCOLOR="#000000" VALIGN="TOP"><B><FONT
COLOR="#ffffff">Type</FONT></B></TD>
    <TD BGCOLOR="#000000" VALIGN="TOP"><B><FONT
COLOR="#ffffff">Company</FONT></B></TD>
    <TD BGCOLOR="#000000" VALIGN="TOP"><B><FONT COLOR="#ffffff">Last
      Name</FONT></B></TD>
    <TD BGCOLOR="#000000" VALIGN="TOP"><B><FONT COLOR="#ffffff">First
      Name</FONT></B></TD>
  </TR><%%liststart%%>
  <TR>
    <TD VALIGN="TOP"><A
HREF="../perl/edit-contact.cgi?username=%%username%%&magic=%%magic%%&id=%%sq
lf5%%">%%sqlf1%%</A></TD>
    <TD VALIGN="TOP">%%sqlf2%%</TD>
    <TD VALIGN="TOP">%%sqlf3%%</TD>
    <TD VALIGN="TOP">%%sqlf4%%</TD>
  </TR><%%listend%%>
</TABLE></P>

<P><CENTER>[<A
HREF="../perl/splash.cgi?username=%%username%%&magic=%%magic%%">home</A>]</C
ENTER></P>

<P><HR ALIGN=LEFT></P>

<BLOCKQUOTE>
  <P><SMALL><SMALL>Copyright (c) 2002 by Fred Morris, 6739 3rd
  NW Seattle WA 98117; e-mail: m3047 at inwa.net; telephone: 206.297.6344.
  All rights reserved.</SMALL></SMALL></P></BLOCKQUOTE>

<H6>rev. date: 14-Jul-2002</H6>

<H6>rev. by: Fred Morris</H6>
</FORM>

</BODY>
</HTML>

I ask you, is there anything in this page which isn't necessary to the
presentation of this particular web page (presuming that you're willing to
grant that SQL is self-documenting, and therefore has virtue)?

Furthermore, the SQL statement does not end up in the page actually
delivered to the (ab)user, avoiding an obvious vulnerability. Every time I
look at the module, I'm amazed at how short the code really is... the power
of Perl! The actual guts of it is 186 lines, including white space and
comments; the POD and whatnot makes it about 450 lines.

--

Fred Morris
m3047 at inwa.net



 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     POST TO: spug-list at pm.org       PROBLEMS: owner-spug-list at pm.org
      Subscriptions; Email to majordomo at pm.org:  ACTION  LIST  EMAIL
  Replace ACTION by subscribe or unsubscribe, EMAIL by your Email-address
 For daily traffic, use spug-list for LIST ;  for weekly, spug-list-digest
     Seattle Perl Users Group (SPUG) Home Page: http://seattleperl.org




More information about the spug-list mailing list