NAME
PApp - multi-page-state-preserving web applications
SYNOPSIS
* this module is at a very early stage of development and *
* requires quite an elaborate setup (see the INSTALL file) *
* documentation will certainly be improved *
DESCRIPTION
PApp is a complete solution for developing multi-page web applications
that preserve state *across* page views. It also tracks user id's,
supports a user access system and provides many utility functions (html,
sql...). You do not need (and should not use) the CGI module.
Advantages:
* Speed. PApp isn't much slower than a hand-coded mod_perl handler, and
this is only due to the extra database request to fetch and restore
state, which typically you would do anyway. To the contrary: a
non-trivial Apache::Registry page is slower than the equivalent PApp
application (or much, much more complicated);
* Embedded Perl. You can freely embed perl into your documents. In fact,
You can do things like these:
Names and amounts
<:
my $st = sql_exec "select name, amount from ...",
[\my($name, $amount];
while ($st->fetch) {?>
Name: $name, Amount: $amount
<:}
:>
That is, mixing html and perl at statement boundaries.
* State-preserving: The global hash `%S' is automaticaly preserved
during the session. Everything you save there will be available in any
subsequent pages that the user accesses.
* XML. PApp-applications are written in XML. While this is no advantage
in itself, it means that it uses a standardized file format that can
easily be extended. PApp comes with a DTD and a vim syntax file, even ;)
* Easy internationalization. I18n has never been that easy: just mark
you strings with __"string", either in html or in the perl source. The
"poedit"-demo-application enables editing of the strings on-line, so
translaters need not touch any text files and can work diretcly via the
web.
Feature-Rich. PApp comes with a *lot* of small-but-nice-to-have
functionality.
Disadvantages:
* Unfinished Interface: To admit it, this module is young and many
features have a kind-of-unfinished interface. PApp will certainly be
changed and improved to accomodate new features (like CGI-only
operation).
* No documentation. Especially tutorials are missing, so you are most
probably on your own.
* Perl5.6 is required. While not originally an disadvantage in my eyes,
Randal Schwartz asked me to provide some explanation on why this is so:
"As for an explanation, I require perl5.6 because I require a whole
lot of features of 5.6 (e.g. DB.pm, utf-8 support, "our", bugfixes,
3-argument open, regex improvements, probably many others,
especially changes on the XS level). In the future it will likely
require weak references, filehandle autovivification, the XSLoader
for extra speed in rare circumstances... I don't want to backport
this to older versions ;)"
Be advised that, IF YOU WANT TO USE THIS MODULE, PELASE DROP THE AUTHOR
(Marc Lehmann ) A MAIL. HE WILL HELP YOU GETTING STARTED.
To get a quick start, read the bench.papp module, the dbedit.papp
module, the cluster.papp module and the papp.dtd description of the papp
file format.
GLOBAL VARIABLES
Some global variables are free to use and even free to change (yes, we
still are about speed, not abstraction). In addition to these variables,
the globs `*state' and `*S' (and in future versions `*L') are reserved.
This means that you cannot define a scalar, sub, hash, filehandle or
whatsoever with these names.
$request [read-only]
The Apache request object (the Apache manpage), the same as returned
by `Apache-'request>.
%state [read-write, persistent]
A system-global hash that can be used for almost any purpose, such
as saving (global) preferences values. All keys with prefix `papp'
are reserved for use by this module. Everything else is yours.
%S [read-write, persistent]
Similar to `%state', but is local to the current application. Input
arguments prefixed with a dash end up here.
%L [read-write, persistent]
(NYI)
%A [read-write, input only]
A global hash that contains the arguments to the current module.
Arguments to the module can be given to surl or any other function
that calls it, by prefixing parameter names with a minus sign (i.e.
"-switch").
%P [read-write, input only]
Similar to `%A', but it instead contains the parameters from forms
submitted via GET or POST (`see parse_multipart_form', however).
Everything in this hash is insecure by nature and must should be
used carefully.
$userid [read-only]
The current userid. User-Id's are automatically assigned to every
incoming connection, you are encouraged to use them for your own
user-databases, but you mustn't trust them.
$pmod (a hash-ref) [read-only]
The current module (don't ask). The only user-accessible keys are:
lang a hash-ref enumerating the available languages, values are
either language I or references to another language-id.
config the argument to the Coption given to C.
$location [read-only]
The location value from `mount'.
$module [read-only]
The current module *within* the application.
FUNCTIONS/METHODS
PApp->search_path(path...);
Add a directory in where to search for included/imported/"module'd"
files.
PApp->configure(name => value...);
pappdb The (mysql) database to use as papp-database
(default "DBI:mysql:papp")
pappdb_user The username when connecting to the database
pappdb_pass The password when connecting to the database
cipherkey The Twofish-Key to use (16 binary bytes),
BIG SECURITY PROBLEM if not set!
(you can use 'mcookie' from util-linux twice to generate one)
cookie_reset delay in seconds after which papp tries to
re-set the cookie (default: one day)
cookie_expires time in seconds after which a cookie shall expire
(default: one year)
The following configuration values are used mainly for development:
checkdeps when set, papp will check the .papp file dates for
every request (slow!!) and will reload the app when necessary.
delayed do not compile applications at server startup, only on first
access. This greatly increases memory consumption but ensures
that the httpd startup works and is faster.
PApp->mount(location => 'uri', src => 'file.app', ... );
location[*] The URI the application is moutned under, must start with "/"
src[*] The .papp-file to mount there
config Will be available to the module as $pmod->{config}
delayed see Cconfigure>.
[*] required attributes
dprintf "format", value... dprint value...
Work just like print/printf, except that the output is queued for
later use by the `debugbox' function.
echo value[, value...]
Works just like the `print' function, except that it is faster for
generating output.
capture { code/macros/html }
Captures the output of "code/macros/perl" and returns it, instead of
sending it to the browser. This is more powerful than it sounds, for
example, this works:
<:
my $output = capture {
print "of course, this is easy\n";
echo "this as well";
:>
Yes, this is captured as well!
<:&this_works:>
$captureme:>
<:
}; # close the capture
:>
reference_url $fullurl
Return a url suitable for external referencing of the current page.
If `$fullurl' is given, a full url (including a protocol specifier)
is generated. Otherwise a partial uri is returned (without
http://host:port/).
This is only a bona-fide attempt: The current module must support
starting a new session and only "import"-variables and input
parameters are preserved.
$url = surl ["module"], arg => value, ...
`surl' is one of the most often used functions to create urls. The
first argument is the name of a module that the url should refer to.
If it is missing the url will refer to the current module.
The remaining arguments are parameters that are passed to the new
module. Unlike GET or POST-requests, these parameters are directly
passed into the `%S'-hash (unless prefixed with a dash), i.e. you
can use this to alter state values when the url is activated. This
data is transfered in a secure way and can be quite large (it will
not go over the wire).
When a parameter name is prefixed with a minus-sign, the value will
end up in the (non-persistent) `%A'-hash instead (for "one-shot"
arguments).
$ahref = slink contents,[ module,] arg => value, ...
This is just "alink shift, &url", that is, it returns a link with
the given contants, and a url created by `surl' (see above). For
example, to create a link to the view_game module for a given game,
do this:
slink "Click me to view game #$gamenr", "view_game", gamenr => $gamenr :>
The view_game module can access the game number as $S{gamenr}.
$ahref = sublink [sublink-def], content,[ module,] arg => value, ...
retlink_p
returl
retlink
*FIXME* (see also `current_locals')
%locals = current_locals
Return the current locals (defined as "local" in a state element) as
key => value pairs. Useful for `sublink's:
sublink [current_locals], "Log me in!", "login" :>
This will create a link to the login-module. In that module, you
should provide a link back to the current page with:
retlink "Return to the caller" :>
sform [module, ]arg => value, ...
cform [module, ]arg => value, ...
multipart_form [module, ]arg => value, ...
endform
Forms Support
These functions return a -Tag. `sform' ("simple
form") takes the same arguments as `surl' and return a -Tag, and *must* be used to close
forms created via `sform'/`cform'/`multipart_form'. It can take
additional key => value argument-pairs (just like the
*form-functions) and must be called in a paired way.
parse_multipart_form \&callback;
Parses the form data that was encoded using the
"multipart/form-data" format. For every parameter, the callback will
be called with four arguments: Handle, Name, Content-Type,
Content-Disposition (the latter is a hash-ref, with all keys
lowercased).
If the callback returns true, the remaining parameter-data (if any)
is skipped, and the next parameter is read. If the callback returns
false, the current parameter will be read and put into the `%P'
hash.
The Handle-object given to the callback function is actually an
object of type PApp::FormBuffer (see the PApp::FormBuffer manpage).
It will not allow you to read more data than you are supposed to.
Also, remember that the `READ'-Method will return a trailing CRLF
even for data-files.
redirect url
internal_redirect url
Immediately redirect to the given url. *These functions do not
return!*. `redirect_url' creates a http-302 (Page Moved) response,
changing the url the browser sees (and displays).
`internal_redirect' redirects the request internally (in the
web-server), which is faster, but the browser will not see the url
change.
abort_to surl-args
Similar to `internal_redirect', but works the arguments through
`surl'. This is an easy way to switch to another module/webpage as a
kind of exception mechanism. For example, I often use constructs
like these:
my ($name, ...) = sql_fetch "select ... from game where id = ", $S{gameid};
abort_to "games_overview" unless defined $name;
This is used in the module showing game details. If it doesn't find
the game it just aborts to the overview page with the list of games.
debugbox
Create a small table with a single link "[switch debug mode ON]".
Following that link will enable debugigng mode, reload the current
page and display much more information (%state, %P, %$pmod and the
request parameters). Useful for development. Combined with the admin
package (the admin entry in the macro manpage), you can do nice
things like this in your page:
#if admin_p
<: debugbox :>
#endif
insert_module "module"
Switch permanently module "module". It's output is inserted at the
point of the call to switch_module.
reload_p
Return the count of reloads, i.e. the number of times this page was
reloaded (which means the session was forked).
This is a relatively costly operation (a database access), so do not
do it by default, but only when you need it.
switch_userid $newuserid
Switch the current session to a new userid. This is useful, for
example, when you do your own user accounting and want a user to
log-in. The new userid must exist, or bad things will happen.
SEE ALSO
The `macro/admin'-package on the distribution, the demo-applications
(.papp-files).
AUTHOR
Marc Lehmann
http://www.goof.com/pcg/marc/