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>
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]> <$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> Performs a counted loop. * <$RIF.'perl code'> <$RELSE> (optional) <$REND_IF> Perform the code if the perl code evaluates to true. * <$RWHILE.'perl code'> <$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]> 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']> Send email, utilizing SMTP connection to localhost. * <$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'> Generate an Anchor for a source view for a template. e.g, <$RSOURCE.'<$RTEMPLATE>'>Click here to view the source for this template 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']> 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'> 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> .. 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: 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>
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