The Penguin Greetings Content Developers' Guide

Edouard Lagache


Copyright © 2003-2005 (Penguin Greetings 1.0.0 edition)

A introduction to developing content for  the Penguin Greetings web-based ecards system.
Table of Contents:

  1. Introduction to Penguin Greetings Content Development
  2. Penguin Greetings Legalese
  3. Quickstart:

    1. I just want my own pretty cards, what do I do? (sys-admin quickstart)
    2. But I don't like the way my image looks in your template!  (template tweaking)

  4. Penguin Greetings development reference:
    1. Penguin Greetings Operational overview
    2. Penguin Greeting templates and Embperl
    3. Card configuration file and configuration parameter access
    4. Penguin Greetings parameters and CGI variables
    5. Using Embperl to simplify content development
    6. Creating Object-Oriented ecard sites
    7. Error handling and form field checking
    8. Testing and debugging templates: PgTemplateTest
    9. Creating secondary ecard sites
    10. Localizing ecard sites in Penguin Greetings
    11. Implementing CGI "Back" buttons
    12. Using shared template libraries
    13. Developing Penguin Greetings content using HTML::Mason
    14. Troubleshooting and Tips

Introduction to Penguin Greetings Content Development

Penguin Greetings is a Perl CGI tool that manages the information for web-based email greeting cards.  It is a tool in development but is already designed to be quite robust and dependable, while avoiding the complexity and overhead of an SQL database backend.  Penguin Greetings attempts to be a "virtuous" backend program: efficiently handling its duties while not getting in the way of the creative content that it serves. 

Penguin Greetings uses a concept of templates to separate the work of card management from the content to be managed.  The HTML to be used in cards and on the screens used to create a card are stored in separate files called templates.  These can be edited by content developers and can take advantage of any service that is accessible through HTML (and Embperl or Mason - see below.)  Penguin Greetings provides support for these templates with configuration files that can be extended by the developer to provide parameters for the cards and categories of cards.  Penguin Greetings can then be instructed (programmed) to run through a set of templates to assemble a card and then store its contents in databases as well as send a multi-part MIME email to the recipient.

[Table of Contents]

Penguin Greetings Legalese

Penguin Greetings is copyright © Edouard Lagache, 2003-2005. Penguin Greetings is released under the GNU General Public License, Version 2. For more information, see the COPYING file included with this software or visit: http://www.gnu.org/copyleft/gpl.html

The artistic content included with this software is also copyright © Edouard Lagache, 2003-2005. It is released under the Design Science License. For more information, see the DSL.txt file included with the software or visit: http://www.dsl.org/copyleft/.

Powered by Penguin Greetings web badge

If you use Penguin Greetings in your own web cards application.  Please give credit were credit is due by displaying the following web badge or something equivalent on your web site:

Powered by Penguin Greetings

There are now quite a few different badges included in Penguin Greetings with the various secondary ecard sites, so take a look if you want something different.  Better still, if you make a nicer web badge, please share it with me so that I can spread the wealth! :-)

[Table of Contents]

I just want my own pretty cards, what do I do?(development quickstart)

Penguin Greetings now ships with an ever growing collection of greeting cards that are similar in style and tastes to Apple's iCards.  System Administrators for systems large and small may find this a nifty addition to their server (even servers for one! ).  However, even the most un-artistic sys-admin will sooner or later want to add some cards of their own to their system.  Those with more ambitious plans will find a simple example a good point of departure.

The easiest way to get some content is to use the same method used for the existing collection - the ol'good camera.  Film cameras are just as useful for this with the advent of photos on disk which is available by most photo finishers.  Unfortunately, the next step is very much in the hands of the content developer - no matter how many thumbs you have.  Still gimp runs on any system that will run Penguin Greetings, and the simplest greeting cards can be made from photos that are rescaled and to which a caption is added.  You'll need to make a thumbnail image for the present system.  The simpleminded solution is to resize the image by about half (Existing Penguin Greetings sites use 40%) and name it something similar like picture.thb.jpg.

Assuming you've crossed the content hurdle and have a photo that you would like to add to the Penguin Greeting content as it is presently shipped, here are the steps needed to add a card to the system.  The bare-bones change is to add the card to the card.conf configuration file (a portion of which is below.)  Suppose you've created a new birthday card, then you need to add a new card to the list of cards and add that card to the category birthday.

# File: cards.conf
######################################################################
#             Greeting card configuration file for
#
#                ** PENGUIN GREETINGS (pgreet) **
#
# A Perl CGI-based web card application for LINUX and probably any
# other UNIX system supporting standard Perl extensions.
#
#     Edouard Lagache, elagache@canebas.org, April 2003
#
#
# The pgreet system uses the Perl Config::General module for
# reading in configuration file information.  The file format
# is the same as for the Apache web server.  The general
# configuration module contains information for both the
# CGI script and the system daemon.  These are kept in
# separate categories for simplicity of management.
#
######################################################################

# Card category definitions:

# ....



<category Birthday>
    caption = "Birthday Cards"
    cards = Birthday_blooms_on_trail
    cards = Bay_bridge_birthday
    cards = Fishing_Birthday
</category>

# ....

# 21
<card Fishing_Birthday>
    caption = "Fishing around for a way to say: Happy Birthday!"
    template = "picture_frame_card.tpl.html"
    image = "Fishing_Birthday.jpg"
    thumb = "Fishing_Birthday.thb.jpg"
</card>

# ....

Every card in the Penguin Greeting system needs a unique name - in this case the card added is called Fishing_Birthday.  Associated with each card is a template.  Penguin Greetings uses a configuration file system that is basically compatible with Apache-styled configurations.  As shipped, Penguin Greetings uses a template to represent a card which contains a plain text caption for the image, a HTML template to be used to display the card, a thumbnail image name, and the name of the image itself.  With this template, it is possible to "lookup" any piece of the card (via Perl hash references) once you have the name of the card.  Again as shipped, Penguin Greetings uses a template for the card categories.  So all the cards that can be used for birthdays are listed in another template with another plain text caption.  So to add a picture to the system, it suffices to copy the image and thumbnail image to the images directory (which you defined when installing Penguin Greetings.)  Then add an entry in card.conf for the new image as shown above for Fishing_birthday.  Finally add an entry for each category that the card could be used in, and ... you're done!

[Table of Contents]


But I don't like the way my picture looks in your card template!! (Template Tweaking)

Warning: .... a little knowledge is a dangerous thing!! ...

If you manage to add your own images to Penguin Greetings, you may want to start making the cards look different.  No problem, the cards are nothing more than HTML where the contents of your card is substituted from the CGI script.  However,  it does you no good unless you know how to get variables from the CGI script into your template.

The first step to making your own templates is to make a copy of the file picture_frame_card.tpl.html which you'll find in the templates folder of Penguin Greetings.  Don't change the original unless you want to change the appearance of every card that comes with Penguin Greetings.  A copy of this template is shown below:

[#
 # Penguin Greetings HTML/Embperl template for an HTML formatted
 # greeting card. 
 #
 # This template is usually called from within
 # other template either for previewing or displaying a card.
 #
 # E. Lagache, 3/2003
 #]

[# Set Embperl options to avoid interpreting characters that could be URLs #]
[* $ENV{'optRawInput'} = 16; *]
[*  $escmode = 0; *]



[# Interface with Penguin Greeting script (pgreet.pl.cgi) #]
[$ var $trans %card_hash %card $]

[-
  # Retrieve parameters from Penguin Greetings script (pgreet.pl.cgi)
  $trans = shift(@param); # $trans is a hash reference

  # All card configuration data
  %card_hash = %{$trans->{'card_hash'}};

  # "record" for selected card.
  %card = %{$card_hash{'card'}->{$trans->{'card'}}};


 -]
    <center>
      <table cellpadding="2" cellspacing="4" border="2" style=
      "text-align: left; width: 400px;">
        <tbody>
          <tr align="center">
            <td style="vertical-align: top;">
            [# retrieve image URL and image name #]
            <img src="[+ $trans->{'imageurl'} +]/[+ $card{'image'} +]"><br>
             </td>
          </tr>

          <tr>
            <td style="vertical-align: top;">
              <table cellpadding="2" cellspacing="2" border="0"
              style="text-align: left; width: 100%;">
                <tbody>
                  <tr>
                    <td style="vertical-align: top;"><span style=
                    "font-family: times new roman,times,serif; font-style: italic;">
                    [# Insert the message text #]
                    [+ $trans->{'html_message'} +]
                    </span><br>
                     </td>
                  </tr>

                  <tr>
                    <td style="vertical-align: top;">
                      <br>
                       <font size="-1"><br>
                      </font>

                      <table cellpadding="2" cellspacing="2"
                      border="1" style=
                      "text-align: left; width: 100%;">
                        <tbody>
                          <tr>
                            <td style=
                            "vertical-align: top; width: 50%;">
                            <font size="-1">
                            [# Insert the sender's name and email #]
                            From: [+ $trans->{'sender_name'} +]<br>
                           [+ $trans->{'sender_email'} +]</font><br>
                             </td>

                            <td style="vertical-align: top;">
                            <font size="-1">
                            [# Insert recipients name and email #]
                            To: [+ $trans->{'recipient_name'} +]<br>
                           [+ $trans->{'recipient_email'} +]</font></td>
                          </tr>
                        </tbody>
                      </table>
                      <br>
                      <div style="text-align: center;">
                        <a href="http://www.canebas.org/pgreet/">
    <img src="[+ $trans->{'imageurl'} +]/powered_by_pgreet.gif"
                  border="0" align="center"></a>
                      </div>
                    </td>
                  </tr>
                </tbody>
              </table>
            </td>
          </tr>
        </tbody>
      </table>
    </center>


Now the HTML may look like HTML, but what is all this odd looking stuff between the square brackets [ ] ?  Anything between the square brackets is processed by Embperl before being sent to the web server.  This is a very powerful tool as will be seen below, but for now, you can think about it as a way of getting values from the CGI script into your HTML.

The procedure you could use to make a new card template might be something like this:  get the content that you want to use in your new cards and copy it to a single folder (this content will end up in the 'images' folder of Penguin Greetings.)  Next, create a new bit of HTML, using whatever tools you like (even the Mozilla composer would do.) When you are satisfied with your new card template, open it up in a plain-text editor (Emacs, Vi, Pico, whatever) and cut and paste what is needed from the template above into your template.

What's that you say?  Well, for starters you'll need to cut and paste everything before the first HTML tag above (<center>).  That's the code that declares variables and gets the data from the CGI script for you to use.  Then, wherever you want to insert a bit of HTML content (like an image, sound, or flash applet,) put it in like the example of the picture above:

<img src="[+ $trans->{'imageurl'} +]/[+ $card{'image'} +]">

Now there are two parts to this.  The [+ $trans->{'imageurl'} +] part gives the URL to the directory where your good stuff will be found.  The second part [+ $card{'image'} +] comes from the card template in the file card.conf.  The syntax of $card{'a name thingy'} allows you to access any of the 4 fields in the card.conf template.  In general, any of the variables listed below that you want to incorporate into your card can be accessed using the $trans->{'variable name'} syntax.  So you can incorporate the sender's email, recipient's name, etc. in this way.

Now repeat after me - I have no idea how this works!   This is NOT an introduction into how Penguin Greetings really works.  However, if you want to know, keep reading!  If you think you can get on without reading more - well, you've been warned!!


[Table of Contents]


Penguin Greetings Operational overview

Penguin Greetings is Perl CGI application that manages the creation, emailing, storing, and retrieving of HTML-based greeting cards.  Penguin Greetings uses two programs to do this: pgreet.pl.cgi and pgreetd.pl.  However, the content developer can do his/her work as if there was a single program operating to manage the cards.  As noted above, Penguin Greetings tries to remain in the background as much as possible while allowing the content developer the maximum artistic and technical freedom.

Still, a backend program cannot be completely invisible or it wouldn't do anything at all for the developer.  Penguin Greetings employs a Perl-based method for communicating with HTML content developers: Embperl (or  Mason as an alternative.)  Developers can either simply accept the conventions provided here and use their own content generation methods, or they can take advantage of the power of Embedding Perl in their pages by using Embperl directly.  The problem with using Embperl is that it looks - well - rather like Perl.  Developers who aren't a fan of Perl will be forced to "hold their noses" somewhat when getting data from the CGI application to their HTML pages.  For those who are comfortable with Perl though, Embperl offers many advantages for streamlining pages.

Penguin Greetings is a CGI application.  As such it is only run when the user clicks on a hyperlink or presses a submit button.  In between calls, information is stored in state files.  State is maintained for an hour (although this is configurable) so that users can move backwards and forwards without fear of losing their card in progress.  The communications model between Penguin Greetings and the content it serves is simple and robust.  Forms communicate with Penguin Greetings via standard CGI variables.  In return, Penguin Greetings provides data for users to embed in their forms using a simple model available within Embperl.  This gives the developer a way to accumulate the information needed to fill out a card of their own design using as many forms as are needed as shown below:


Penguin Greetings Data cycle

Penguin Greetings preserves all state variables from any given call to the next.  Developers can create as many variables as they need to create their card.  These variables can then be inserted into the next HTML page using the $trans->{'CGI variable name'} syntax shown above in the quick start.  As a result, developers can use a card creation cycle shown below:

Penguin Greetings card creation cycle
Penguin Greetings card creation cycle

A user coming to Penguin Greetings to create a card first needs to login into the system (if system is access restricted.)  This is the login phase.  The next phase is the back and forth with the user to collect all the information needed to send the card.  If the user could type the image name to use in their card, a single HTML form would work just fine.  However, in practice, users need to be guided in their selections.  The Penguin Greetings templates that are shipped with the install provide 3 templates to aid the user in selecting a card.  First, a user selects a card category: love, birthdays, etc.  Then, the user selects a card from that category.  Finally the user is presented with a form to enter the names, email addresses, and other information needed to complete the card.  Some systems may need more levels, other systems, less (such as the secondary ecard sites included with Penguin Greetings.)  Penguin Greetings can support any number of steps to creating the card and any number of templates can be called from any step.  Finally, there is the send phase, where the user can preview the card and send it.

In trying to design a web site that uses Penguin Greetings keep in mind that there are first two kinds of HTML templates which are completely different: there are the cards themselves and then the HTML forms to select and fill in a card (or retrieve and view a card.)  It isn't possible to design the forms to fill in the card until you have designed the cards first.  The simple card template shipped with the default Penguin Greetings web site only needs a picture selected and some text entered.  More complicated cards will require more support for the user.  Also, Penguin Greetings delivers cards as email (plain-text and HTML formatted email.)  There are templates associated with that as well although these are not templates that can afford to be very complicated.  Penguin Greetings permits HTML templates to be included within other HTML templates.  So that a preview and view template can simply include the card template that is also used to generate the HTML that is sent out as email.  Other common bits such as page headers and footers can also be included as a common bit of HTML stored in a single file.

Since version 0.8.8, Penguin Greetings supports secondary ecard sites.  Each site is essentially independent with a few unintrusive exceptions.  Sites need not use the same templates, content, or databases.  See the demonstration secondary sites now included with Penguin Greetings as examples.

[Table of Contents]

Penguin Greeting templates and Embperl


Penguin Greetings shares with its ancestor WebGrams a notion of HTML template files.  These template files are the same as standard HTML files except that they have embedded in them Perl expressions that are evaluated before they are sent to web browser.  In version 0.8.0 (actually 0.7.8) and above, Penguin Greetings moves beyond simply incorporating Perl variables by adopting the Embperl standard for embedding Perl expressions into HTML.  Version 0.9.9 also provides support for HTML::Mason for those who prefer that framework for embedded Perl (see below.)  This means that any Perl expressions can be incorporated into Penguin Greeting templates.  Penguin Greetings doesn't require users to be Perl programmers, but since the incorporation of Embperl, it certainly does help. It is now possible to use any Perl expressions in your Penguin Greetings templates.   It is possible to use Penguin Greetings without any background in Perl, but it will be very easy to make mistakes that will be hard to diagnose without some knowledge of Perl syntax.  Because Penguin Greetings (and this manual) were developed over years when only Embperl was supported, most of the information and examples are provided within the Embperl framework.  However, the transformation to Mason is quite easy.  See the Savoring the sights of Seattle (PgSeattle) secondary ecard site as an example of an Mason implementation of a Penguin Greetings ecard site.

As an example of embedding Perl, if you wish to have the time when a user accesses your greeting card system displayed at some point in your HTML you can do this with this simple expression:

[+ localtime() +]

Embperl uses the [+ +] syntax to wrap any Perl code you wish to include in your HTML page.  Embperl evaluate the expression and substitute the result into the HTML document before sending it (via the Penguin Greetings CGI script) to the web browser.  The expression localtime() is a built-in Perl function that called in this way returns a string similar to this: Fri Mar 21 19:40:36 PST 2003.  If you don't like the date and time formatted in this way ... don't worry, in Perl - you can change it!

The HTML for cards used on the demonstration system are generated using the template shown above for the quick-start example.  For clarity, the Embperl code has been highlighted in bold to set it apart from the HTML.  There are three additional examples of Embperl that are used in this example: [# #] is a comment block, [* *] is a global setting block, and [- -] is a block of Perl code that needs to be evaluated does not produce any output that should be inserted into the HTML page that will be displayed by the browser.  Most Penguin Greetings developers will probably only need the [+ +] block and the [# #] block for comments.   For more details on Embperl syntax, see the Embperl website.  Note that the header in this example:  [- ...   $trans = shift(@param) ... -] is used by Penguin Greetings to move the HTML variables into template page.  This code is required for any HTML template page used by this application.  Another code example that this time expands into plain text is the template used for the text email message shown below:

[* $ENV{'optRawInput'} = 16; *]
[*  $escmode = 0; *]
[-
  # Retrieve parameters from Penguin Greetings script (pgreet.pl.cgi)
  $trans = shift(@param);
 -]
Dear [+ $trans->{'recipient_name'} +],

[+ $trans->{'sender_name'} +] has sent you a Penguin Greeting!  If your email reader doesn't
support email with images, you can view your Penguin Greeting on the world wide
web.  Just point your browser to:

[+ $trans->{'URL_short_cut'} +]

and, if needed,  enter the following information:

Card ID:      [+ $trans->{'number'} +]
Password:    [+ $trans->{'password'} +]

The text of the message from [+ $trans->{'sender_name'} +] is provided below:
-----------------------------------------------------------------

[+ $trans->{'message'} +]

-----------------------------------------------------------------
We hope you enjoy your Penguin Greeting!


Penguin Greetings' HTML page variables are accessed by looking up the variable in the hash reference $trans.  So to return the value of the cgiurl, the expression is: $trans->{'cgiurl'} and to insert that text into your HTML page the required Embperl expression is [+ $trans->{'cgiurl'} +].  Note that while there is a space between each + in the [+ +] square braces, those spaces will not appear in your resulting HTML.  If your imageurl is http://www.myserver.com/images, and pic contains my_picture.gif then the following line:

<img src="[+ $trans->{'imageurl'} +]/[+ $trans->{'pic'} +]">

will produce the following pure HTML:

<img src="http://www.myserver.com/images/my_picture.gif">



[Table of Contents]

Card configuration file and configuration parameter access.


As of Penguin Greetings 0.8.0, there is separate configuration file for card data and each card is represented by a symbolic name.  The configuration file is fairly straightforward to use, but for completeness, an abbreviated example of this file is provided below:

# File: cards.conf
######################################################################
#             Greeting card configuration file for
#
#                ** PENGUIN GREETINGS (pgreet) **
#
# A Perl CGI-based web card application for LINUX and probably any
# other UNIX system supporting standard Perl extensions.
#
#     Edouard Lagache, elagache@canebas.org, April 2003
#
#
# The pgreet system uses the Perl Config::General module for
# reading in configuration file information.  The file format
# is the same as for the Apache web server.  The general
# configuration module contains information for both the
# CGI script and the system daemon.  These are kept in
# separate categories for simplicity of management.
#
######################################################################

# Card category definitions:

<category Encouragement>
    caption = "Cards for encouragement"
    cards = Barrel_of_cheer
    cards = Flower_in_rocks
</category>



# Categories to display at this time.  Provide an entry for each category
# you which to have displayed during current operation.  To change order
# change order in this file.

categories = Encouragement
# categories = St_Patrick
# categories = New_Year

# Card definitions:


# 11
<card Barrel_of_cheer>
    caption = "A barrel of cheerful flowers"
    template = "picture_frame_card.tpl.html"
    image = "Barrel_of_cheer.jpg"
    thumb = "Barrel_of_cheer.thb.jpg"
</card>

# 14
<card Flower_in_rocks>
    caption = "Californian Poppy in rocky ground"
    template = "picture_frame_card.tpl.html"
    image = "Flower_in_rocks.jpg"
    thumb = "Flower_in_rocks.thb.jpg"
</card>


# Array of card names to enable transition and perhaps otherwise useful.
cards = Barrel_of_cheer
cards = Flower_in_rocks

What is more important and less obvious is how to access data from this file in templates.  Penguin Greetings uses the Perl module Config::General to read in configuration files.  Config::General converts this file into a Perl hash data structure that can be easily accessed by standard Perl expressions.  Indeed the above file is converted into the following data structure.

%card_hash = (
                 'card' => {
                            'Flower_in_rocks' => {
                                 'template' => 'picture_frame_card.tpl.html',
                                 'caption' => 'Californian Poppy in rocky ground',
                                 'thumb' => 'Flower_in_rocks.thb.jpg',
                                 'image' => 'Flower_in_rocks.jpg'
                               },
                            'Barrel_of_cheer' => {
                                 'template' => 'picture_frame_card.tpl.html',
                                 'caption' => 'A barrel of cheerful flowers',
                                 'thumb' => 'Barrel_of_cheer.thb.jpg',
                                 'image' => 'Barrel_of_cheer.jpg'
                               },

                           },

                 'cards' => [
                             'Barrel_of_cheer',
                             'Flower_in_rocks',
                            ],
                 'category' => {
                                'Encouragement' => {
                                    'caption' => 'Cards for encouragement',
                                    'cards' => [
                                                'Barrel_of_cheer',
                                                'Flower_in_rocks'
                                               ]
                                                   },

                               },
                 'categories' => [
                                  'Encouragement',
                                 ]
                );


Perl programmers will immediately recognize the various hashes that are produced by the configuration file.  More importantly, the Perl hash %card_hash that is shown above is the same hash that is defined at the top of all the all HTML templates with the statement: %card_hash = %{$trans->{'card_hash'}};.  The table above provides a rough road map to get at elements of the configuration file.  There is an array reference of card categories that can be accessed by: $card_hash{'categories'}.  To get a plain array, just dereference it like this: @{$card_hash{'categories'}} .  The image for the card Barrel_of_cheer requires two levels of lookup.  It makes more sense if you imagine the process as a database lookup.  You are looking for an item in the configuration hash.  It is a card first, it has the name Barrel_of_cheer.  So the Perl expression to get you that card is: $card_hash{'card'}->{'Barrel_of_cheer}.  However, that only gets you to the card, not the image.  If we are at the card, we need the image.  So the final expression is: $card_hash{'card'}->{'Barrel_of_cheer'}->{'image'}.  Each of these lookup items are in bold in the table above.  Using these lookup capabilities, it is possible to get to any piece of information in the configuration file.

There is a special configuration type called Force_to_array that isn't really a configuration variable at all, but a declarative to force values to always be arrays in order to avoid complicated Embperl loops.  This declarative is discussed below.  The card configuration files for secondary ecard sites are completely independent of any information in the primary ecard site, so they must be complete and entirely self-sufficient.  Developers are free to use an entirely different arrangement in each site.

IMPORTANT:  The example here is entirely arbitrary.  In order to implement your own cards you may need other information in your card configuration file.  Penguin Greetings does not assume ANYTHING about the contents of this file.  The configuration structure you create here is only used by your own ecard and web page templates.  Developers should not feel bound by the structures and conventions shown in the demonstration sites shipped with Penguin GreetingsPenguin Greetings in far more flexible than that.  The downside of this is that developers must provide their own tools to deal with their own data-structures.  For example the utility  CardConfTest.pl included with Penguin Greetings only works with the demonstration sites included with Penguin Greetings

[Table of Contents]

Penguin Greetings parameters and CGI variables

Content developers can access any CGI script variable that they define in a template via a form or in a URL get command by the name they assign to it.  All CGI variables can be accessed using the $tran hash reference.  So to access a variable named myvar the Perl expression would be $trans->{'myvar'}.  The only caveat is that name collisions will probably result in unexpected problems.  Penguin Greetings uses CGI.pm to access CGI variables and CGI.pm supports multiple values.  In addition, some of the variables from the configuration files pgreet.conf and card.conf are passed by their configuration file names.
At the moment, the following variables are passed to the HTML templates from the CGI script:

Penguin Greetings' Variable
Variable contents
cgiurl URL to cgi-bin directory on server
imageurl URL to image directory on server
card_hash
Hash reference of the configuration file 'card.conf'
message Text of message to be included in card
html_message
The text of the message to be included in the card formatted in HTML
varstring String of hidden variables to be included in a URL Get request
hiddenfields String of hidden variables formatted as hidden fields of a CGI form
sender_name Name of sender of card
sender_email Email of card sender
recipient_name Name of Recipient
recipient_email Email of Recipient
number Card login (old number in WebGrams)
password Password needed to retrieve card.
login Login of Penguin Greetings user on server.
UserPassword Password of Penguin Greetings user on server.
URL_short_cut URL with card login and password already included for quick access.
SpeedyCGI Boolean that if true indicates that pgreet.pl.scgi is indeed running as a SpeedyCGI persistent server.  The two variables below are only defined this this variable is set to true.
StartTime The UNIX time at which the persistent (SpeedyCGI) process started.  This can be converted using the Localtime function or what-not.
Invocations The number of CGI requests processed by is particular SpeedyCGI process.
BackVarStr A set of state variables encoded in a CGI "GET" request style (ampersands and var=value format) that if invoked in a call to Penguin Greetings will take the user to the previous state of creating their ecard.
BackHiddenFields A set of state variables encoded as "hidden Variables" that if included in a form "POST" request, would take the user to the previous state of creating their ecard.
VERSION
The version number of the CGI application (pgreet.pl.(s)cgi).

In addition, Penguin Greetings expects CGI form variables to be defined for some of its templates.  The recognized CGI variables are:

CGI Variable
Purpose
state_file
Name of state file where user's previous entries are stored on the server
action
Action that pgreet.pl.cgi should do on its next call.  See discussion on action below.
next_template
Name of the next template to be displayed by the CGI script.  Do not include a filename extension, the default extension defined in pgreet.conf is appended to the filename.
message
Text of message
sender_name
Name of sender
sender_email
Email of sender
recipient_name Name of recipient (primary)
recipient_name-2 to 5 Names of any supplemental recipients (up to 4 additional)
recipient_email Email of recipient (primary)
recipient_email-2 to 5 Emails of any supplemental recipients (up to 4 additional)
code
access code for card (old WebGrams number)
password
access password for card
card The name of the card selected
login
User login for accessing Penguin Greetings on this server
UserPassword
User password for accessing Penguin Greetings on this server
schedule
Binary flag - should card be scheduled to emailing later
day
Day to email card later
month
Month to email card later
year
Year to email card later
copy_for_you
Binary flag - do you want a copy of ecard emailed to sender?
site
Name of a secondary ecard site if your server has more than one ecard site running at the same time.
subject
Contains text of a user-supplied subject for the email message.  The subject text will be appended after the identifying tag [pgreet].  If the user does not supply a subject line, the line Penguin Greeting from user name will be used.

Penguin Greetings has a number of actions that can be performed.  This system was outlined in the operational overview.  By specifying one of the actions below and the next template to be displayed, just about any card generation website can be put together.  The available actions are:

Action Notes
<none>
This is the screen that will be displayed if a user accesses Penguin Greetings without any action specified.
build
These are the templates to select and outfit a card.  You can have any number of build stages.  Each time, the CGI script will collect the variables from the previous stage, and output the template specified by the variable next_template.
login
Display login and password page for installations of Penguin Greetings were only authorized users may create cards.
preview
State to review the resulting card and schedule when it will be sent.
send
Confirmation that a Penguin Greeting has been sent.  A link from this page can be added to go back to build state so to allow users to send multiple cards during the same session.
view
State and template for a user who has already received a Penguin Greeting and wants to view the card via the web site.   This is the page that this also displayed if URL_short_cut is enabled.


Versions prior to 0.7.8 of Penguin Greetings provided a  Server Side Include pseudo-declaration.  This has been eliminated in favor of the Execute function provided directly by Embperl.  It is possible to include templates within templates.  The only caveat is that the $trans hash reference isn't automatically passed to the files that are included, therefore the syntax for using Execute with the file my_file.tpl.html is:

[- Execute("myfile.tpl.html", $trans) -]

or you can use the long form:

 [- Execute ({inputfile =>"myfile.tpl.html",
              param => [$trans]
             }
            )
 -]



[Table of Contents]

Using Embperl to simplify content development

It is possible to use nothing more of Embperl to create your website than the facility to move variables from Penguin Greetings into your web pages.  For those who are comfortable with Perl, Embperl provides a powerful development environment for simplifying your web pages and automating the generation of similar HTML.

Programmers will recognize that in the data-structures of the cards and categories in cards.conf are some useful abstractions to simplify the creation of HTML.  In the demonstration web site shipped with Penguin Greetings, a single card thumbnail is shown with the following little snippet of Embperl and HTML:

 <tr>
      <td style="text-align: center; vertical-align: middle;">

              [# The URL will be the general URL above + card selected #]
         <a href="[+ $script_URL +]&card=[+ $card +]">
            [# The image is the image URL + the image name #]
            <img src="[+ $trans->{'imageurl'} +]/[+ $card_data{$card}->{'thumb'} +]"
            >
         </a>
      </td>
    </tr>


There is a whole table with every image within a given category displayed one after the other.  The list of cards in a category is  an array within the category structure.  Following the example in the section on the cards.conf configuration, to get the list of cards in the category Encouragement the following expression will do: @{$card_hash{'category'}->{'Encouragement'}->{'cards'}}.  If you have a list of items in Perl, you can perform a set of common operations with the foreach loop.  Embperl doesn't let down Perl fans, it has its own version of the foreach loop.  The syntax is:

[$ foreach $myvar (@myarray) $]
<my HTML stuff here> ....
[$ endforeach $]

See Embperl documentation for full details.

The demonstration web site displays a sample thumbnail image for each category and then once a user chooses a category, it displays all the thumbnail images for that category.  An old version of the page that does that (card.tpl.html) is shown below (the current version of this template uses Embperl::Object - see below.)

<HTML>
<HEAD>
   <TITLE>Penguin Greetings - Select a picture</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">

[* $ENV{'optRawInput'} = 16; *]
[*  $escmode = 0; *]
[$ var $trans $script_URL %card_hash %category_hash @cards_list %card_data
       $card $image_ref
 $]
[-
  # Retrieve parameters from Penguin Greetings script (pgreet.pl.cgi)
  $trans = shift(@param);

  # Get the contents of card.conf into a single hash.
  %card_hash = %{$trans->{'card_hash'}};

  # Get the category hash
  %category_hash = %{$card_hash{'category'}};

  # Get the hash of card data
  %card_data = %{$card_hash{'card'}};

  # Get the list of all the card names in the category chosen.
  @cards_list =  @{$category_hash{$trans->{'category'}}->{'cards'}};


  # Build up pieces of URLs to simplify represention.
  $script_URL = join('', $trans->{'cgiurl'}, "/",
                         $trans->{'cgi_script'}, "?action=build&",
                         "next_template=text&",
                         $trans->{'varstring'}
                    );

 -]


<CENTER>
<table cellpadding="2" cellspacing="2" border="0"
 style="text-align: left; width: 640px;">
  <tbody>
    <tr>
      <td style="vertical-align: top;">

      <td style="vertical-align: top;">
      <img src="[+ $trans->{'imageurl'} +]/pgreet_CGI_banner.jpg"
           align="center">
     <img src="[+ $trans->{'imageurl'} +]/pgreet_status_bar-2.jpg"
          align="left"><br>
<center>
<FONT FACE="Arial"><b><small>Please select a picture for your
Penguin Greeting below.</b></small></FONT></CENTER>
<br><br><hr>
<CENTER>

<H3>[+ $category_hash{$trans->{'category'}}->{'caption'}  +]</H3><br>

<table cellpadding="2" cellspacing="2" border="0"
       style="text-align: left; width: 600px;">
  <tbody>

   [# Loop through every card in the category #]
   [$ foreach $card (@cards_list) $]
    <tr>
      <td style="text-align: center; vertical-align: middle;">
        
        [# The URL will be the general URL above + card selected #]
         <a href="[+ $script_URL +]&card=[+ $card +]">
           [# The image is the image URL + the image name #]
            <img src="[+ $trans->{'imageurl'} +]/[+ $card_data{$card}->{'thumb'} +]"
            >
         </a>
      </td>
    </tr>
    [$ endforeach $]

  </tbody>
</table>
</CENTER>
      </td>
    </tr>
  </tbody>
</table>
</center>
[- Execute($trans->{'templatedir'} . "/pgreet_credit.tpl.html", $trans) -]

</BODY>
</HTML>

Using Embperl greatly simplifies the HTML in this example.  Not only does it eliminate making a separate table entry for each card image in an given category, it avoids the need of having a separate file for each category.  Each category is dynamically generated on the fly.  Without using Embperl, this would be difficult to do and essentially impossible to do with the direct integration to the Perl data-structures that are used in the configuration files.  Using Embperl, it is possible to make very compact templates that still expand to elaborate HTML pages.

Unfortunately, there is one wrinkle in using Embperl loops with the data coming from the tool used to read the configuration file Config::General.  There is no explicit mechanism in Config::General to indicate when something is a single value of a list of something.   Instead, if there is only one of something, it is assumed to be a single value until a second one shows up and an array is created for the pair.  This may not seem like a problem until one tries to come up with Embperl code to loop through the values in your configuration file.  Consider what will happen in the foreach loop above if there is category with just one card in it.  If there is just one value, there won't be an array to loop over and Embperl will crash as the attempt to define the array @cards_list.  Of course, this problem can be solved by an explicit programming test, but such tests have to be placed in every template and protect every loop.  This could get very clumsy.

To simplify matters, there is a pseudo configuration type: Force_to_array.  An example is shown below from the Camel Collection secondary ecard site:

# Request that all card entries be array references.
<category Force_to_array>
    fields = cards
</category>

# 01
<category Hello>
    caption = "Hello and general interest cards"
    cards = Camel_racers_unite
    cards = Camel_fun_yet
</category>

# 02
<category Love>
    caption = "Cards for Love and Romance"
    cards = Sweet_camel_two
</category>

By using the pseudo-configuration type Force_to_array in the configuration type category, special processing has been requested of every item that is of the type categoryPenguin Greetings will go through every item that is of category and look for fields named cards.  If anything is returned from Config::General as a single value (scalar), Penguin Greetings will automatically make it into an array of one item.  In the above example, the category hello has two cards Camel_racers_unite and Camel_fun_yet.  These would have been put into an array reference by Config::General.  However, the category Love has only one card Sweet_camel_two.  The Force_to_array declarative will replace that single value with an array reference containing that one items.  It isn't at all necessary to use the Force_to_array declarative, but it can make Embperl coding much simpler.

This is just one example of what is possible using Embperl.  For more information, first, see the Embperl web site and documentation.  Also look at the templates included in the Penguin Greetings demonstration web site for additional ways to use Embperl in your web page templates.