NAME
Merge - Embedded HTML/SQL/Perl system by Raz Information Systems.
INSTALLATION
After installing the package, activate mergecreateinstance to create an
instance in your cgi-bin (or modperl) directory. Follow the directions
you get from mergecreateinstance in order to configure your web server.
You must edit the merge.conf created for you.
SYNOPSIS
<$RQ.'SELECT * FROM customers'>
<$RLOOP>
<$RVAR.name> owes <$RVAR.debt>
$RLOOP>
DESCRIPTION
Merge is an embedded HTML/Perl/SQL tool used to create dynamic web
content. All Merge pages are refered to by
cgi-bin-dir/merge.pl?template=file.html although on CGI mode you can
define merge.pl as an handler with the Action directive in Apache.
Using merge.pl under Apache::Registry will utilize Perl's built-in
caching to cache pages using the do command.
Merge uses a configuration file to retrieve information about database
connectivity and debugging. It has an embedded debugging tool and
on-line configuration. To turn that option on, set DEVELOPMENT to 1 in
the configuration file. Don't forget to set it off before deployment.
Alternate configuration files can appear in /etc/merge.conf and
$HOME/.merge.
FILES
B Main script, usually a symbolic link to each instance.
B Configuration, unique per each instance.
B<$PREFIX/share/merge/private> Internal scripts.
B<$PREFIX/bin/merge.cgi> Main script, central.
B<$PREFIX/bin/merge.conf> Template for configuration files.
B<$PREFIX/bin/mergecreateinstance> Instance creating script.
AUTHOR
* Initial design by Oded Resnik, oded@raz.co.il.
* Versions 1 and 2 written by Roi Illouz, roi@raz.co.il.
* Version 3 written by Ariel Brosh, ariel@raz.co.il.
* Toolbox written by Eial Solodki.
COPYRIGHT
Copyright (c) 1999, 2000, 2001, 2002 Raz Information Systems Ltd.
http://www.raz.co.il
This package is distributed under the same terms as Perl itself, see the
Artistic License on Perl's home page.
SEE ALSO
perl(1), the HTML::Merge::Tags manpage, the HTML::Merge::Ext manpage.
NAME
Merge tags - Tag summary for Merge.
DATABASE TAGS
* <$RDB='[Database type:]Database name[:Host][,User[,Password]]'>
Connect to alternative database. Defaults are taken from the
configuration file. If two parameters are given in the first
token, the database type takes precedence.
* <$RS='SQL statement'>
Perform a non query SQL statement.
* <$RQ='SELECT SQL statement'>
Perform a query. First row of result is immediately
available. Query can be iterated with <$RLOOP> tags.
* <$RERUN>
Reperforms the query.
* <$RLOOP[.LIMIT=number]>
$RLOOP>
<$REND>
Performs a loop over fetched query elements. Last row
remains valid after iteration. Iteration number can be
limited.
* <$RSQL.variable>
Derferences a column from the current fetch.
* <$RINDEX>
Substitues for the number of the row currently fetched.
* <$RFETCH>
Fetches another row. Increments the index.
* <$RSTATE>
Returns the SQL state of the last statement.
* <$REMPTY>
Returns a boolean value of whether the last query yielded an
empty set.
* <$RDISCONNECT>
Destroy an engine. This is used if the DB_DATABASE
configuration variable has been changed using the <$RCFGSET>
tag to recreate the engine with the new parameters.
FLOW TAGS
* <$RITERATION.LIMIT=number>
$RITERATION>
Performs a counted loop.
* <$RIF.'perl code'>
<$RELSE> (optional)
<$REND_IF>
$RIF>
$RELSIF.'perl code'>
Perform the code if the perl code evaluates to true.
* <$RWHILE.'perl code'>
$RWHILE>
<$REND_WHILE>
Perform a while loop.
* <$RBREAK>
Break out of a loop.
* <$RCONT>
Jump to the next iteration of the loop.
* <$RCOUNT.variable=from:to[,step]>
$RCOUNT>
Perform a classic variable iteration loop. All parameters
are mandatory.
* <$REXIT>
Exit a template in the middle.
* <$RENUMREQ.iterator variable=value variable>
Iterate over all request parameters; each time having the
first variable contain the parameter name and the second
contain the value.
* <$RENUMQUERY.iterator variable=value variable>
Iterate over all the columns of a query result. each time
having the first variable contain the column name and the
second contain the data.
FUNCTIONAL TAGS
* <$RPIC.picture type(instruction set).'string'>
<$RPIC.F(char).'string'>
Replace all white spaces by the given char. e.g.,
<$RPIC.F(+).'Banana, a yellow energy bomb'> will yield:
Banana,+a+yellow+energy+bomb and so on.
<$RPIC.R(find=replace, ...).'string'>
Replace tuples of string-to-find/string-to-replace in the
given string. e.g., <$RPIC.R('na'='ta').'Banana'> will yield
Batata and so on.
<$RPIC.N(width.fraction positions).'number'>
Left space pad the number, with a fixed number of decimal
places.
<$RPIC.N(0).'number'>
Left zero pad the number, with a fixed number of decimal
places.
(Hint, the instruction is equal to *printf*ing with
%stringf)
<$RPIC.NZ().'number'>
Substitute a blank for zero. (Mnemonic: zero suppress)
<$RPIC.NF().'number'>
After formatting the number, add commas.
* <$RDECIDE.'perl code'?'string':'string'>
Evaluates the code. If true, yields the first string,
otherwise the second.
* <$RMAIL.'From address','To address'[,'Subject']>
$RMAIL>
Send email, utilizing SMTP connection to localhost.
* <$RPERL>
$RPERL>
Embed perl code. print() may be used.
* <$RPERL.A>
<$RPERL.B>
<$RPERL.C>
Documentation soon.
SOURCE TAGS
* <$REM.'string'>
Add a server side comment.
* <$RTRACE.'string'>
Send a string to the log file.
* <$RINCLUDE.'template name'>
Include a template in compile time.
* <$RWEBINCLUDE.'url'>
Include an external web page in run time.
* <$RSOURCE.'template'>
$RSOURCE>
Generate an Anchor for a source view for a template. e.g,
<$RSOURCE.'<$RTEMPLATE>'>Click here to view the source for
this template$RSOURCE>
VARIABLE TAGS
* <$RVAR.variable>
Dereferences a local variable, or a CGi variable.
(Precedence to the former).
* <$RSET.variable='perl code'>
Set a variable to the result of a perl code segment. CGI
variables may be overwritten.
* <$RINC.variable>
* <$RINC.variable+number>
<$RINC.variable-number>
Modify a variable.
* <$RPSET.variable='perl code'>
<$RPGET.variable>
Store and retrive session variables. Must be configured in
the configuration file manually.
* <$RPIMPORT.variable>
Copy a persistent variable to a local variable, for faster
retrieving. Memory variables work much faster than session
variables.
* <$RPEXPORT.variable>
Copy a regular variable to a persistent variable of the same
name.
* <$RPCLEAR>
Erases all session variables.
* <$RCFG.variable>
Retrieve a variable from Merge configuration.
* <$RCFGSET.variable='perl code'>
Forge a temporary value instead of a configuration variable.
Does NOT change the configuration file!
* <$RCOOKIE.name>
Retrieve a cookie.
* <$RCOOKIESET.name='perl expression'>
<$RCOOKIESET.name='perl expression',minutes>
<$RCOOKIESET.name='perl expression',non numeric>
Set a cookie using a HTTP-EQUIV HTML tag. The
notations are used for setting a permanent cookie, a cookie
with an expire date, and a temporary cookie that will
disappear when the browser exits.
SECURITY TAGS
These tags are impleneted only if the merge database exists.
IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT
IMPORTANT These tags are to be used with the Merge security
backend which is not written yet. IMPORTANT IMPORTANT IMPORTANT
IMPORTANT IMPORTANT IMPORTANT IMPORTANT
* <$RLOGIN.'user','password'>
Logs in. Tag outputs a boolean value to notify if login was
successful or failed.
* <$RAUTH.'realm'>
Check if the user has permission to a specific realm/key.
* <$RCHPASS.'new password'>
Change password for the logged in user.
* <$RADDUSER.'user','password'>
Add a new user. Use with CAUTION! Any user running the page
could create a user with this tag. If Merge is running on a
user shell machine, configuration and templates should be
readable to the web server but not world readable! Pages
using <$RADDUSER> *must* be protected.
* <$RDELUSER.'user'>
Remove a user.
* <$RJOIN.'user','group'>
<$RPART.'user','group'>
Add a user to a group and remove a user from a group,
accordingly.
* <$RGRANT.U.'user','realm'>
<$RGRANT.G.'group','realm'>
Grant a permission over a realm to a group or a user.
* <$REVOKE.U.'user','realm'>
<$REVOKE.G.'group','realm'>
Revoke a permission over a realm from a group or a user.
* <$REQUIRE.'template name','list of possible realms'>
Require users of a specific template to have access for at
least one of the templates in the list. (Comma separated)
* <$RUSER>
Yield the username of the currently logged in user.
* <$RNAME>
Yield the real name of the currently logged in user.
* <$RTAG>
Yield the tag string of the currently logged in user.
* <$RATTACH.'template','subsite'>
Attach a template to a subsite.
* <$RDETACH.'template','subsite'>
Detach a template from a subsite.
DATE TAGS
* <$RDATE>
<$RDATE,'number of days ahead'>
Return the date as a YYMDHmS string. For example:
199912312359 is December 31, 1999, at one minute before
midnight. The second parameter gives the date for a few days
ahead, or beyond, if given negative.
* <$RDAY.'date'>
<$RMONTH.'date'>
<$RYEAR.'date'>
Return the corresponding part of the date given.
* <$RDATEDIFF.D.'earlier date','later date'>
<$RDATEDIFF.H.'earlier date','later date'>
<$RDATEDIFF.M.'earlier date','later date'>
<$RDATEDIFF.S.'earlier date','later date'>
Return the difference between dates, in days, hours, minutes
and seconds, correspondingly.
<$RLASTDAY.'date'>
Give the last day of month related to the specific date.
<$RADDDATE.'date','day','month','year'>
Add the gievn number of days, then the given number of
months and years to the date. Returns a new date.
FORM AND HTML ENHANCEMENT TAGS
* <$RSUBMIT[.'javascript validation code']>
$RSUBMIT>
Create the HTML code for a POST form pointed at the same
merge template it is called from. An optional paramater is
passed to the onSubmit attribute; a typical value would be
'return *function*()' where *function* returns a boolean
value.
* <$RTRANSFER.field name>
Create a HIDDEN input tag, for the parameter with the
corresponding name, based on the values the server side
parameter with the same name has. Useful to transfer input
fields among pages.
* <$RMULTI.'iterator variable'='form field'>
Iterate over multiple input form fields.
* <$RMERGE>
The name of the Merge CGI.
* <$RTEMPLATE>
The name of the current template.
FILE TAGS
* <$RGLOB.F.'iterator variable'='base directory or wildcards'>
<$RGLOB.D.'iterator variable'='base directory'>
Iterate over a directory. Produces either files only or
directories only, accordingly.
* <$RFTS.'iterator variable'='base directory'>
Iterate over a subtree of files.
* <$RDIVERT.'buffer name'> $RDIVERT>
Divert the output into a named buffer. Buffers are store in
temporary files and do not overlap between processes.
Subsequent diverting is appended to the existing buffer.
<$RDUMP.'buffer name'>
Dump the named buffer.
SYNOPSIS
DESCRIPTION
NAME
Merge extensions - Writing your own tags to be used in Merge pages.
DESCRIPTION
This file contains instructions as to how to create your own Merge tags.
TYPES OF TAGS
Generally, there are four types of tags in Merge.
Output tags
Tags such as <$RVAR> or others, that are substituted by values that
appear in the output. For example: <$RVAR.x> is substituted by the value
of the vairable x.
Non block tags
Tags that perform an action, and have no corresponding closing tags. For
example: <$RSET.x='8'> sets the value 8 into the variable x.
Opening block tags
Tags that usually handle the flow of the template. These tags, together
with the closing tags, encapsulate a block of HTML and tags between
them. The data inside the block will be treated as regular output
statements. If you wish to capture it for a different use, a capturing
mechanism (for example, using the Perl select() statement) needs to be
used. For example, <$RITERATION.LIMIT=4> .. $RITERATION> will print
everything inside the block 4 times.
Closing block tags
The tags that close blocks beginning in the opening tags. The tags
<$REND>, <$REND_IF> and <$REND_WHILE> are privilleged as closing tags.
Other closing tags use the SGML like notation of specifying a slash
before the name of the tag, for example: $RCOUNT> is the closing tag
for <$RCOUNT>
COMPILATION PROCESS
Do not execute, create code!
When Merge scans the template, it does not interprete the program, but
creates Perl code to run it. The HTML code is converted to print()
statements. Non block tags are inserted as generated Perl code. Block
tags are added as generated code, that encapsulate a perl operation on
the code within. Output tags depend on connotation: when specified in
the middle of HTML code, the generated code will be used as a parameter
for print(). When specified as part of a parameter for another tag,
string concatenation is used to create one string. For example:
<$RVAR.x> is translated to : print ($vars{"x"});
<$RQ.'<$RVAR.x>'> is translated to: $engines{""}.Query("" . ($vars{"x"})
. "")
In both cases, the code generated by <$RVAR> is an expression, not a
list of statements.
Notice, that when using *any* parameter gotten for a tag, either assumed
to be string or not, it must be encapsulated in double quotes. Consider
we are writing a tag <$RSQR> and generating the code "sqr($x)". If the
user tried <$RSQR.<$RVAR.x>>, we will get sqr(" . $vars{"x"} . ") which
is not what we intended. Therefore we should create the code:
"sqr(\"$x\")" Which can be sqr("3") for <$RSQR.3> or sqr("" . $vars{"x"}
. "") for <$RSQR.<$RVAR.x>>.
Hint: sometimes you need to perform a few sentences for generating an
output tag. In this case it is better to create a function to run in
runtime in the extension module, for example:
sub Proper {
my $str = shift;
$str =~ s/(\w+)/ucfirst(lc($1))/ge;
$str;
}
and generate the code: "HTML::Merge::Ext::Proper(\"$x\")". Note that all
the functions in the extension files reside under the namespace
HTML::Merge::Ext.
You can access the variable $HTML::Merge::Ext::ENGINE, or simply
$ENGINE, to determine which engine was called for the tag. The engine
API is not documented yet and might change without a warning.
EXTENSION FILES
Extension files are created per site, as a file called merge.ext,
residing in the instance directory, or per server, in the file
/etc/merge.ext.
EXTENDED TAGS SYNTAX
Every tag is defined as a function returning the Perl code for the tag.
The function must have a prototype cotaining only scalars, to represent
the number of input parameters.
If we defined a tag called <$RUSER> with two parameters, it will be
called as <$RUSER..>. If parameters
were encapsulated with quotes, it's the job of the user defined function
to strip them.
All special chars in the parameters will be quoted with a leading
backslash using the function quotemeta. Special chars that were not
quoted belong to the generated code the parameters might already
contain. We basically encourage that you don't alter the parameters,
except of stripping quotes if necessary.
Here is an example for a tag called PLUS, that accepts two parameters,
and is substituted by the result of their addition in the output. Notice
that the function prototype is crucial.
sub OUT_PLUS ($$) {
my ($a, $b) = @_;
"\"$a\" + \"$b\""; # Return perl code to perform the operation
}
Notes:
1 The prototype defines two parameters.
2 The parameters must be encapsulated with double quotes, even though
we expect numbers.
Here is how ***NOT*** to implement the tag:
sub OUT_PLUS ($$) {
my ($a, $b) = @_;
return $a + $b; # or equally WRONG:
return '"' . ($a + $b) . '"'';
}
You should not perform the operation in compilation time, but enable
it to perform in run time. The second version will work for
<$RPLUS.4.5> but NOT for <$RPLUS.5.<$RVAR.a>>, which will result in
a hard coded zero.
IMPLEMENTING VARIOUS TAGS
Functions should be in all uppercase, and consist of a prefix describing
the type of the tag, an underscore, and the tag name. Merge is case
insensitive, so don't try to define tags with lowercase names.
For a non block tag, use the prefix B.
For a block opening tag, use the prefix B.
For a block ending tag, use the prefix B.
For an output tag, use the prefix B.
You can use the perl functions setvar, getvar and incvar to manipulate
Merge variables.
Here are some examples:
sub OAPI_CSV ($) {
my $filename = shift;
$filename =~ s/^\\(["'])(.*)\\\1$/$2/; # Drop the quotes
# in compilation time!
<); # Do not use my() !
chop \$__headers;
local (\@__fields) = split(/,\\s*/, \$__headers);
# Notice that we must escape variable names with backslashes
while () {
chop;
my \@__data = split(/,\\s*/);
foreach my \$i (0 .. \$#__fields) {
setvar(\$__fields[\$i], \$__data[\$i]);
}
EOM
}
sub CAPI_CSV () {
"}";
}
Here is how we would use it:
<$RCSV.'/data/<$RVAR.name>'>
<$RVAR.worker> has salary <$RVAR.salary>
$RCSV>
name could be 'workers.dat', and the file /data/workers.dat could be:
worker, salary, office
Bill, 9999999999999, Redmond
George, 0, White House
MACRO TAGS
Macro tags define a tag by simply grouping merge code to be susbtituted
under it. Suppose we have two tags, <$RFIRST> that takes two parameters,
and <$RSECOND> that takes two as well, we could define the tag
<$RCOMBINED> this way:
sub MACRO_COMBINED ($$$) {
<<'EOM';
First $1 and $2: <$RFIRST.$1.$2>
Second $2 and $3: <$RSECOND.$2.$3>
EOM
}
This tag can now be called with three parameters. Note: You do not need
to parse the parameters yourself in a Macro tag. You need to return a
string containing Merge code and references to the parameters like in a
shell script. Writing a prototype is still mandatory.
DESCRIBED TAGS
Until now, extension tags could be called only with a list of parameters
separated by commas. But merge enables defining tags that take a syntax
similar to Merge native tags.
Suppose we define a tag:
sub OUT_MINUS ($$) {
my ($a, $b) = @_;
qq!("$a") - ("$b")!;
}
Now suppose we define a description function:
sub DESC_MINUS {
'U-U';
}
We can now call the new tag: <$RMINUS.7-6> or <$RMINUS.<$RVAR.x>-1> and
so on.
All the non alpha characters in the description string stand for
themselves. The following letters are assigned:
U - Unquoted parameters (e.g. 9, ball, <$RVAR.a> etc).
Q - Quote parameter, (e.g. 'building', "quoted string", 'a "parameter" with <$RVAR.a> inside')
E - Call can end here, rest of the parameters optional. For example, a tag with the description QE:Q-QE*Q can be called as either 'first', 'first':'second'-'third' or 'first':'second'-'third'*'fourth'.
D - Either a dot or equal sign.
MOD PERL COMPLIANCE NOTICE
Merge implements the extensions by compiling them as Perl code into
Merge itself. Therefore, on a mod_perl driven web server with several
instances, extensions will be shared among all instances.
SYNOPSIS