code: 01.
section: NAME
type: item
title: Version

<A NAME="Version">Version</A></H2>
<P>
This document describes MiniVend 3.12, based on Andrew Wilcox's original
Vend, Version 0.2, with portions from Vend 0.3. This is the third major
revision of MiniVend.

<P>
<HR>


code: 02.00
section: NAME
type: overview
title: NAME

<A NAME="NAME">NAME</A></H1>
<P>
MiniVend -- shopping cart and electronic catalog system

<P>
<HR>


code: 03.00
section: DESCRIPTION
type: overview
title: DESCRIPTION

<A NAME="DESCRIPTION">DESCRIPTION</A></H1>
<P>
MiniVend is a database access and retrieval system focused on e-commerce.
It allows customers to select items to buy from catalog pages. The program
tracks which products they have selected and the quantity desired. Many
different catalog pages may be visited, and the user ``session'' will be
tracked to build a cumulative list of items. Once selection is finished,
they may complete the ordering process by entering their name and address
along with payment information, if any. Once the order process is
completed, MiniVend submits the order to the system via email or an
external order entry program.

<P>
Though its name begins with ``Mini'', MiniVend is anything but. It is a
high-end, fully customizable, powerful software system with complete
database functionality. It is suitable for many applications besides
shopping carts, though that is its main bent.

<P>
MiniVend plugs into a system with an 
<FONT SIZE=-1>SSL</FONT> (Secure Sockets Layer) server, allowing encrypted
transmission of sensitive customer data. This capability makes the entry of
credit card numbers practical and secure. In addition, it supports online
payment systems and encryption; no credit card numbers need be stored on
the system ``en clair''.

<P>
Many different catalogs can be run from the same MiniVend server, allowing an 
<FONT SIZE=-1>ISP</FONT> to serve many different customers from one or just a few MiniVend server processes. As many as 1,000 MiniVend catalogs have been run on one machine from the same server process.


<P>
When possible, multiple servers are forked to serve the same set of
catalogs. This ensures fast response, while only one server runs when there
is no catalog activity.

<P>
MiniVend is powerful, and correspondingly complex. It can easily handle
catalogs of a million items or more, with excellent performance. It has
completely flexible page display, search, and order entry capability. If
you only have a few items to catalog, MiniVend is probably overkill for
your needs. But if you are willing to spend some up-front learning time, it
can support your simple catalog with unlimited room to grow. To get a fast
start with a simple catalog, start with the simple demo and customize from
there.

<P>
<HR>


code: 03.02
section: OVERVIEW_OF_MINIVEND
type: item
title: The Vend Concept

<A NAME="The_Vend_Concept">The Vend Concept</A></H2>
<P>
MiniVend is a descendent of Vend, originally developed by Andrew Wilcox.
Though the original Vend was much simpler than MiniVend in implementation,
the basic concept remains unchanged. Quite simply, MiniVend maintains its
own set of pages, <EM>outside of regular HTML space</EM>, which contain special tags that are interpreted by MiniVend.

<P>
The tags, which are in <CODE>[square brackets]</CODE> or 
<FONT SIZE=-1>&lt;IMG</FONT> SRC=``somepic.gif'' MV=``[embedded in 
<FONT SIZE=-1>HTML]''&gt;,</FONT> are interpreted by MiniVend and many different values can be substituted. Some examples are:


<DL>
<DT><STRONG><A NAME="item_User">User form input</A></STRONG><DD>

MiniVend remembers input by a user from form to form, and the value of any
form variable is ``remembered'' and inserted upon finding a <CODE>[value input_field]</CODE>
tag. The <CODE>input_field</CODE> is a normal 
<FONT SIZE=-1>HTML</FONT> form field.

<P><DT><STRONG><A NAME="item_Database">Database contents</A></STRONG><DD>

MiniVend can have an unlimited number of attached databases, either in one of its own internal formats or attached via 
<FONT SIZE=-1>SQL/ODBC.</FONT> The contents of a database can be referenced with tags like
 <CODE>[data table=products column=name key=334-12]</CODE>.

<P><DT><STRONG><A NAME="item_Session">Session parameters</A></STRONG><DD>

Things like where the user originally found your catalog <CODE>[data session referer]</CODE>), domain they are from (<CODE>[data session host]</CODE>), source of hit in a partner program (<CODE>[data session source]</CODE>), the time of their last access (<CODE>[data session time]</CODE>), and many other parameters.

<P><DT><STRONG><A NAME="item_File">File contents or program output</A></STRONG><DD>

You can insert the contents of an outboard file with
<CODE>[file directory/file]</CODE> or <CODE>[include directory/file]</CODE>, or the output from an arbitrary program (given proper permission from
your administrator!).

<P><DT><STRONG><A NAME="item_Searches">Searches of files</A></STRONG><DD>

MiniVend supports different search engines, including <EM>Glimpse</EM>, or you can call your own and have MiniVend process the output for you.

<P></DL>
<P>
There are over 80 different distinct tags supporting hundreds of functions.

<P>
<HR>


code: 03.03
section: OVERVIEW_OF_MINIVEND
type: item
title: A typical user session

<A NAME="A_typical_user_session">A typical user session</A></H2>
<P>
The user hears about your catalog via a search engine, link from another page, or click-thru from a banner ad. They access the link, which is a 
<FONT SIZE=-1>URL</FONT> pointing to the MiniVend 
<FONT SIZE=-1>CGI</FONT> link program (generically called 
<FONT SIZE=-1>VLINK</FONT> or 
<FONT SIZE=-1>TLINK,</FONT> more on that below). The MiniVend server is already running on your system, and your catalog has been designed and tested.


<P>
The link, which is a regular 
<FONT SIZE=-1>CGI</FONT> program, calls the MiniVend server through a socket. The MiniVend server sees the path information which is appended to the 
<FONT SIZE=-1>URL</FONT> calling it, and brings up the corresponding page. The page contains a link to find or order items from your catalog.


<P>
The user clicks on the link and MiniVend looks in the <EM>products</EM> database, finds the item, and places it in the user's shopping cart. (Each
user has a separate shopping cart, which is attached to their <EM>session</EM>.)

<P>
Once the user decides to purchase, they check out by filling out a form
with their name, address, payment information, etc. In the process they may
make choices about how the product should be shipped, how they will pay,
and provide any other information you may ask for. They then place (or
``submit'') the order.

<P>
Their payment may be taken at that point via real-time electronic payment and a soft-goods product downloaded -- or their order information may be simply sent to you, the store owner, via encrypted email or 
<FONT SIZE=-1>FAX.</FONT> The order is saved to a file or database table as backup, or in the case of fully-automated systems sent directly to an order entry program or database link.


<P>
All of these operations are fully configurable by you. The base MiniVend
distribution includes a sample store -- some users have simply customized
the text and images inside, changed the database entries, and opened their
store. You will probably want to fully customize for a distinctive catalog
look and feel.

<P>
<HR>


code: 03.03
section: OVERVIEW_OF_MINIVEND
type: item
title: Page Delivery

<A NAME="Page_Delivery">Page Delivery</A></H2>
<P>
MiniVend pages are written in regular 
<FONT SIZE=-1>HTML</FONT> with extensions to support catalog ordering.
MiniVend extensions look like:

<P>
<PRE>    [page specials]See our specials![/page]
</PRE>
<P>
Pages are delivered through the following steps:

<UL>
<LI>

The 
<FONT SIZE=-1>HTTPD</FONT> server (Apache, Netscape, or 
<FONT SIZE=-1>NCSA</FONT> are examples of 
<FONT SIZE=-1>HTTP</FONT> servers) receives a request for a MiniVend page.


<P><LI>

The server is already running as a daemon, and the request calls a small 
<FONT SIZE=-1>C</FONT> program (source is vlink.c or tlink.c) that is
<EM>named according to which catalog is being called.</EM> This program communicates with the MiniVend program via a 
<FONT SIZE=-1>UNIX-</FONT> or INET-domain socket.

<P><LI>

MiniVend reads the source page from the MiniVend pages directory, and
interprets the MiniVend tags in the file. If the page doesn't exist, and
corresponds to a part number in the database, it is built ``on the fly''
using a template page. In the process, it may read or modify any number of
database tables. If the user's browser doesn't accept cookies, then any
links generated on the page will contain the <EM>session ID</EM>, which is needed to ensure the user's session is retained.

<P><LI>

The page, which is now entirely in regular 
<FONT SIZE=-1>HTML,</FONT> is delivered to the 
<FONT SIZE=-1>HTTP</FONT> server, which returns it to the browser.


<P></UL>
<P>
<HR>


code: 03.04
section: OVERVIEW_OF_MINIVEND
type: item
title: How MiniVend Manages Sessions

<A NAME="How_MiniVend_Manages_Sessions">How MiniVend Manages Sessions</A></H2>
<P>
Normally, each request for a World Wide Web page which comes in to a server
stands on its own. While the server will probably know which machine a
request comes from, it may not know if the next request comes from the same
browser or even from the same user on that machine.

<P>
MiniVend keeps track of who is ordering what by including in the 
<FONT SIZE=-1>URL</FONT> a
<EM>session id</EM>, which is a random piece of text which is different for each customer
browsing the catalog.

<P>
This session 
<FONT SIZE=-1>ID</FONT> is either tracked with cookies, or it can be passed along through special URLs within catalog pages. Pages in the catalog served by MiniVend running as a cgi-bin program generate a special 
<FONT SIZE=-1>URL</FONT> for every link. Here is an example of such a 
<FONT SIZE=-1>URL:</FONT>


<P>
<PRE>    <A HREF="http://machine.company.com/cgi-bin/simple/browse?WehUkATn">http://machine.company.com/cgi-bin/simple/browse?WehUkATn</A>;arg;1
</PRE>
<P>
An explanation of each part:

<DL>
<DT><STRONG><A NAME="item_machine">machine.company.com</A></STRONG><DD>

Internet address of the server hosting the MiniVend catalog.

<P><DT><STRONG><A NAME="item_cgi">cgi-bin</A></STRONG><DD>

Informs server that the requested page will be generated by a program.

<P><DT><STRONG><A NAME="item_simple">simple</A></STRONG><DD>

Name of the program to run

<P><DT><STRONG><A NAME="item_browse">browse</A></STRONG><DD>

Page of the catalog to display

<P><DT><STRONG><A NAME="item_WehUkATn">WehUkATn</A></STRONG><DD>

The session 
<FONT SIZE=-1>ID</FONT>

<P><DT><STRONG><A NAME="item__">;</A></STRONG><DD>

Separates session 
<FONT SIZE=-1>ID</FONT> from argument.

<P><DT><STRONG><A NAME="item_arg">arg</A></STRONG><DD>

An argument which can be used by MiniVend to select page display options.

<P><DT><STRONG>;</STRONG><DD>

Separates argument from the unique integer.

<P><LI>


<FONT SIZE=-1>A</FONT> unique integer (or source code, if it contains a letter) which prevents caching servers from caching the 
<FONT SIZE=-1>URL.</FONT>


<P></DL>
<P>
<HR>


code: 04.00
section: OVERVIEW_OF_MINIVEND
type: overview
title: OVERVIEW OF MINIVEND

<A NAME="OVERVIEW_OF_MINIVEND">OVERVIEW OF MINIVEND</A></H1>
<P>
The following section describes how MiniVend works, and should be read by
anyone creating a MiniVend catalog.

<P>
<HR>


code: 04.02
section: DISTRIBUTION_AND_SUPPORT_INFORMA
type: item
title: Where to Download MiniVend

<A NAME="Where_to_Download_MiniVend">Where to Download MiniVend</A></H2>
<P>
The MiniVend version described in this document is available from:

<P>
<PRE>    <A HREF="http://www.minivend.com/minivend/download.html">http://www.minivend.com/minivend/download.html</A>
</PRE>
<P>
You can also go to any 
<FONT SIZE=-1>CPAN</FONT> archive and access the directory
<CODE>authors/id/MIKEH</CODE>.

<P>
<HR>


code: 04.03
section: DISTRIBUTION_AND_SUPPORT_INFORMA
type: item
title: Perl

<A NAME="Perl">Perl</A></H2>
<P>
You will need Perl version 5.004 or higher to run MiniVend 3.12. Many sites are still running lower Perl versions. In addition, on systems that do not have 
<FONT SIZE=-1>GDBM</FONT> or DB_File installed, memory problems may occur. Large catalogs will use large amounts of memory if the databases must all reside there.


<P>
You can download the latest Perl 5 from any 
<FONT SIZE=-1>CPAN</FONT> (Comprehensive Perl Archive Network) site. See

<P>
<PRE>    <A HREF="http://www.perl.com/CPAN/">http://www.perl.com/CPAN/</A>
</PRE>
<P>
Windows users will need to obtain the either the ActiveState Perl build 5xx (the one from the 
<FONT SIZE=-1>NT</FONT> Resource Kit will 
<FONT SIZE=-1>NOT</FONT> work) or the standard version Perl, also known as the
 <EM>Gurusamy Sarathy</EM> or <EM>CORE</EM> version, from the directory <CODE>ports/win32/Standard/x86</CODE>.

<P>
<HR>


code: 04.04
section: DISTRIBUTION_AND_SUPPORT_INFORMA
type: item
title: Setup for HTTP Servers

<A NAME="Setup_for_HTTP_Servers">Setup for HTTP Servers</A></H2>
<P>
MiniVend requires a that a web server be installed on your system in the
normal course of events; it does have an internal server which can be used
for administration, testing, and maintenance, but you will not want to use
it to serve images and other content.

<P>
As detailed previously, MiniVend is always running in the background as a
daemon. It monitors either 1) a UNIX-domain file-based socket, located in
the <A HREF="#item_etc_">etc/</A> subdirectory; or 2) a series of INET-domain sockets. The small 
<FONT SIZE=-1>CGI</FONT> link program, called in the demo <A HREF="#item_simple">simple</A>, is run to connect to one of those sockets and provide the link between
your browser.

<P>

<FONT SIZE=-1>NOTE:</FONT> Since Apache and other CERN/NCSA-derived servers are the most popular, we will talk in the terms they use. If you use another web server, you may have to translate the terms; for instance on 
<FONT SIZE=-1>MS</FONT> Personal web server the standard
 <CODE>ScriptAlias</CODE> is <CODE>/scripts</CODE>.

<P>
You need to have a <CODE>ScriptAlias</CODE> or other 
<FONT SIZE=-1>CGI</FONT> execution capability to use the link program. (The
default <CODE>ScriptAlias</CODE> for many web servers is <CODE>/cgi-bin</CODE>.) If you have <CODE>ExecCGI</CODE> set for all of your directories, then any program ending in a particular
file suffix (usually
<A HREF="#item__cgi">.cgi</A>) will be seen as a 
<FONT SIZE=-1>CGI</FONT> program.

<P>
MiniVend, by convention, names the link program the same name as the catalog 
<FONT SIZE=-1>ID.</FONT> In the distribution demo, this would yield a program name or 
<FONT SIZE=-1>SCRIPT_PATH</FONT> of
 <CODE>/cgi-bin/simple</CODE> or <CODE>/simple.cgi</CODE>. This 
<FONT SIZE=-1>SCRIPT_PATH</FONT> is used to determine which MiniVend
catalog will be used when the link program is accessed.

<P>
<HR>


code: 04.05
section: DISTRIBUTION_AND_SUPPORT_INFORMA
type: item
title: Internal HTTP server

<A NAME="Internal_HTTP_server">Internal HTTP server</A></H2>
<P>
If you contact the socket directly (only for INET-domain sockets), MiniVend will perform the 
<FONT SIZE=-1>HTTP</FONT> server function itself, talking directly to the browser. It can monitor any number of ports and map them to a particular catalog; by default it only maps the special catalog mv_admin, which performs administrative functions. The default port is 7786 
<FONT SIZE=-1>(ASCII</FONT> for 
<FONT SIZE=-1>M</FONT> an 
<FONT SIZE=-1>V),</FONT> which is the default compiled into the distribution
 <EM>tlink</EM> program. You can change this port via the
<EM>TcpMap</EM> directive.

<P>
To prevent catalogs that do not wish access made in this way from being served from the internal server, MiniVend has a fixed 
<FONT SIZE=-1>SCRIPT_PATH</FONT> of
 <CODE>/catalogname</CODE> (/simple for the distribution demo) which needs to be placed as an alias in
the <EM>Catalog</EM> directive to enable access. See <EM>TcpMap</EM> for more details.

<P>
<HR>


code: 04.05
section: DISTRIBUTION_AND_SUPPORT_INFORMA
type: item
title: UNIX-domain sockets

<A NAME="UNIX_domain_sockets">UNIX-domain sockets</A></H2>
<P>
This is a socket which is not reachable from the Internet directly, but
which must come from a request on your own server. The link program
<CODE>vlink</CODE> is the provided facility for such communication with MiniVend.

<P>
This is the most secure way to run your catalog, for there is no way for
systems on the Internet to interact with MiniVend except through its link
program.

<P>
The most important issue with UNIX-domain sockets on MiniVend is the permissions with which the 
<FONT SIZE=-1>CGI</FONT> program and the MiniVend server run.


<P>
To improve security, MiniVend normally runs with the socket file having 0600 permissions (rw-------), which mandates that the 
<FONT SIZE=-1>CGI</FONT> program and the server run
 <EM>as the same user ID</EM>. This means that the <CODE>vlink</CODE> program must be 
<FONT SIZE=-1>SUID</FONT> to the same user 
<FONT SIZE=-1>ID</FONT> as the server executes under. (Or that 
<FONT SIZE=-1>CGIWRAP</FONT> is used on a single catalog system).


<P>
With MiniVend 3.0 multiple catalog capability, the permissions situation
gets a bit tricky. MiniVend comes with a program, <CODE>makecat</CODE>, which configures catalogs for a multiple catalog system. It should
properly set up ownership and permissions for multiple users if run as the
superuser.

<P>
<HR>


code: 04.06
section: DISTRIBUTION_AND_SUPPORT_INFORMA
type: item
title: INET-domain sockets

<A NAME="INET_domain_sockets">INET-domain sockets</A></H2>
<P>
These are sockets which are reachable from the Internet directly. The link
program <CODE>tlink</CODE> is the provided facility for such communication with MiniVend; you may also
use your browser to talk to the socket directly if you have it mapped to a
catalog with the global <EM>TcpMap</EM> directive.

<P>
To improve security, MiniVend usually checks that the request comes from
one of a limited number of systems, defined in the global <EM>TcpHost</EM>
directive. (This check is not made for the internal 
<FONT SIZE=-1>HTTP</FONT> server.)

<P>
<HR>


code: 05.00
section: DISTRIBUTION_AND_SUPPORT_INFORMA
type: overview
title: DISTRIBUTION AND SUPPORT INFORMATION

<A NAME="DISTRIBUTION_AND_SUPPORT_INFORMA">DISTRIBUTION AND SUPPORT INFORMATION</A></H1>
<P>
MiniVend is normally free of charge, and is distributed under the 
<FONT SIZE=-1>GNU</FONT> general public license. This means that
individuals and organizations, both commercial and non-commercial, may use
MiniVend without charge. If you modify and redistribute it, there are
certain obligations you must fulfill. See the file <STRONG>Copying</STRONG> which came with your MiniVend distribution for the full license.

<P>
MiniVend is not guaranteed to be supported other than by making full source
code available. If it breaks you get to keep both pieces. However, the
author is always looking to improve MiniVend and sometimes answers
questions. The more concise and better-researched your question, the more
likely it is to get an answer. No tutorials will be provided, though. You
have to learn all of this stuff on your own, or use the MiniVend mail list
and hope that someone will help you.

<P>
<HR>


code: 05.02
section: QUICK_START
type: item
title: The Catalog

<A NAME="The_Catalog">The Catalog</A></H2>
<P>
MiniVend pages are 
<FONT SIZE=-1>NOT</FONT> in normal 
<FONT SIZE=-1>HTML</FONT> space. They are contained in the

<EM>catalog directory</EM>. Each individual catalog must have its own base directory. The catalog
directory has this structure by default:

<DL>
<DT><STRONG><A NAME="item_catalog">catalog.cfg</A></STRONG><DD>

File containing configuration directives for this catalog. (Subcatalogs
have differing information in a file named for the subcatalog.)

<P><DT><STRONG><A NAME="item_config">config</A></STRONG><DD>

Directory that will be read when directives are set with the &lt;filename notation. For example, the file <CODE>config/static.pages</CODE>
will be read when the directive

<P>
<PRE> StaticPage  &lt;static.pages
</PRE>
<P>
is encountered in the catalog.cfg file.

<P>
This directory also contains template information used with the makecat
program.

<P><DT><STRONG><A NAME="item_error">error.log</A></STRONG><DD>

File which contains catalog-specific errors.
<EM>Check this file when something doesn't work right.</EM>
It is also where any syntax errors in embedded Perl code will be shown.

<P><DT><STRONG><A NAME="item_etc">etc</A></STRONG><DD>

Directory that contains logs, order profiles, and other information. If the <EM>ScratchDir</EM> directive is not redefined (it is set to the directory
<A HREF="#item_tmp">tmp</A> in the simple demo) then search overflow files and cache files will be
based there as well.

<P><DT><STRONG><A NAME="item_pages">pages</A></STRONG><DD>

Directory that contains the pages of your catalog. This can be considered
to be the ``document root'' of the catalog. Pages contained therein are
called with the path information after the script name -- i.e. <CODE>/cgi-bin/simple/products/gold</CODE> will call the page in the file <CODE>pages/products/gold.html</CODE>.

<P><DT><STRONG><A NAME="item_products">products</A></STRONG><DD>

Directory containing database source files, including the special MiniVend
databases shipping.asc, accessories.asc, pricing.asc (and other shipping
database files)

<P><DT><STRONG><A NAME="item_reconfig">reconfig</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> script file, which when executed, will cause the catalog.cfg file to be re-read and the catalog configuration to change. If errors occur, the catalog will stay with its old/previous configuration. This script is set up by the makecat program, but may require editing if you deviate from the standard MiniVend configuration. It operates by executing the link program that is contained in the 
<FONT SIZE=-1>CGI</FONT> directory and passing the proper parameters through the environment.


<P><DT><STRONG><A NAME="item_session">session</A></STRONG><DD>

Directory which contains session files when 
<FONT SIZE=-1>DBM</FONT> sessions are not in use.

<P><DT><STRONG><A NAME="item_session">session.gdbm (or session.db)</A></STRONG><DD>

The 
<FONT SIZE=-1>GDBM</FONT> or DB_File session database file. This is a 
<FONT SIZE=-1>DBM</FONT> database that contains the user sessions.


<P><DT><STRONG><A NAME="item_tmp">tmp</A></STRONG><DD>

In the simple demo, this is where the cache and search paging files are
placed because of the <EM>ScratchDir</EM> definition.

<P></DL>
<P>
<HR>


code: 05.03
section: QUICK_START
type: item
title: If something goes wrong

<A NAME="If_something_goes_wrong">If something goes wrong</A></H2>
<P>
MiniVend is a complex program, and needs the services of other complex programs to work. When there is a problem, it is not always MiniVend. It may have to do with Perl or your 
<FONT SIZE=-1>HTTP</FONT> server setup. In fact, in the over two years of MiniVend's existence many more basic installation problems have to do with those than with MiniVend itself.


<P>
If you get a message about not being able to find libraries, or if you get
a core dump or segment fault message, it is always an improperly built or
configured Perl and has nothing to do with MiniVend. Contact your system
administrator or install a new Perl yourself.

<P>
The <CODE>makecat</CODE> program is intended to be used to create the starting point for the catalog. If you don't get the demo to work the first time, keep trying. If you still can't get the demo to work, try running in 
<FONT SIZE=-1>INET</FONT> mode. Finally, see the MiniVend 
<FONT SIZE=-1>FAQ</FONT> at:


<P>
<PRE>    <A HREF="http://www.minivend.com/minivend/faq/">http://www.minivend.com/minivend/faq/</A>
</PRE>
<P>
Check the two error log files -- <CODE>error.log</CODE> in the MiniVend home directory (where minivend.cfg resides) and <CODE>error.log</CODE> in the catalog directory (where catalog.cfg resides; there can be many of
these). Many problems can be diagnosed quickly if these error logs are
consulted.

<P>
Check the 
<FONT SIZE=-1>README</FONT> file, the 
<FONT SIZE=-1>FAQ,</FONT> and mail list archive at the official MiniVend web site for information:


<P>
<PRE>    <A HREF="http://www.minivend.com/minivend/">http://www.minivend.com/minivend/</A>
</PRE>
<P>
You may subscribe to the MiniVend users mail list by sending the
<STRONG>message text</STRONG>  <CODE>subscribe minivend-users</CODE> to:

<P>
<PRE>    majordomo@minivend.com
</PRE>
<P>
Double check that you have the following things:

<OL>
<LI>

The <CODE>vlink</CODE> program is 
<FONT SIZE=-1>SUID,</FONT> or you have made appropriate changes in the <EM>ReadPermission</EM> and <EM>WritePermission</EM> directives. Unless the files are world-writable, the vlink program and the MiniVend server must run as the same user 
<FONT SIZE=-1>ID!</FONT>


<P>
If you have trouble with the vlink program (named <A HREF="#item_simple">simple</A> in the demo configuration), try re-running <CODE>makecat</CODE> and using 
<FONT SIZE=-1>INET</FONT> mode instead. (Or you can copy the <CODE>tlink</CODE> 
<FONT SIZE=-1>INET</FONT> mode link program over <CODE>vlink</CODE>). This should work unchanged for many systems, but if you are on an 
<FONT SIZE=-1>ISP</FONT> or have a non-standard network configuration you
may have to make some changes to <EM>minivend.cfg</EM>. For <CODE>tlink</CODE> to work you must have the proper host <CODE>name(s)</CODE> configured into
the <EM>TcpHost</EM> directive in <EM>minivend.cfg</EM>. The program selects port 7786 by default (the 
<FONT SIZE=-1>ASCII</FONT> codes for 
<FONT SIZE=-1>``M''</FONT> and 
<FONT SIZE=-1>``V'')</FONT> -- if you decide to use another port, you must set the same number in both the tlink program (before compilation, or by editing tlink.pl) and the
 <CODE>minivend.cfg</CODE> file.

<P>
The <CODE>tlink</CODE> program does <STRONG>not</STRONG> need to be 
<FONT SIZE=-1>SUID.</FONT>

<P><LI>

That you have proper file permissions.

<P>
<STRONG>IMPORTANT NOTE:</STRONG> The MiniVend server should not run as the user
<CODE>nobody</CODE>!

<P>
The program files can be owned by anyone, but any databases, 
<FONT SIZE=-1>ASCII</FONT> database source files, error logs, and the
directory that holds them must be <STRONG>writable</STRONG> by the proper user 
<FONT SIZE=-1>ID,</FONT> that is the one that is executing the minivend
program. The best way to operate in multi-user, multi-catalog setups is to
create a special <CODE>minivend</CODE>
user, then put that user in the group that each catalog user is in. If you
can define a group for each individual user, that provides the best
security. Then all associated files can be in 660 or 770 mode, and you
should have no problems with permissions, and no problems with security.

<P><LI>

The <CODE>vlink</CODE> program is being executed on a machine that has the socket file <CODE>etc/socket</CODE> on a directly attached disk. UNIX-domain sockets will not work on
NFS-mounted filesystems! That means the server <CODE>minivend</CODE> and the 
<FONT SIZE=-1>CGI</FONT> program <CODE>vlink</CODE> must be executing on the same machine.

<P>
The <CODE>tlink</CODE> program does not have this problem, but it must have the proper host <CODE>name(s)</CODE> and 
<FONT SIZE=-1>TCP</FONT> ports set in the
 <EM>TcpHost</EM> and <EM>TcpPort</EM>
directives in <CODE>minivend.cfg</CODE>. Also, you should be careful of security if sensitive information like
customer credit card numbers is being placed on a network wire.

<P></OL>
<P>
MiniVend is an ambitious and complex program, and is not presented as being <EM>easy to use</EM>, <EM>easy to install</EM>, or <EM>bug-free</EM>. The configuration scripts were done to try and make a very painful process only slightly painful. Some people install in one pass. Others never make it, especially when they are running on an 
<FONT SIZE=-1>ISP</FONT> with a restrictive setup. Determined and thoughtful users almost always make MiniVend work.


<P>
<HR>


code: 05.03
section: QUICK_START
type: item
title: makecat -- set up a catalog from a template

<A NAME="makecat_set_up_a_catalog_from">makecat -- set up a catalog from a template</A></H2>
<P>
The supplied <CODE>makecat</CODE> script, which is in the MiniVend program directory
<CODE>bin</CODE>, is designed to set up a catalog based on your server configuration. It interrogates the user for parameters like the directories to use, 
<FONT SIZE=-1>URL</FONT> to base the catalog in, 
<FONT SIZE=-1>HTTP</FONT> server definitions, and file ownership. It is self-documenting in that it asks verbose questions and gives relevant examples.


<P>
The <CODE>makecat</CODE> script needs a template catalog to operate on. The
<EM>simple</EM> and <EM>flycat</EM> demo templates are distributed with MiniVend -- there is also an older <EM>sample</EM> frame-based demo catalog available at
<CODE>ftp.minivend.com</CODE>.

<P>
<STRONG>IMPORTANT NOTE:</STRONG> You only make a catalog once. All further configuration is done by editing
the files within the <EM>catalog directory</EM>.

<P>

<FONT SIZE=-1>A</FONT> catalog template contains an image of a configured
catalog. The best way to see what the makecat program does is to configure
the simple demo and then run a recursive <CODE>diff</CODE> on the template and configured catalog directories:

<P>
<PRE>  diff -r mvend/simple catalogs/simple
</PRE>
<P>

<FONT SIZE=-1>NOTE:</FONT> <CODE>diff</CODE> is usually only available on 
<FONT SIZE=-1>UNIX.</FONT>

<P>
You will see that the files are mostly the same, except that certain macro
strings have been replaced with the answers you gave to the script. For
example, if you answered <CODE>www.mydomain.com</CODE> at the prompt for server name, then you would see this difference in the
catalog.cfg file:

<P>
<PRE>    # template
    Variable SERVER_NAME  __MVC_SERVERNAME__
</PRE>
<P>
<PRE>    # configured catalog
    Variable SERVER_NAME  www.mydomain.com
</PRE>
<P>
The macro string 
<FONT SIZE=-1>__MVC_SERVERNAME__</FONT> was substituted with the answer to
the question about server name. In the same way, other variables are
substituted, and include (at least):

<P>
<PRE>    MVC_BASEDIR      MVC_IMAGEDIR
    MVC_CATROOT      MVC_IMAGEURL
    MVC_CATUSER      MVC_MAILORDERTO
    MVC_CGIBASE      MVC_MINIVENDGROUP
    MVC_CGIDIR       MVC_MINIVENDUSER
    MVC_CGIURL       MVC_SAMPLEHTML
    MVC_DEMOTYPE     MVC_SAMPLEURL
    MVC_DOCUMENTROOT MVC_VENDROOT
    MVC_ENCRYPTOR
</PRE>
<P>
(Not all of these are present in the simple or sample templates.) In fact, any environment variable that is set and begins with 
<FONT SIZE=-1>MVC_</FONT> will be substituted for by the
 <CODE>makecat</CODE> script. So if you wanted to set up a configurable parameter to customize the 
<FONT SIZE=-1>COMPANY</FONT> variable in catalog.cfg, you could run a pre-qualifying script that set the environment variable 
<FONT SIZE=-1>MVC_COMPANY</FONT> and then place in the catalog.cfg file:


<P>
<PRE>    Variable   COMPANY   __MVC_COMPANY__
</PRE>
<P>
All files within a template directory are substituted for macros, not just
the catalog.cfg file. There are two special directories named <CODE>html</CODE> and <CODE>images</CODE>. These will be recursively copied to the directories defined as SampleHTML
and ImageDir.

<P>
<STRONG>IMPORTANT NOTE:</STRONG> The template directory is located in the MiniVend software directory, i.e.
where <CODE>minivend.cfg</CODE> resides. You normally do not edit files in the template directory. If you
want to try creating your own template, it is recommended that you name it
something besides simple and copy the <A HREF="#item_simple">simple</A> demo directory to it as a starting point. Templates are normally placed in
the MiniVend base directory, but can be located anywhere -- the script will
prompt you for location if it cannot find a template.

<P>
In addition to the standard parameters prompted for by MiniVend, and the
standard catalog creation procedure, you may define four other files in the <A HREF="#item_config">config</A> directory of the template:

<P>
<PRE>    additional_fields  -- file with more parameters for macro substitution
    additional_help    -- extended description for the additional_fields
    pre_commands       -- commands passed to the system prior to catalog copy
    post_commands      -- commands passed to the system after catalog copy
</PRE>
<P>
All files are paragraph-based; in other words, a blank line (with no
spaces) terminates the individual setting.

<P>
The <EM>additional_fields</EM> file contains:

<P>
<PRE>    PARAM
    The prompt. Set PARAM to?
    The default value of PARAM
</PRE>
<P>
This would cause a question during makecat:

<P>
<PRE>    The prompt. Set PARAM to?.....[The default value of PARAM]
</PRE>
<P>
If the <EM>additional_help</EM> file is present, you can give additional instructions for 
<FONT SIZE=-1>PARAM.</FONT>

<P>
<PRE>    PARAM
    These are additional instructions for PARAM, and they
    may span multiple lines up to the first blank line.
</PRE>
<P>
The prompt would now be:

<P>
<PRE>    These are additional instructions for PARAM, and they
    may span multiple lines up to the first blank line.
</PRE>
<P>
<PRE>    The prompt. Set PARAM to?.....[The default value of PARAM]
</PRE>
<P>
If the file <EM>config/pre_commands</EM> exists, it will be read as a command followed by the prompt/help value.

<P>
<PRE>    mysqladmin create __MVC_CATALOGNAME__
    We need to create an SQL database for your Minivend
    database tables.
     
This will cause the prompt:
</PRE>
<P>
<PRE>    We need to create an SQL database for your Minivend
    database tables.
     
    Run command &quot;mysqladmin create simple&quot;?
</PRE>
<P>
If the response is ``y'' or ``yes'', then the command will be run by passing it through the Perl <CODE>system()</CODE> function. As with any of the additional configuration files, 
<FONT SIZE=-1>MVC_PARAM</FONT> macro substitution is done on the command and help. Obviously you must have proper permissions for the command.


<P>
The file <EM>config/post_commands</EM> is exactly the same as <EM>pre_commands</EM>
except you are prompted <EM>after</EM> the catalog files are copied and macro substitution is performed on all
files.

<P>
<HR>


code: 05.04
section: QUICK_START
type: item
title: Setting up multiple catalogs

<A NAME="Setting_up_multiple_catalogs">Setting up multiple catalogs</A></H2>
<P>
MiniVend has multiple catalog capability, and therefore breaks the
configuration files into two pieces. One is global (<CODE>minivend.cfg</CODE>) and affects every catalog running under it. The other (<CODE>catalog.cfg</CODE>) is specific to an individual catalog, and has no effect on other
catalogs.

<P>
The global <CODE>minivend.cfg</CODE> file is located in the main MiniVend directory, and has only a few
server-wide configuration parameters. The most important is the <EM>Catalog</EM> directive, which defines the catalogs will be created at server startup.
The <EM>Catalog</EM> directive is often set up by the <CODE>makecat</CODE> program, which can be used to configure a catalog.

<P>
Here is an example <EM>Catalog</EM> directive:

<P>
<PRE> Catalog simple /home/catalogs/simple /cgi-bin/simple /secure-bin/simple
</PRE>
<DL>
<DT><STRONG>simple</STRONG><DD>

The <EM>catalog identifier</EM>, used as the name of the catalog on command lines. In the supplied demo
configuration this would be <A HREF="#item_simple">simple</A>. The identifier can contain characters from the set [<STRONG>A-Za-z0-9_</STRONG>].

<P><DT><STRONG><A NAME="item__home_catalogs_simple">/home/catalogs/simple</A></STRONG><DD>

The directory where the catalog.cfg file may be found, and usually the
directory where pages and databases are kept.

<P><DT><STRONG><A NAME="item__cgi_bin_simple">/cgi-bin/simple  /secure-bin/simple</A></STRONG><DD>

The script names which, when containing a MiniVend link program, will cause
that catalog to be called. At least one must be supplied, and the same name
may not be used for more than one catalog unless the <EM>FullURL</EM> directive is specified, in which case the parameter may be specified as
www.yourcompany.com/cgi-bin/simple and www.theirs.com/cgi-bin/simple may
call a different catalog.

<P></DL>
<P>
There may also be <EM>SubCatalog</EM> directives:

<P>
<PRE>  SubCatalog easy simple /home/catalogs/simple /cgi-bin/easy
</PRE>
<DL>
<DT><STRONG><A NAME="item_easy">easy</A></STRONG><DD>

The name of the subcatalog, which also controls the name of the subcatalog
configuration file -- in this case <CODE>easy.cfg</CODE>.

<P><DT><STRONG>simple</STRONG><DD>

The name of the base configuration, which will be the basis for the
catalog. Parameters in the easy.cfg file that are different will override
those in the catalog.cfg file for the base configuration.

<P></DL>
<P>
The remaining parameters are as in the <EM>Catalog</EM> directive.

<P>
Additional minivend.cfg parameters set up administrative parameters that
are catalog wide -- see <EM>Server Configuration File</EM> for details on each of these.

<P>
Each catalog can be completely independent, with different databases -- or
catalogs can share any or all pages, databases, and session files. This
means that several catalogs can share the same information, allowing
``virtual malls''.

<P>
<HR>


code: 06.00
section: QUICK_START
type: overview
title: QUICK START

<A NAME="QUICK_START">QUICK START</A></H1>
<P>
Obtain, decompress and untar the distribution:

<P>
<PRE>    gzip -dc minivend-3.12.tar.gz | tar xvf -
</PRE>
<P>

<FONT SIZE=-1>NOTE</FONT> 
<FONT SIZE=-1>FOR</FONT> 
<FONT SIZE=-1>WINDOWS:</FONT> Windows users need to unzip the file WinZip or a similar program or obtain the self-extracting executable.


<P>
Before installing, check the site where you obtained MiniVend for any
patches that might have been issued since the release.

<P>
Change to the created directory, something like:

<P>
<PRE>    cd minivend-3.12
</PRE>
<P>
Run the configure script with:

<P>
<PRE>    ./configure
</PRE>
<P>

<FONT SIZE=-1>NOTE</FONT> 
<FONT SIZE=-1>FOR</FONT> 
<FONT SIZE=-1>WINDOWS:</FONT> Type
 <CODE>configure</CODE> instead. The ./ is needed for 
<FONT SIZE=-1>UNIX</FONT> users with a properly setup shell.

<P>
If you have trouble with ./configure, try this:

<P>
<PRE>    perl Makefile.PL
    make
    make test
    make install
</PRE>
<P>
Replace the <CODE>perl</CODE> with the proper path to your Perl 5.004 or higher binary.

<P>
You will be asked for the directory where you want to install MiniVend -- any directory will do. You must of course have write permission there; and you will eventually need to have write permission on your 
<FONT SIZE=-1>CGI-BIN</FONT> and 
<FONT SIZE=-1>HTML</FONT> directories. This directory is referred to later in the documentation as
 <STRONG>VendRoot</STRONG> or the <STRONG>MiniVend software directory</STRONG>.

<P>
The process should be self-explanatory. If you have trouble answering the
questions asked, <STRONG>look closely</STRONG> at the examples provided. If you still have trouble, you will need to find a tutorial about the World Wide Web -- the 
<FONT SIZE=-1>WWW</FONT> 
<FONT SIZE=-1>FAQ</FONT> at www.boutell.com would be a good place to look.


<P>
If you discover any problems, refer to the section <EM>If something goes wrong</EM>. Otherwise, MiniVend should be installed at the completion of the script.
It is strongly suggested that you install the demo catalogs as a starting
point for your own catalog -- in fact you will not be able to run MiniVend
until you have created a catalog.

<P>
You will want separate directories to hold the catalog pages and databases.
The <CODE>makecat</CODE> program supplied with MiniVend will make those for you.

<P>
<STRONG>IMPORTANT NOTE:</STRONG> One point that is to be emphasized --
<EM>only your base html pages go in the document space of your http server.</EM>
Any pages with MiniVend elements/tags go in the directory set by the
<EM>PageDir</EM> directive (the default is <CODE>~/catalogs/catalog_name/pages</CODE>). For the demos supplied with MiniVend, this means that only a few pages will be copied to your 
<FONT SIZE=-1>HTML</FONT> directory, with the remainder of the pages staying in the directory defined as
 <EM>PageDir</EM>.

<P>
If you are on an 
<FONT SIZE=-1>ISP</FONT> where <STRONG>all</STRONG> of your files are in 
<FONT SIZE=-1>HTML</FONT> document space, you should disable all access to your MiniVend catalog directory with the proper 
<FONT SIZE=-1>HTTP</FONT> access restrictions. Normally that is creating a .htaccess file like this:


<P>
<PRE>  &lt;Limit GET POST&gt;
  order allow,deny
  deny from all
  &lt;/Limit&gt;
</PRE>
<P>
If you are unable to do this, it is recommended that you do not run MiniVend. If you can set file permissions such that files will not be served, it may be 
<FONT SIZE=-1>OK,</FONT> but security will be a problem. Please be careful with your customers' personal information.


<P>
<HR>


code: 06.02
section: SETTING_UP_YOUR_CATALOG
type: item
title: Start with a database

<A NAME="Start_with_a_database">Start with a database</A></H2>
<P>
The first thing you must do is develop your product database. This might contain all of the information used to display pages about your products -- or just the product code 
<FONT SIZE=-1>(SKU),</FONT> short description, and price. At the minimum, those three fields are required.


<P>
Some other things you might put in:

<DL>
<DT><STRONG><A NAME="item_image">image</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> database field giving the name of an image file to
display the product. Alternatively, you can keep images in files that are
named for the product code -- then display them if they exist (use the
<CODE>[if file file.gif] TAG [/if]</CODE> construct).

<P><DT><STRONG><A NAME="item_nontaxable">nontaxable</A></STRONG><DD>

This field should be present if you have items that do not have sales tax
calculated for them.

<P><DT><STRONG><A NAME="item_size">size</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> comma-separated string containing product size
information, for example:

<P>
<PRE>  Small, Medium, Large, XL
</PRE>
<P>
You can also define any other attribute information in a database field.

<P><DT><STRONG><A NAME="item_weight">weight</A></STRONG><DD>

The shipping weight of an item is useful for 
<FONT SIZE=-1>UPS</FONT> lookup or other weight-based shipping
calculations.

<P><DT><STRONG><A NAME="item_category">category</A></STRONG><DD>

If you wish to do one-click category searches to build product directories,
you might use this field to select on.

<P><DT><STRONG><A NAME="item_related">related</A></STRONG><DD>

Items related to the item in the record. Using MiniVend's <CODE>[loop item]</CODE>
tag, you could build product subclasses and accessory sets.

<P></DL>
<P>
By default, all database source files are located in the in the
<A HREF="#item_products">products</A> subdirectory of the catalog directory. The main products database we
discussed above is in the file <CODE>products/products.asc</CODE>
by default. If you use one of the internal database methods, then any changes that are made to the 
<FONT SIZE=-1>ASCII</FONT> source file will be reflected in the database on the next access by a user. If you have a very large database, this may not be what you want -- it can take some time to build a large database. If you have less than a thousand records like the ones shown above in your products database, you normally need not worry -- updates will be almost instantaneous. (See
 <EM>NoImport</EM> if you wish to stop auto updating.)

<P>
<HR>


code: 06.03
section: SETTING_UP_YOUR_CATALOG
type: item
title: On-the-fly pages, static, or both?

<A NAME="On_the_fly_pages_static_or_bot">On-the-fly pages, static, or both?</A></H2>
<P>
The on-the-fly page capability of MiniVend makes it easy to build your
catalog without hard-coding a single page. To build category pages, use the
one-click search and the search result page. To display information about
single items, use the flypage.html template. You can customize these pages
in many ways, and you can even use different templates for different types
of products -- define a product database field (with the
<EM>PageSelectField</EM> directive) to hold the name of the base on-the-fly page for that item. You
might define it to be the same as the category of product, for example.

<P>
If you have a large catalog, you will almost certainly want to use the on-the-fly page for most products. But if you want to mix in a few extra-special pages, perhaps for your best sellers, you can do so. Just build the pages and place them in files corresponding to the part number (in the MiniVend pages directory, of course -- not your 
<FONT SIZE=-1>HTML</FONT> directory). They will take precedence over the on-the-fly page.


<P>
If you have only a small number of products, hard coded pages are just fine, though you would be surprised how much of a maintenance headache they are compared to database definitions. Build them just about like normal 
<FONT SIZE=-1>HTML</FONT> pages, except for the MiniVend tags to order the item. Place them wherever they can be reached -- if you are using searches, you will want to name the file by the part number, or at least make a link to it.


<P>
Some other things you might put in:

<DL>
<DT><STRONG><A NAME="item_Images">Images</A></STRONG><DD>

You can easily place a thumbnail image (even with a link to a blowup) only
for those items that have them.

<P><DT><STRONG><A NAME="item_Accessories">Accessories</A></STRONG><DD>

The accessories database allows you to pre-define additional products to
offer with a main product.

<P><DT><STRONG><A NAME="item_Reviews">Reviews/Testimonials</A></STRONG><DD>

You can key the placement on the existence of a file in a certain
directory.

<P></DL>
<P>
<HR>


code: 06.04
section: SETTING_UP_YOUR_CATALOG
type: item
title: Use the demo catalogs

<A NAME="Use_the_demo_catalogs">Use the demo catalogs</A></H2>
<P>
The demo catalogs supplied with MiniVend are there to give you a starting
point for your own catalog. Play with them, change them, and rename them --
add your own icons, change flypage.html, change the results.html files,
etc.

<P>
<HR>


code: 06.05
section: SETTING_UP_YOUR_CATALOG
type: item
title: Tree design

<A NAME="Tree_design">Tree design</A></H2>
<P>
Determine how users will enter and exit your catalog. There are quite
complex and intelligent conditional schemes possible, especially if you use
the <EM>Cookies</EM> capability, but simplicity is often the easiest and most reliable.

<P>
The most important thing to remember is that if you are supporting browsers
which might not accept cookies, you must never send the user to a page that
is not served by MiniVend. If you do, they will lose their session (and
items in their shopping cart).

<P>
If you are using MiniVend's frames mode, you must be careful to source all
frame panes from a page served by MiniVend. If you do not, then you may
find the user has multiple session IDs depending on which frame the link
came from.

<P>
<HR>


code: 06.06
section: SETTING_UP_YOUR_CATALOG
type: item
title: The Essentials

<A NAME="The_Essentials">The Essentials</A></H2>
<P>
The rest of this section describes the rest of the things you need to know
to make the most basic of MiniVend catalogs, one which displays pages and
uses the demo shopping basket and checkout sequence. If you want to add
custom features, like special shipping charges and sales tax, you will need
to go much further. But this will get you started.

<P>
All of the mentioned features (and more) are demonstrated in the
<A HREF="#item_simple">simple</A> demo catalog.

<P>
<HR>


code: 06.07
section: SETTING_UP_YOUR_CATALOG
type: item
title: Catalog Pages -- MiniVend tags

<A NAME="Catalog_Pages_MiniVend_tags">Catalog Pages -- MiniVend tags</A></H2>
<P>
Pages in the catalog are written in regular 
<FONT SIZE=-1>HTML</FONT> with extensions to support catalog ordering. To distinguish them from regular 
<FONT SIZE=-1>HTML,</FONT> these extended elements use
 <CODE>[square brackets]</CODE> instead of angular brackets. We will usually call them <STRONG>MiniVend tags</STRONG> or just <STRONG>tags</STRONG>.

<P>
These tags perform various display and modification operations for the user
session. The tag names and their general function are:

<P>
<PRE>  accessories    Access product accessory functions
  area           Insert a re-written MiniVend URL
  areatarget     Insert a re-written MiniVend URL with frame
  body           Insert a predefined &lt;BODY ...&gt; HTML tag
  buttonbar      Insert a predefined buttonbar
  calc           Perform Perl calculations (low overhead)
    /calc
  cart           Set the current shopping cart name
  checked        Conditionally check an HTML check/radio box
  comment        Insert comments in MiniVend pages
    /comment
  compat         Define regions to be interpreted with old syntax
    /compat
  col            Used with [row] -- rudimentary text tables for order reports
    /col
  condition      Sets a condition inside [if explicit] and others
    /condition
  currency       Formats a number like currency for current locale
    /currency
  data           Access a database or user session element
  default        Insert a variable but with a default response if blank
  description    Output a product description
  discount       Set a product discount coupon
    /discount
  discount-price Show the discounted price
  else           Defines else region for [if ...], [if-field ..] and others
    /else
  elsif          Defines elsif region for [if ...]
    /elsif
  field          Access a product database field
  file           Insert the contents of a file
  finish-order   DEPRECATED. Conditionally show a &quot;check basket&quot; link.
  fly-list       Show an item &quot;on-the-fly&quot; in an arbitrary page
    /fly-list     (new tags mode only)
  framebase      DEPRECATED. Set a &lt;BASE FRAME=&quot;...&quot;&gt; only if in frames mode.
  frames-off     Turn off MiniVend frames mode.
  frames-on      Turn on MiniVend frames mode.
  help           DEPRECATED. Show a help message only if help is enabled.
  if             Perform any of many conditional tests
    /if
  if-data        Display region only if database element non-empty
    /if-data
  if-field       Display region only if field non-empty
    /if-field
  if-loop-data   Display region only if database element non-empty
    /if-loop-data
  if-loop-field  Display region only if field non-empty
    /if-loop-field
  if-modifier    Display only if item attribute/modifier set
    /if-modifier
  if-sql-data   Display region only if database element non-empty
    /if-sql-data
  if-sql-field  Display region only if field non-empty
    /if-sql-field
  include       Include a file with complete MiniVend interpretation
  item-accessories  Product accessory functions (set select box)
  item-code     Insert current item SKU/code/part number
  item-data     Insert data entry corresponding to current SKU
  item-description     Insert description corresponding to current SKU
  item-discount Show amount of discount for current SKU
  item-field    Insert product database entry corresponding to current SKU
  item-increment       Count for list
  item-last     Stop displaying if condition is met
    /item-last
  item-link     DEPRECATED. Auto-HTML link to product page.
  item-next     Skip item if condition is met
    /item-next
  item-list     Iterate over a shopping cart
    /item-list
  item-modifier Show value of item attribute/modifier
  item-param    DEPRECATED. Show element from positional list.
  item-price    Display price of item with any discounts/price breaks/adjustments
  item-quantity Show quantity ordered on shopping cart line
  item-subtotal Subtotal for the item (item-quantity * item-price)
  last-page     DEPRECATED.
    /last-page
  lookup        Lookup an item in a database if not already set
  loop          Iterate over an arbitrary list
    /loop
  loop-accessories  Product accessory functions (set select box)
  loop-change   Grouping of items in list display
    /loop-change
  loop-code     Insert current item SKU/code/part number
  loop-data     Insert data entry corresponding to current SKU
  loop-description  Insert description corresponding to current SKU
  loop-field    Insert product database entry corresponding to current SKU
  loop-increment      Count for list
  loop-last     Stop displaying if condition is met
    /loop-last
  loop-link     DEPRECATED. Auto-HTML link to product page.
  loop-next     Skip item if condition is met
    /loop-next
  loop-price    Display price of item
  matches       Show number of matches from search
  modifier-name Place a variable name that corresponds to an attribute
  more          Show region of search list only if more matches
  more-list     Display more matches list with links to next series
    /more-list
  sql           Perform any of several types of SQL query
  sql-code      Insert current item SKU/code/part number
  sql-data      Insert data entry corresponding to current SKU
  sql-description  Insert description corresponding to current SKU
  sql-field     Insert product database entry corresponding to current SKU
  sql-increment      Count for list
  sql-link      DEPRECATED. Auto-HTML link to product page.
  sql-param     Show element from returned SQL queries.
  sql-price     Display price of item
  no-match      Define area of search results page displayed when no match
    /no-match
  new           Set new syntax for this page
  nitems        Show number of items for a shopping cart
  old           Set old syntax for this page
  order         Create HTML link to order an item
    /order
  on-change     Grouping of items in list display
    /on-change
  page          Create A HREF with re-written URL to call MiniVend page
    /page
  pagetarget    Create A HREF with re-written URL for frames MiniVend page
    /pagetarget
  perl          Embed output of arbitrary Perl in the page
    /perl
  post          DEPRECATED. Force region to be interpreted last.
    /post
  price         Show price of an item
  process-order Create URL for MiniVend form processing, retain security setting
  process-search Create URL to call MiniVend form-based search
  process-target Create URL to call MiniVend form processing
  quantity-name  Place a variable name that corresponds to item quantity
  random        Insert a random banner
  rotate        Insert a rotating banner
  row           Used with [col] -- rudimentary text tables for order reports
    /row
  salestax      Show amount of salestax for shopping cart
  scratch       Access a scratch variable
  search        Do a MiniVend search, output list of returned item codes
  search-list   Display output of a MiniVend search
    /search-list
  selected      Conditional selection of drop-down &lt;SELECT ...&gt;
  set           Set a scratch variable
    /set
  shipping      Calculate shipping
  shipping-desc Show shipping description
  sort          Set sort order for iterating lists
    /sort
  subtotal      Calculate subtotal without tax or shipping
  tag           Miscellaneous functions
    /tag
  then          Define THEN region for [if ...]
    /then
  total-cost    Calculate order total with tax, handling, and shipping
  uniq          Remove duplicate search returns
  userdb        Access user database functions
  value         Display form value
</PRE>
<P>
The syntax for each tag is displayed in the documentation below.

<P>
The first page displayed in the catalog, if no argument is supplied to the <CODE>vlink</CODE> or <CODE>tlink</CODE> cgi-bin program, is ``catalog.html''. This page will contain links to other
catalog pages with the <CODE>[page pagename]</CODE> tag. Individual products can be ordered by the <CODE>[order &lt;item-code</CODE>]&gt; element, which brings up the shopping basket page. The shopping
basket page contains an <CODE>[item-list]</CODE>, which builds information on each item ordered, and optionally has input
boxes for the customer to type in their name and address. If desired, the
customer can be ``stepped through'' the order process (as is demonstrated
in the supplied demos). Once the order has been sent the receipt page is
displayed.

<P>
Unless you are using the 
<FONT SIZE=-1>HTTP</FONT> cookie support, you will normally not want to
include regular hypertext links to pages outside of the catalog. Such links
will not include the session id, which means that if the customer follows
an external link back to the catalog the list of products ordered so far
will have been lost.

<P>
Inline images, on the other hand, are served in the normal fashion. You
should include a regular &lt;
<FONT SIZE=-1>IMG</FONT> 
<FONT SIZE=-1>SRC=``URL''&gt;</FONT> element, where the 
<FONT SIZE=-1>URL</FONT> refers to a graphic image. You cannot use relative image names as you would in an 
<FONT SIZE=-1>HTML</FONT> document! MiniVend has the capability of defining an image directory (with the

<EM>ImageDir</EM> and <EM>ImageDirSecure</EM> directives) that automatically adjusts your image path to a set base
directory.

<P>
MiniVend has a powerful static page-building capability. This allows you to pre-build catalog pages that don't contain dynamic elements (such as order/shopping basket status) into 
<FONT SIZE=-1>HTML,</FONT> then automatically point the browser to those pages when appropriate. This reduces the number of pages that MiniVend must parse in real time, and can increase server capacity by orders of magnitude. See
 <EM>STATIC PAGE BUILDING</EM>.

<P>
<HR>


code: 06.08
section: SETTING_UP_YOUR_CATALOG
type: item
title: Cookies

<A NAME="Cookies">Cookies</A></H2>
<P>
All you need to do to have users with cookie-capable browsers retain
session context is enable the <EM>Cookies</EM> directive. You can then intermix standard 
<FONT SIZE=-1>HREF</FONT> and MiniVend page links without fear of losing
the shopping basket. Cookie capability is also required to use search
caching, page caching, and statically generated pages. If the browser does
not support cookies, the cache will be ignored.

<P>
If you plan to use more than one host name <EM>within the same domain</EM> for naming purposes (perhaps a secure server and non-secure server) then
you can set the domain with the <EM>CookieDomain</EM> directive. This must contain at least two periods (.) as per the cookie
specification, and you cannot set a domain that your server is not located
within.

<P>
<HR>


code: 06.09
section: SETTING_UP_YOUR_CATALOG
type: item
title: Basic MiniVend Tags

<A NAME="Basic_MiniVend_Tags">Basic MiniVend Tags</A></H2>
<P>
<STRONG>NOTE:</STRONG> In the descriptions, parameters marked with an asterisk* are optional.

<P>
When a tag is separated by an underscore, as in <EM>item_list</EM>, a dash is just as appropriate (i.e. <CODE>item-list</CODE>). They are interchangeable, except that the ending tag and beginning tag
should match (don't use <CODE>[item-list] list [/item_list]</CODE>).


<STRONG>*</STRONG>  <EM>indicates an optional argument</EM>



<P><DL>
<DT><STRONG><A NAME="item__value">[value name=field escaped=1 set=&quot;new value&quot; hide=1]</A></STRONG><DD>

positional:  <CODE>[value field]</CODE>



<P>

<FONT SIZE=-1>HTML</FONT> examples:

<P>
<PRE>   &lt;PARAM MV=&quot;value name&quot;&gt;
   &lt;INPUT TYPE=&quot;text&quot; NAME=&quot;name&quot; VALUE=&quot;[value name]&quot;&gt;
</PRE>
<P>
Expands into the current value of the customer/form input field named by
field.If the <CODE>set</CODE> value is present, the form variable value will be set to it and the new value returned. Use this to ``uncheck'' a checkbox or set other form variable values to defaults. If 
<FONT SIZE=-1>HIDE</FONT> is set, the value will be set but not returned to the page.


<P>
If <CODE>escaped</CODE> is 1, single quotes will be escaped with a backslash; this allows you to
contain the <A HREF="#item__value_">[value ...]</A> tag within single quotes. (It is somewhat better to use other Perl quoting
methods like <CODE>q{[value whatever]}</CODE>.)

<P>
When the value is returned, any MiniVend tags present in the value will be
escaped. This prevents users from entering MiniVend tags in form values,
which would be a serious security risk.

<P><DT><STRONG><A NAME="item__page">[page ...]</A></STRONG><DD>

named: [page href=``dir/page'' arg=``argument'' secure=1* form=``form
string'']

<P>
positional: [page dir/page arg*] (only two positional parameters)

<P>

<FONT SIZE=-1>HTML</FONT> example: 
<FONT SIZE=-1>&lt;A</FONT> MV=``page'' MV.HREF=``dir/page'' MV.ARG=``arg''* HREF=``dir/page.html''&gt;


<P>
Insert a hyperlink to the specified catalog page pg. For example, [page
shirts] will expand into &lt; a
href=``http://machine.company.com/cgi-bin/vlink/shirts?WehUkATn;;1''&gt;.
The catalog page displayed will come from ``shirts.html'' in the pages
directory.

<P>
If the user has sent a cookie to MiniVend (meaning the <STRONG>second</STRONG> page they access), and you set the scratch value c&lt;mv_no_session_id&gt; in their session, the session 
<FONT SIZE=-1>ID</FONT> will not be appended to the 
<FONT SIZE=-1>URL.</FONT> If you set the scratch value
 <CODE>mv_no_count</CODE>, then the page count will not be appended; this is not dependent on
cookies. So if you put in your initial page

<P>
<PRE>        [set mv_no_session_id]1[/set]
        [set mv_no_count]1[/set]
</PRE>
<P>
no session 
<FONT SIZE=-1>ID</FONT> or count will be shown. That makes the 
<FONT SIZE=-1>URL</FONT> shown above be <A HREF="http://machine.company.com/cgi-bin/vlink/shirts">http://machine.company.com/cgi-bin/vlink/shirts</A> -- once again, that is on the
 <EM>second</EM> page the user accesses if they are taking and sending cookies. If the user has a pre-existing 
<FONT SIZE=-1>MV_SESSION_ID</FONT> cookie from a prior session, the effect will be immediate.


<P>
The <CODE>argument</CODE> will be passed to MiniVend and placed in the
<A HREF="#item_arg">arg</A> session parameter. This allows programming of a conditional page display
based on where the link came from. The argument is then available with the
tag [data session arg], or the embedded Perl session variable
$Safe{'session'}-&gt;{arg}. If you set the catalog configuration option
<EM>NewEscape</EM>, which is the default, then spaces and some other characters will be
escaped with the <CODE>%NN</CODE> HTTP-style notation and unescaped when
the argument is read back into the session.

<P>

<FONT SIZE=-1>A</FONT> bit of magic occurs if MiniVend has built a static plain 
<FONT SIZE=-1>HTML</FONT> page for the target page. Instead of generating a normal MiniVend-parsed page reference, a static page reference will be inserted if the user has accepted and sent back a cookie with the session 
<FONT SIZE=-1>ID.</FONT>


<P>
The optional <CODE>form</CODE> argument allows you to encode a form in the link.

<P>
<PRE>        [page form=&quot;
                mv_order_item=99-102
                mv_order_size=L
                mv_order_quantity=1
                mv_separate_items=1
                mv_todo=refresh&quot;] Order t-shirt in Large size &lt;/A&gt;
</PRE>
<P>
The two form values <EM>mv_session_id</EM> and <EM>mv_arg</EM> are automatically added when appropriate. (<EM>mv_arg</EM> is the <A HREF="#item_arg">arg</A> parameter for the tag.)

<P>
If the parameter <CODE>href</CODE> is not supplied, <EM>process</EM> is used, causing normal MiniVend form processing. If the <CODE>href</CODE> points to an http:// link no MiniVend 
<FONT SIZE=-1>URL</FONT> processing will be done, but the mv_session_id

<P>
This would generate a form that ordered item number 99-102 on a separate
line (<CODE>mv_separate_items</CODE> being set), with size <CODE>L</CODE>, in quantity 2. Since the page is not set, you will go to the default
shopping cart page -- equally you could set <CODE>mv_orderpage=yourpage</CODE>
to go to <CODE>yourpage</CODE>.

<P>
You must have TolerateGet set (which is the default) and all normal
MiniVend form caveats apply -- you must have an action, you must supply a
page if you don't want to go to the default, etc.

<P>
You can theoretically submit any form with this, though none of the
included values can have newlines or trailing whitespace. If you want to do
something like that you will have to write a UserTag.

<P>
You can also use it for submitting foreign forms if you like; it will not
touch the href if it begins with http:, ftp:, or the like.

<P>

code: 06.10
section: SETTING_UP_YOUR_CATALOG
type: item
title: Where do I go from here?

<A NAME="Where_do_I_go_from_here_">Where do I go from here?</A></H2>
<P>
MiniVend is very complicated but very powerful. If you have read and
understood the documentation so far, you have a good start on building a
catalog. There are many, many, more features than are shown in the demo,
and mastering the ones you need will take time. Thousands of people have
built MiniVend catalogs -- you can too. If you feel it is beyond you, then
we would suggest engaging a competent consultant. Good luck!

<P>
<HR>


code: 06.10
section: SETTING_UP_YOUR_CATALOG
type: item
title: [area ...]

<A NAME="_area_">[area ...]</A></H2>

named: [area href=``dir/page'' secure=1* arg=``argument''* form=``form
string''*]

<P>
positional: [area pg arg*]

<P>

<FONT SIZE=-1>HTML</FONT> example: 
<FONT SIZE=-1>&lt;A</FONT> MV=``area dir/page'' HREF=``dir/page.html''&gt;


<P>
Produces the 
<FONT SIZE=-1>URL</FONT> to call a MiniVend page, without the surrounding 
<FONT SIZE=-1>A</FONT> 
<FONT SIZE=-1>HREF</FONT> notation. This can be used to get control of your 
<FONT SIZE=-1>HREF</FONT> items, perhaps to place an 
<FONT SIZE=-1>ALT</FONT> string or a Javascript construct. It was originally named
 <CODE>area</CODE> because it also can be used in a client-side image map.

<P>
<PRE>   &lt;A HREF=&quot;[area catalog]&quot; ALT=&quot;Main catalog page&quot;&gt;
</PRE>
<P>
The optional <EM>arg</EM> is used just as in the <EM>page</EM> tag.

<P>
The optional <CODE>form</CODE> argument allows you to encode a form in the link.

<P>
<PRE>        &lt;A HREF=&quot;[area form=&quot;
                mv_order_item=99-102
                mv_order_size=L
                mv_order_quantity=1
                mv_separate_items=1
                mv_todo=refresh&quot;
        ]&quot;&gt; Order t-shirt in Large size &lt;/A&gt;
</PRE>
<P>
See above for more information.

<P><DT><STRONG><A NAME="item__page_">[/page], [/area]</A></STRONG><DD>

Expands into &lt;/a&gt;. Used with the page element, such as:

<P>
<PRE>  [page shirts]Our shirt collection[/page].
</PRE>
<P>

<FONT SIZE=-1>TIP:</FONT> 
<FONT SIZE=-1>A</FONT> small efficiency boost in large pages is to just use the 
<FONT SIZE=-1>&lt;/A&gt;</FONT> tag.


<P></DL>
<P>
<HR>


code: 06.11
section: SETTING_UP_YOUR_CATALOG
type: item
title: How to order an item

<A NAME="How_to_order_an_item">How to order an item</A></H2>
<P>
MiniVend can either use a form-based order or a link-based order to place
an item in the shopping cart. The link-based order uses the special <CODE>[order item-code]</CODE> tag:

<DL>
<DT><STRONG><A NAME="item__order">[order code cart/page* database*]</A></STRONG><DD>

named attributes: <CODE>[order code=&quot;code&quot; href=&quot;cart/page&quot; base=&quot;database&quot;]</CODE>



<P>

<FONT SIZE=-1>HTML</FONT> example: 
<FONT SIZE=-1>&lt;A</FONT> MV=``order code'' HREF=``ord/basket''&gt;


<P>
Expands into a hypertext link which will include the specified code in the
list of products to order and display the order page. <STRONG>code</STRONG>
should be a product code listed in one of the ``products'' databases. The
optional argument <STRONG>cart/page</STRONG> selects the shopping cart the item will be placed in (begin with / to use
the default cart <CODE>main</CODE>) and the order page that will display the order. The optional argument <STRONG>database</STRONG> constrains the order to a particular products file -- if not specified, all
databases defined as products files will be searched in sequence for the
item.

<P>
Example:

<P>
<PRE>  Order a [order TK112]Toaster[/order] today.
</PRE>
<P>
Note that this is the same as:

<P>
<PRE>  Order a [page order TK112]Toaster&lt;/A&gt; today.
</PRE>
<P>
You can change frames for the order with:

<P>
<PRE>  Order a &lt;A HREF=&quot;[area order TK112]&quot; TARGET=newframe&gt;Toaster&lt;/A&gt; today.
</PRE>
<P><DT><STRONG><A NAME="item__order_">[/order]</A></STRONG><DD>

Expands into &lt;/a&gt;. Used with the order element, such as: Buy a
<CODE>[order TK112]</CODE>Toaster<A HREF="#item__order_">[/order]</A> today.

<P></DL>
<P>
To order with a form, you set the form variable <CODE>mv_order_item</CODE> to the item-code/SKU and use the <A HREF="#item_refresh">refresh</A> action:

<P>
<PRE>  &lt;FORM ACTION=&quot;[process-target]&quot; METHOD=POST&gt;
  &lt;INPUT TYPE=hidden  NAME=&quot;mv_todo&quot;        VALUE=&quot;refresh&quot;&gt;
  &lt;INPUT TYPE=hidden  NAME=&quot;mv_order_item&quot;  VALUE=&quot;TK112&quot;&gt;
 
  Order &lt;INPUT NAME=&quot;mv_order_quantity&quot; SIZE=3 VALUE=1&gt; toaster
 
  &lt;INPUT TYPE=submit VALUE=&quot;Order!&quot;&gt;
  &lt;/FORM&gt;
</PRE>
<P>
You may also specify attributes like size or color at time of order, and
may batch select whole groups of items. Read further to see how, or order
the T-shirt from the more details page of the <A HREF="#item_simple">simple</A> demo to see how it is done.

<P>
<HR>


code: 07.00
section: SETTING_UP_YOUR_CATALOG
type: overview
title: SETTING UP YOUR CATALOG

<A NAME="SETTING_UP_YOUR_CATALOG">SETTING UP YOUR CATALOG</A></H1>
<P>
MiniVend uses its own tags to implement catalog functions -- they are similar to normal 
<FONT SIZE=-1>HTML,</FONT> but are in
 <CODE>[square brackets]</CODE>. They will be referred to as either <EM>tags</EM> or <EM>elements</EM> in this document.

<P>
In order to set up a custom catalog, there are a number of steps.

<P>
You will need to become familiar with the MiniVend tags and directives to
make your own catalog. The demo catalogs are a good starting point, but are
not a finished product.

<P>
<HR>


code: 07.02
section: DATABASES
type: item
title: The Product Database

<A NAME="The_Product_Database">The Product Database</A></H2>
<P>
Each product you are selling should be given a product code: 
<FONT SIZE=-1>A</FONT> short code that identifies the product on the
ordering page and in the catalog. You can use any combination of letters,
digits, dashes, periods, hash signs, or underscores for the product code.
The
<EM>products.asc</EM> file is a ASCII-delimited list of all the product codes, along with an
arbitrary number of fields which must contain at least the fields <A HREF="#item_description">description</A> and <CODE>price</CODE> (or whatever you set the PriceField and DescriptionField directives to).
Any additional information you want in the catalog can be placed in any
arbitrary field. See <EM>MiniVend Database Capability</EM>for details on the format.

<P>
Field names are case-sensitive. Unless you have fields with the names
``description'' and ``price'' field, you will have to appropriately set the
<EM>PriceField</EM> and <EM>DescriptionField</EM> directives to use the <CODE>[item-price]</CODE>
and <CODE>[item-description]</CODE> tags.

<P>
The product code must be the first field in the line, and must be unique.
Product codes can contain the characters <STRONG>A-Za-z0-9</STRONG>, along with hyphen (<CODE>-</CODE>), underscore (<CODE>_</CODE>), pound sign/hash mark (<CODE>#</CODE>), slash (<CODE>/</CODE>), and period (<CODE>.</CODE>).

<P>
The words should be separated by one of the approved delimiting schemes 
<FONT SIZE=-1>(TAB,</FONT> 
<FONT SIZE=-1>PIPE,</FONT> or 
<FONT SIZE=-1>CSV,</FONT> set with the
 <EM>Delimiter</EM> directive), and are case-sensitive. If you play with the case of the
``description'' or ``price'' field, you will have to appropriately set the <EM>PriceField</EM> and
<EM>DescriptionField</EM> directives.

<P>
<STRONG>NOTE:</STRONG> 
<FONT SIZE=-1>CSV</FONT> is not recommended as the scheme for the products database. It is much slower than 
<FONT SIZE=-1>TAB-</FONT> or PIPE-delimited, and dramatically reduces search engine functionality -- no field-specific searches are possible. Don't use it unless you know
 <STRONG>exactly</STRONG> what you are doing -- you will be sorry if you do. Using 
<FONT SIZE=-1>CSV</FONT> for any small database that will not be searched
is fine.


<STRONG>IMPORTANT NOTE:</STRONG> The field names must be on the first line of the
<CODE>products.asc</CODE> file. These field names must match <EM>exactly</EM> the field names of the <CODE>[item-field]</CODE> tags in your catalog pages, or the MiniVend server will not access them
properly. Field names can contain the characters <STRONG>A-Za-z0-9</STRONG>, along with hyphen (<CODE>-</CODE>), underscore (<CODE>_</CODE>), pound sign/hash mark (<CODE>#</CODE>), slash (<CODE>/</CODE>), and period (<CODE>.</CODE>).

<P>
As of MiniVend 3.0, more than one database may be used as a products
database. If the catalog directive <EM>ProductFiles</EM> is set to a space-separated list of valid MiniVend database identifiers,
those databases will be searched (in the order specified) for any items
that are ordered, or for product information (as in the <CODE>[price code]</CODE> and <CODE>[field code]</CODE> tags).

<P>
<P>
When the products.asc file changes after import or edit, the 
<FONT SIZE=-1>DBM</FONT> database is re-built upon the next user access. No
restart of the server is necessary.

<P>
If changing the database on the fly, it is recommended that you lock the
file while it is being modified.

<P>
<HR>


code: 07.03
section: DATABASES
type: item
title: Arbitrary Databases

<A NAME="Arbitrary_Databases">Arbitrary Databases</A></H2>
<P>
MiniVend can manage an unlimited number of arbitrary database tables. They
are in the same format as the products file by default, but an unlimited
number of addressable schemes are available. These are defined by default:

<P>
<PRE>    Type 1      DEFAULT - uses default delimiter set by Delimiter
    Type 2      LINE
                Each field on its own line, a blank line
                separates the record. Watch those carriage
                returns! Also has a special format when CONTINUE
                is set to be NOTES.
    Type 3      %%
                Fields separated by a \n%%\n combination, records by
                \n%%%\n (where \n is a newline). Watch those carriage
                returns!
    Type 4      CSV
    Type 5      PIPE
    Type 6      TAB
    Type 7      mSQL
    Type 8      SQL
</PRE>
<P>
The databases are specified in <EM>Database</EM> directives, as:

<P>
<PRE>    Database    Arbitrary arbitrary.csv CSV
</PRE>
<P>
That specifies a type 4 database, the 
<FONT SIZE=-1>ASCII</FONT> version of which is located in the file arbitrary.csv, and the identifier it will be accessed under in MiniVend is ``Arbitrary''. The 
<FONT SIZE=-1>DBM</FONT> file, if any, will be created in the
 <STRONG>same directory</STRONG> if the 
<FONT SIZE=-1>ASCII</FONT> file is newer, or if the 
<FONT SIZE=-1>DBM</FONT> file does not exist. The files will be created as arbitrary.db or arbitrary.gdbm, depending on 
<FONT SIZE=-1>DBM</FONT> type.


<P>
The <A HREF="#item_identifier">identifier</A> is case sensitive, and can only contain characters in the class [<STRONG>A-Za-z0-9_</STRONG>]. Fields are accessed with the [item_data <A HREF="#item_identifier">identifier</A> field] or [data <A HREF="#item_identifier">identifier</A> field key] elements.

<P>
<HR>


code: 07.04
section: DATABASES
type: item
title: MiniVend built-in database support

<A NAME="MiniVend_built_in_database_suppo">MiniVend built-in database support</A></H2>
<P>
If you specify one of the first 6 types, the database will automatically be built in the default MiniVend 
<FONT SIZE=-1>DB</FONT> style. You cannot mix the styles -- all built-in databases on a single server will be the same style. They will coexist just fine with an unlimited number of 
<FONT SIZE=-1>DBI</FONT> databases of different types.


<P>
In addition to the database, the session files will be kept in the default
format, and are affected by the actions below.

<P>
The order of preference is:

<DL>
<DT><STRONG><A NAME="item_GDBM">GDBM</A></STRONG><DD>

This uses the Perl GDBM_File module to build a 
<FONT SIZE=-1>GDBM</FONT> database. You can see if 
<FONT SIZE=-1>GDBM</FONT> is in your perl with the command:


<P>
<PRE>    perl -e 'require GDBM_File and print &quot;I have GDBM.\n&quot;'
</PRE>
<P>
Installing GDBM_File requires rebuilding Perl after obtaining the 
<FONT SIZE=-1>GNU</FONT> 
<FONT SIZE=-1>GDBM</FONT> package, and is beyond the scope of this forum. Linux will typically have this by default -- most other operating systems will need to specifically build this in.


<P><DT><STRONG><A NAME="item_DB_File">DB_File (Berkeley DB)</A></STRONG><DD>

This uses the DB_File module to build a Berkeley 
<FONT SIZE=-1>DB</FONT> (hash) database. You can see if DB_File is in your
perl with the command:

<P>
<PRE>    perl -e 'require DB_File and print &quot;I have Berkeley DB.\n&quot;'
</PRE>
<P>
Installing DB_File requires rebuilding Perl after obtaining the Berkeley 
<FONT SIZE=-1>DB</FONT> package, and is beyond the scope of this document. 
<FONT SIZE=-1>BSDI,</FONT> FreeBSD, and Linux will typically have it by default -- most other operating systems will need to specifically build this in.


<P>
If you wish to use DB_File even though you have GDBM_File in your Perl, you must set the environment variable 
<FONT SIZE=-1>MINIVEND_DBFILE</FONT> to a true (non-zero, non-blank) value:


<P>
<PRE>    # csh or tcsh
    setenv MINIVEND_DBFILE 1
</PRE>
<P>
<PRE>    # sh, bash, or ksh
    MINIVEND_DBFILE=1 ; export MINIVEND_DBFILE
</PRE>
<P>
Then re-start the server.

<P><DT><STRONG><A NAME="item_In">In-memory</A></STRONG><DD>

This uses Perl hashes to store the data directly in memory. Every time you
restart the MiniVend server, it will re-import all in-memory databases for
every catalog.

<P>
If you wish to use this despite the presence of GDBM_File or DB_File, set the environment variable 
<FONT SIZE=-1>MINIVEND_NODBM</FONT> as above, then re-start the server.


<P></DL>
<P>
<HR>


code: 07.05
section: DATABASES
type: item
title: Character usage restrictions

<A NAME="Character_usage_restrictions">Character usage restrictions</A></H2>
<P>
To review, database identifiers, field names, and product codes (database keys) are restricted in the characters they may use. 
<FONT SIZE=-1>A</FONT> short table showing restrictions:


<P>
<PRE>                                       Legal characters
                                       ---------------------
    Database identifiers               A-Z a-z 0-9 _
    Field names                        A-Z a-z 0-9 _ # - . /
    Database keys (product code/SKU)   A-Z a-z 0-9 _ # - . /
    Database values                    Any (subject to field/record delimiter)
</PRE>
<P>
You probably should restrict the field names to the same set of characters as database identifiers -- this will prevent conflict with external database programs, noticeably 
<FONT SIZE=-1>SQL</FONT> databases which use the period (.) as a table.field separator.


<P>
<HR>


code: 07.06
section: DATABASES
type: item
title: Import Attributes

<A NAME="Import_Attributes">Import Attributes</A></H2>
<P>
Especially in 
<FONT SIZE=-1>SQL</FONT> databases, there are certain things that can be set with additional database attributes. For text import, the 
<FONT SIZE=-1>CONTINUE</FONT> extended database import attribute allows additional control over the format of imported text.


<P>

<FONT SIZE=-1>NOTE:</FONT> 
<FONT SIZE=-1>CONTINUE</FONT> applies to all types except 
<FONT SIZE=-1>CSV.</FONT> (You won't want to use 
<FONT SIZE=-1>NOTES</FONT> unless using type 
<FONT SIZE=-1>LINE.)</FONT>


<DL>
<DT><STRONG><A NAME="item_CONTINUE">CONTINUE</A></STRONG><DD>

One of 
<FONT SIZE=-1>UNIX,</FONT> 
<FONT SIZE=-1>DITTO,</FONT> 
<FONT SIZE=-1>LINE,</FONT> 
<FONT SIZE=-1>NONE,</FONT> or 
<FONT SIZE=-1>NOTES.</FONT> The default, 
<FONT SIZE=-1>NONE,</FONT> is to simply split the line/record according to the delimiter, with no possible spanning of records. Setting 
<FONT SIZE=-1>CONTINUE</FONT> to 
<FONT SIZE=-1>UNIX</FONT> appends the next line to the current when it encounters a backslash (
<CODE>\</CODE>) at the end of a record, just like many Unix commands and shells.

<P>

<FONT SIZE=-1>DITTO</FONT> is invoked when the key field is blank -- it
adds the contents of following fields to the one above, separated by a
newline character. This allows additional text to be added to a field
beyond the 255 characters available with most spreadsheets and flat-file
databases.

<P>
Example in catalog.cfg:

<P>
<PRE>  Database products products.asc  TAB
  Database products CONTINUE      DITTO
</PRE>
<P>
Products.asc file:

<P>
<PRE>  code     price     description
  00-0011  500000    The Mona Lisa, one of the worlds great masterpieces.
                     Now at a reduced price!
</PRE>
<P>
The description for product 00-0011 will contain the contents of the
<A HREF="#item_description">description</A> field on both lines, separated by a newline.

<P>

<FONT SIZE=-1>NOTE:</FONT> Fields are separated by tabs, formatted for
reading convenience.

<P>
This <EM>will</EM> work for multiple fields in the same record. If the field contains any
non-empty value, it will be appended.

<P>

<FONT SIZE=-1>LINE</FONT> is a special setting so that you can use a multi-line field. Normally, when using the 
<FONT SIZE=-1>LINE</FONT> type, you may have only data on one line separated by one blank line. When using 
<FONT SIZE=-1>CONTINUE</FONT> 
<FONT SIZE=-1>LINE,</FONT> you may have some number of fields which are each on a line, while the last one spans multiple lines up until the first blank line.


<P>
Example in catalog.cfg:

<P>
<PRE>  Database products products.asc  LINE
  Database products CONTINUE      LINE
</PRE>
<P>
Products.asc file:

<P>
<PRE>    code
    price
    description
  
    00-0011
    500000
    The Mona Lisa, one of the worlds great masterpieces.
    Now at a reduced price!
  
    00-0011a
    1000
    A special frame for the Mona Lisa.
</PRE>
<P>
<STRONG>NOTES</STRONG> reads a Lotus Notes ``structured text'' file. The format is that there are
any number of fields, all except one of which must have a field name
followed by a colon and then the data. There is optional whitespace after
the colon.

<P>
Records are separated by a settable delimiting charater which goes on a line by itself, much like a ``here document''. By default it is a form feed 
<FONT SIZE=-1>(^L)</FONT> character.


<P>
The final field begins at the first blank line and continues to the end of
the record. This final field is named <CODE>notes_field</CODE>
unless you set it as mentioned below.

<P>
MiniVend reads the field names from the first paragraph of the file. The
key field should be first, followed by other fields in any order. If one
(and only one) field name has whitespace, then its name is used for the <CODE>notes_field</CODE> and any characters after a space or 
<FONT SIZE=-1>TAB</FONT> are used as the record delimiter. If there are none, then the delimiter returns to the default form feed 
<FONT SIZE=-1>(^L)</FONT> and the field name reverts to
 <CODE>notes_field</CODE>. The field in question will be discarded, but a second field with
whitespace will cause an import error.

<P>
Following records are then read by name, and only fields with data in them
need be set. Only the <CODE>notes_field</CODE> may contain a newline. It is always the last field in the record, and
begins at the <STRONG>first</STRONG> blank line.

<P>
The following example sets the delimiter to a tilde <CODE>(~)</CODE> and renames the <CODE>notes_field</CODE> to <A HREF="#item_description">description</A>.

<P>
Example in catalog.cfg:

<P>
<PRE>  Database products products.asc  LINE
  Database products CONTINUE      NOTES
</PRE>
<P>
Products.asc file:

<P>
<PRE>    code
    title
    price
    image
    description ~
    size
    color
  
    title: Mona Lisa
    price: 500000
    code: 00-0011
    image: 00-0011.jpg
  
    The Mona Lisa, one of the worlds great masterpieces.
    Now at a reduced price!
    ~
    title: The Art Store T-Shirt
    code: 99-102
    size: Medium, Large*, XL=Extra Large
    color: Green, Blue, Red, White*, Black
    price: 2000
  
    Extra large 1.00 extra.
    ~
</PRE>
<P><DT><STRONG><A NAME="item_EXCEL">EXCEL</A></STRONG><DD>

Microsoft Excel insists on surrounding any exported field that contains a comma with quotes, even for TAB-delimited exports. Set the 
<FONT SIZE=-1>EXCEL</FONT> attribute to 1 to fix this on import:


<P>
<PRE>    Database products EXCEL 1
</PRE>
<P>
This is normally used only with TAB-delimited files.

<P></DL>
<P>
<HR>


code: 07.07
section: DATABASES
type: item
title: Dictionary indexing with INDEX

<A NAME="Dictionary_indexing_with_INDEX">Dictionary indexing with INDEX</A></H2>
<P>
MiniVend will automatically build index files for a fast binary search of
an individual field. This type of search is useful for looking up the
author of a book based on the beginning of their last name, a book title
based on its beginning, or other analagous situations.

<P>
Such a search requires a dictionary ordered index with the field to be
searched contained in the first field and the database key (product code)
in the second field. If you specify the <CODE>INDEX field</CODE> modifier MiniVend will build the index upon database import:

<P>
<PRE>   Database  products  products.asc   TAB
   Database  products  INDEX          title
</PRE>
<P>
If the <CODE>title</CODE> field is the fourth column in the <A HREF="#item_products">products</A> database table, a file <CODE>products.asc.4</CODE> will be built, containing two tab-separated fields something like:

<P>
<PRE>    American Gothic   19-202
    Mona Lisa         00-0011
    Sunflowers        00-342
    The Starry Night  00-343
</PRE>
<P>
The fast binary search is described in greater detail below -- see 
<EM>THE SEARCH ENGINE</EM>.

<P>
<HR>


code: 07.08
section: DATABASES
type: item
title: MEMORY for memory-only databases

<A NAME="MEMORY_for_memory_only_databases">MEMORY for memory-only databases</A></H2>
<P>
MiniVend's memory-based databases are the fastest possible way to organize and store data you will frequently use. To force a database to be built in memory instead of 
<FONT SIZE=-1>DBM,</FONT> use the 
<FONT SIZE=-1>MEMORY</FONT> modifier:


<P>
<PRE>   Database  country  country.asc   TAB
   Database  country  MEMORY        1
</PRE>
<P>
Obviously large tables will use a great deal of memory, and the data will need to be re-imported from the 
<FONT SIZE=-1>ASCII</FONT> source file at every catalog reconfiguration or MiniVend restart. The big advantage of using 
<FONT SIZE=-1>MEMORY</FONT> is that the database remains open at all times and does not need to be reinitialized at every connect -- use it for smaller tables that will be frequently accessed.


<P>
The 
<FONT SIZE=-1>MEMORY</FONT> modifier forces 
<FONT SIZE=-1>IMPORT_ONCE.</FONT>


<P>
<HR>


code: 07.09
section: DATABASES
type: item
title: IMPORT_ONCE

<A NAME="IMPORT_ONCE">IMPORT_ONCE</A></H2>
<P>
The 
<FONT SIZE=-1>IMPORT_ONCE</FONT> modifier tells MiniVend not to re-import the database from the 
<FONT SIZE=-1>ASCII</FONT> file every time it changes. Normally, MiniVend does a comparison of the database file modification time with the 
<FONT SIZE=-1>ASCII</FONT> source every time it is accessed, and if the 
<FONT SIZE=-1>ASCII</FONT> source is newer it will re-import the file. 
<FONT SIZE=-1>IMPORT_ONCE</FONT> tells it only to import on a server restart or catalog reconfiguration:


<P>
<PRE>   Database  products  products.asc   TAB
   Database  products  IMPORT_ONCE    1
</PRE>
<P>

<FONT SIZE=-1>SQL</FONT> databases don't normally need this -- they will
only be imported once in normal operation. Also see <EM>NoImport</EM> for a way to guarantee that the table will never be imported.

<P>

<FONT SIZE=-1>IMPORT_ONCE</FONT> is always in effect for 
<FONT SIZE=-1>MEMORY</FONT> databases. Do a catalog reconfiguration to force a change.


<P>
<HR>


code: 07.10
section: DATABASES
type: item
title: Importing in a page

<A NAME="Importing_in_a_page">Importing in a page</A></H2>
<P>
You might often want to add a data record to a database as a result of an
order or other operation. Use MiniVend's <CODE>[import ...]</CODE> tag.

<DL>
<DT><STRONG><A NAME="item__import">[import table type*] RECORD [/import]</A></STRONG><DD>

Named attributes:

<P>
<PRE> [import table=table_name
         file=filename*
         type=(TAB|PIPE|CSV|%%|LINE)*
         continue=(NOTES|UNIX|DITTO)*
         separator=c*]
</PRE>
<P></DL>
<P>
Import one or more records into a database. The <A HREF="#item_type">type</A> is any of the valid MiniVend delimiter types, with the default being
defined by the setting of <EM>Delimiter</EM>. The table must already be a defined MiniVend database table; it cannot be created on the fly. (If you need that, it is time to use 
<FONT SIZE=-1>SQL.)</FONT>


<P>
The import type selected need not match the type the database was
specified; different delimiters may be used.

<P>
The <A HREF="#item_type">type</A> of <CODE>LINE</CODE> and <CODE>continue</CODE> setting of <CODE>NOTES</CODE> is particularly useful, for it allows you to name your fields and not have
to remember the order in which they appear in the database. The following
two imports are identical in effect:

<P>
<PRE>    [import table=orders]
             code: [value mv_order_number]
    shipping_mode: [shipping-description]
           status: pending
    [/import]
  
    [import table=orders]
    shipping_mode: [shipping-description]
    status:        pending
    code:          [value mv_order_number]
    [/import]
</PRE>
<P>
The <A HREF="#item_code">code</A> or key must always be present, and is always named <A HREF="#item_code">code</A>.

<P>
If you do not use <CODE>NOTES</CODE> mode, you must import the fields in the same order as they appear in the 
<FONT SIZE=-1>ASCII</FONT> source file.

<P>
The <A HREF="#item_file">file</A> option overrides the container text and imports directly from a named file <EM>based in the catalog directory</EM>. Careful, if you want to import from <CODE>products.asc</CODE> you must specify
<CODE>file=&quot;products/products.asc&quot;</CODE>. If the <EM>NoAbsolute</EM> directive is set to <CODE>Yes</CODE> in minivend.cfg, only relative path names will be allowed.

<P>
The <CODE>[import ....] TEXT [/import]</CODE> region may contain multiple records. If using <CODE>NOTES</CODE> mode, you must use a separator, which by default is a form-feed character 
<FONT SIZE=-1>(^L).</FONT> See <EM>Import Attributes</EM> above for more information.

<P>
<HR>


code: 07.11
section: DATABASES
type: item
title: Exporting from a database

<A NAME="Exporting_from_a_database">Exporting from a database</A></H2>
<P>
To export your existing database to a file suitable for searching by
MiniVend, you can create an <EM>AdminPage</EM> (or any page, for that matter) that contains a <CODE>[tag export ...][/tag]</CODE> element.

<P>
Perhaps a better method is to define the same sort of tags in an
<EM>OrderProfile</EM>, and then use forms and buttons to access the profile.

<P>
<HR>


code: 07.11
section: DATABASES
type: item
title: Global Databases

<A NAME="Global_Databases">Global Databases</A></H2>
<P>
If you have a database you want to make available to all catalogs on the MiniVend server instance, you may define a database in minivend.cfg. Any catalog running under that server will be able to use it. Careful; it is writable by any catalog unless you use 
<FONT SIZE=-1>WRITE_CONTROL.</FONT>


<P>
<HR>


code: 07.12
section: DATABASES
type: item
title: Write Control

<A NAME="Write_Control">Write Control</A></H2>
<P>
MiniVend databases can be written in the normal course of events, either
using the <CODE>[import ...]</CODE> tag or with a tag like
<CODE>[data table=table column=field key=code value=new-value]</CODE>.

<P>
If you wish to control writing of a global database, or to a certain
catalog within a series of subcatalogs, or make one read only, you can do
so.

<P>
To enable write control:

<P>
<PRE>        Database   products  WRITE_CONTROL  1
</PRE>
<P>
Once that is done, you can make a database read only, which won't allow
writing even if <CODE>[tag flag write]products[/tag]</CODE> is specified:

<P>
<PRE>        Database   products  READ_ONLY  1
</PRE>
<P>
If you want to have control with <CODE>[tag flag write]products[/tag]</CODE>:

<P>
<PRE>        Database   products  WRITE_TAGGED  1
</PRE>
<P>
If you want to limit write to certain catalogs, you can set:

<P>
<PRE>        Database   products  WRITE_CATALOG  simple=0, sample=1
</PRE>
<P>
The ``simple'' catalog will not be able to write, while ``sample'' will if <CODE>[tag flag write]products[/tag]</CODE> is enabled.

<P>
If you want a database to be always writable without having to specify <CODE>[tag flag write] ... [/tag]</CODE>, then you can define:

<P>
<PRE>        Database   products  WRITE_ALWAYS  1
</PRE>
<P>
The default behavior of 
<FONT SIZE=-1>SQL</FONT> datbases is equivalent to 
<FONT SIZE=-1>WRITE_ALWAYS,</FONT> while the default for GDBM_File, DB_File, and Memory databases is equivalent to:


<P>
<PRE>        Database   products  WRITE_CONTROL 1
        Database   products  WRITE_TAGGED  1
</PRE>
<P>
<HR>


code: 08.00
section: DATABASES
type: overview
title: DATABASES

<A NAME="DATABASES">DATABASES</A></H1>
<P>
MiniVend, as with most powerful shopping cart programs, is all about
databases.

<P>

<FONT SIZE=-1>NOTE:</FONT> No other database besides MiniVend's internal one is needed. You may find that keeping your database in an 
<FONT SIZE=-1>SQL</FONT> manager makes it easier to integrate MiniVend with other tools. MiniVend is fully buzzword-equipped, but if you just want to maintain a spreadsheet with your product information, you can ignore the references to 
<FONT SIZE=-1>SQL,</FONT> 
<FONT SIZE=-1>DBI,</FONT> 
<FONT SIZE=-1>DBD,</FONT> and all of those other things and just modify the file products.asc appropriately.


<P>
This version of MiniVend implements the database in 
<FONT SIZE=-1>GDBM,</FONT> DB_File, 
<FONT SIZE=-1>SQL,</FONT> or in-memory format. If you have 
<FONT SIZE=-1>DBM,</FONT> large catalogs can be used without using too much memory. The 
<FONT SIZE=-1>DBM</FONT> files are built automatically when they change, from the the 
<FONT SIZE=-1>ASCII</FONT> source file. If you don't have either 
<FONT SIZE=-1>GDBM</FONT> or DB_File, or you set the environment variable 
<FONT SIZE=-1>MINIVEND_NODBM</FONT> before starting the server, an in-memory product database will be used. Catalogs of more than, say, 1,000 items will use large amounts of memory.


<P>

<FONT SIZE=-1>NOTE:</FONT> In the following descriptions, we will use the
following terms interchangeably:

<DL>
<DT><STRONG><A NAME="item_key">key, code</A></STRONG><DD>

Either one is a reference to the <STRONG>key</STRONG> for the database. In MiniVend this is often the product <STRONG>code</STRONG> or <STRONG>sku</STRONG>, which is the part number for the product. Other key values may be used to
generate relationships to other database tables.

<P>
It is required that the key be the first column of an 
<FONT SIZE=-1>ASCII</FONT> source file for 
<FONT SIZE=-1>GDBM,</FONT> Berkeley 
<FONT SIZE=-1>DB,</FONT> or in-memory built-in database formats. It is also strongly suggested that you keep that practice for 
<FONT SIZE=-1>SQL</FONT> databases, since MiniVend's import, export, and search facilities will work much better with that practice.


<P><DT><STRONG><A NAME="item_field">field, column</A></STRONG><DD>

This is a column of the database. One of the columns is always the key --
MiniVend prefers that the key be the first column. Field is an
interchangeable reference.

<P><DT><STRONG><A NAME="item_table">table, database</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> table in the database. Because of the evolution of
MiniVend from a single-table database to an access method for an unlimited
number of tables (and databases, for that matter), we will sometimes refer
to a table as a database. The only time <STRONG>database</STRONG> refers to something different is when describing that concept as it relates to 
<FONT SIZE=-1>SQL</FONT> -- where a database contains a series of tables. MiniVend cannot create 
<FONT SIZE=-1>SQL</FONT> databases, but given the proper permissions it may drop and create tables within that database.


<P></DL>
<P>
If necessary, MiniVend reads the data to place in tables from standard ASCII-delimited files. All of these 
<FONT SIZE=-1>ASCII</FONT> source files are kept in the products directory, normally
 <STRONG>products</STRONG> in the catalog directory (where catalog.cfg is).

<P>
<STRONG>NOTE:</STRONG> Microsoft Excel is a widely-used tool to maintain MiniVend databases, but
has several problems with its standard TAB-delimited export, like encasing
fields containing commas in quotes, generating extra carriage returns
embedded in records, and not including trailing blank fields. To avoid
problems, use a text-qualifier of <STRONG>none</STRONG>.

<P>
The 
<FONT SIZE=-1>ASCII</FONT> files can have 
<FONT SIZE=-1>^M</FONT> (carriage return) characters if desired, but must have a newline character at the
 <STRONG>end</STRONG> of the line to work -- Mac users uploading files must use 
<FONT SIZE=-1>ASCII</FONT> mode, not binary mode!

<P>
MiniVend sets the default 
<FONT SIZE=-1>ASCII</FONT> delimiter scheme with the <EM>Delimiter</EM>
directive, which can have one of three settings, 
<FONT SIZE=-1>TAB,</FONT> 
<FONT SIZE=-1>PIPE,</FONT> or 
<FONT SIZE=-1>CSV.</FONT>


<P>
<STRONG>IMPORTANT NOTE:</STRONG> The items must be separated by a <STRONG>single</STRONG> delimiter. The items are lined up for your reading convenience.

<DL>
<DT><STRONG><A NAME="item_TAB">TAB</A></STRONG><DD>

Fields separated by 
<FONT SIZE=-1>^I</FONT> characters. No whitespace should be at the
beginning of the line.

<P>
<PRE>    code    description             price   image
    SH543   Men's fine cotton shirt 14.95   shirts.jpg
</PRE>
<P><DT><STRONG><A NAME="item_PIPE">PIPE</A></STRONG><DD>

Fields separated by <CODE>|</CODE> characters. No whitespace should be at the beginning of the line.

<P>
<PRE>    code|description|price|image
    SH543|Men's fine cotton shirt|14.95|shirts.jpg
</PRE>
<P><DT><STRONG><A NAME="item_CSV">CSV</A></STRONG><DD>

Fields enclosed in quotes, separated by commas. No whitespace should be at
the beginning of the line.

<P>
<PRE>    &quot;code&quot;,&quot;description&quot;,&quot;price&quot;,&quot;image&quot;
    &quot;SH543&quot;,&quot;Men's fine cotton shirt&quot;,&quot;14.95&quot;,&quot;shirts.jpg&quot;
</PRE>
<P></DL>
<P>
<STRONG>NOTE:</STRONG> Using the default 
<FONT SIZE=-1>TAB</FONT> delimiter is highly recommended if you are planning on searching the 
<FONT SIZE=-1>ASCII</FONT> source file of the database. 
<FONT SIZE=-1>PIPE</FONT> works fairly well, but 
<FONT SIZE=-1>CSV</FONT> delimiter schemes cause problems with searching.


<P>
The <EM>Delimiter</EM> directive sets the default scheme, and should be set to one of those three values. 
<FONT SIZE=-1>TAB</FONT> is the default scheme.


<P>
<STRONG>IMPORTANT NOTE:</STRONG> Field names are usually case-sensitive. Unless you are consistent in the
names, you will have problems. All lower or all upper case names are
recommended.

<P>
MiniVend uses one mandatory database, the products database. It is by
default identified as <EM>products</EM> and the 
<FONT SIZE=-1>ASCII</FONT> source is kept in the file <CODE>products.asc</CODE> in the products directory. This file is also the default file for searching
with the <EM>THE SEARCH ENGINE</EM>.

<P>
MiniVend also has a number of standard but optional databases, some of
which are in fixed special formats:

<DL>
<DT><STRONG><A NAME="item_shipping">shipping.asc</A></STRONG><DD>

The database of shipping options if the <EM>CustomShipping</EM> directive is in use. This is a fixed-format database, and must be created
as specified. See <EM>SHIPPING</EM>.

<P><DT><STRONG><A NAME="item_salestax">salestax.asc</A></STRONG><DD>

The database of sales tax information if the <A HREF="#item__salestax_">[salestax]</A> tag is to be used. 
<FONT SIZE=-1>A</FONT> default is supplied -- caution, these things change!
This is a fixed-format database, and must be created as specified. See <EM>Sales Tax</EM>.

<P><DT><STRONG><A NAME="item_accessories">accessories.asc</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> simple auxiliary database keyed on the product code.
It's value is available via the <CODE>[item-accessories]</CODE> or <CODE>[accessories code]</CODE> tags. This is a fixed-format database, and must be created as specified.
See <EM>Accessories</EM>. The big advantage of this database is speed -- it is always retained in
memory. If you have a large number (many thousands) of items, use an <EM>Arbitrary Database</EM> instead.

<P><DT><STRONG><A NAME="item_pricing">pricing.asc</A></STRONG><DD>

The database of quantity pricing information. It must be defined as the
regular MiniVend database <STRONG>pricing</STRONG>, with the product code as the first field, and a field named <STRONG>price</STRONG> (all lower case) that holds space-separated price information in the order
defined by <EM>PriceBreaks</EM>. Also subject to <EM>MixMatch</EM>. In addition, this database <EM>may</EM> hold information about price adjustments -- see <EM>PriceAdjustment</EM>. This is a database that can be in any form, including 
<FONT SIZE=-1>SQL/DBI</FONT> if desired. The only requirement is the
presence of the <STRONG>price</STRONG> field in the proper format, and an appropriate key.

<P></DL>
<P>
<HR>


code: 08.02
section: SQL_SUPPORT
type: item
title: Msql support

<A NAME="Msql_support">Msql support</A></H2>
<P>
The first minimal 
<FONT SIZE=-1>SQL</FONT> support provided by MiniVend was for the Msql.pm module. This is now deprecated in favor of the 
<FONT SIZE=-1>DBI</FONT> support. In most cases, existing Msql users should be able to install and test DBD::mSQL, then change the database directive to the type of
 <CODE>dbi:mSQL:minivend</CODE> and go from there. You may have to set your directive to <CODE>dbi:mSQL:minivend:localhost:1114</CODE> or some other value corresponding to host and 
<FONT SIZE=-1>TCP</FONT> port.

<P>
<HR>


code: 08.03
section: SQL_SUPPORT
type: item
title: Importing from an ASCII file

<A NAME="Importing_from_an_ASCII_file">Importing from an ASCII file</A></H2>
<P>
When importing a file for 
<FONT SIZE=-1>SQL,</FONT> MiniVend by default uses the first column of the 
<FONT SIZE=-1>ASCII</FONT> file as the primary key, with a
 <CODE>char(16)</CODE>
type, and assigns all other columns a <CODE>char (128)</CODE> definition. These definitions can be changed by placing the proper definitions in 
<FONT SIZE=-1>COLUMN_DEF</FONT>

<EM>Database</EM> directive attribute:

<P>
<PRE>  Database  products  COLUMN_DEF  price=char(20), nontaxable=char(3)
</PRE>
<P>
You can set this as many times as desired if it will not fit on the line
nicely. 

<P>
<PRE>  Database  products  COLUMN_DEF  price=char(20), nontaxable=char(3)
  Database  products  COLUMN_DEF  description=char(254)
</PRE>
<P>
To create an index automatically, you can append information when the value
is in quotes:

<P>
<PRE>  Database  products  COLUMN_DEF  &quot;code=char(14) primary key&quot;
</PRE>
<P>
The field delimiter to use is 
<FONT SIZE=-1>TAB</FONT> by default, but can be changed with the Database 
<FONT SIZE=-1>DELIMITER</FONT> directive:


<P>
<PRE>  Database  products products.csv dbi:mSQL:minivend:localhost:1114
  Database  products DELIMITER  CSV
</PRE>
<P>
If you wish to create other secondary keys to speed sorts and searches, you
can either use MiniVend tags in an admin menu page

<P>
<PRE>  [sql set]CREATE INDEX CATEGORY_IDX on products (category)[/sql]
</PRE>
<P>
or use external database tools. Careful! Not all 
<FONT SIZE=-1>SQL</FONT> databases use the same index commands. For
example, with MySQL you would do instead:

<P>
<PRE>  [sql set]ALTER TABLE products CHANGE category category char(128) key[/set]
</PRE>
<P>
If you wish to use an existing 
<FONT SIZE=-1>SQL</FONT> database instead of importing, set the
<EM>NoImport</EM> directive in catalog.cfg to include any database identifiers you never wish
to import:

<P>
<PRE>    NoImport  products inventory
</PRE>
<P>
<STRONG>WARNING:</STRONG> If MiniVend has write permission on the products database, you <STRONG>must</STRONG> be careful to set the <EM>NoImport</EM> directive or create the proper .sql file. If that is not done, and the database source file is changed, the 
<FONT SIZE=-1>SQL</FONT> database could be overwritten. In any case, always back up your database before enabling it for use by MiniVend.


<P>
<HR>


code: 08.03
section: SQL_SUPPORT
type: item
title: SQL support via DBI

<A NAME="SQL_support_via_DBI">SQL support via DBI</A></H2>
<P>
MiniVend now provides complete external 
<FONT SIZE=-1>SQL</FONT> database support via the Perl 
<FONT SIZE=-1>DBI</FONT> and 
<FONT SIZE=-1>DBD</FONT> modules. This allows transparent access to any database engine that is supported by a 
<FONT SIZE=-1>DBD</FONT> module. The current list includes mSQL, mySQL, Solid, Postgres, Oracle, Sybase, Informix, Ingres, Qbase, 
<FONT SIZE=-1>DB2,</FONT> Fulcrum, and others. Any 
<FONT SIZE=-1>ODBC</FONT> (with appropriate driver) should also be supported.


<P>
The configuration of the 
<FONT SIZE=-1>DBI</FONT> database is done by setting attributes in
additional <EM>Database</EM> directives <STRONG>after</STRONG> the initial defining line as described above. For example, the following
defines the database <STRONG>arbitrary</STRONG>
as a 
<FONT SIZE=-1>DBI</FONT> database, sets the data source 
<FONT SIZE=-1>(DSN)</FONT> to an appropriate value for an mSQL database named
 <CODE>minivend</CODE> on port 1114 of the local machine:

<P>
<PRE>    Database arbitrary arbitrary.asc SQL
    Database arbitrary DSN           dbi:mSQL:minivend:localhost:1114
</PRE>
<P>
As a shorthand method, you can instead include the 
<FONT SIZE=-1>DSN</FONT> as the type:

<P>
<PRE>    Database arbitrary arbitrary.asc dbi:mSQL:minivend:localhost:1114
</PRE>
<P>
Supported configuration attributes include (but are not limited to):

<DL>
<DT><STRONG><A NAME="item_DSN">DSN</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> specification of the 
<FONT SIZE=-1>DBI</FONT> driver and its data source. To use the DBD::mSQL driver for 
<FONT SIZE=-1>DBI,</FONT> you would typically use:


<P>
<PRE>    dbi:mSQL:minivend:othermachine.my.com:1112
</PRE>
<P>
where mSQL selects the driver (case 
<FONT SIZE=-1>IS</FONT> important), <CODE>minivend</CODE> selects the database, <CODE>othermachine.my.com</CODE> selects the host, and 1112 is the port. On many systems, <CODE>dbi:mSQL:minivend</CODE> will work just fine. (The <CODE>minivend</CODE>
database must already exist, of course.)

<P>
This is the same as the <STRONG>DBI_DSN</STRONG> environment variable -- if you don't set the 
<FONT SIZE=-1>DSN</FONT> parameter, then the value of <STRONG>DBI_DSN</STRONG> will be used to try and find the proper database to connect to.

<P><DT><STRONG><A NAME="item_USER">USER</A></STRONG><DD>

The user name you log into the database with -- same as the environment
variable <STRONG>DBI_USER</STRONG>. If you don't need a user name, just don't set the 
<FONT SIZE=-1>USER</FONT> directive.

<P><DT><STRONG><A NAME="item_PASS">PASS</A></STRONG><DD>

The password you log into the database with -- same as the environment
variable <STRONG>DBI_PASS</STRONG>. If you don't need a password, just don't set the 
<FONT SIZE=-1>PASS</FONT> directive.

<P><DT><STRONG><A NAME="item_COLUMN_DEF">COLUMN_DEF</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> comma-separated set of lines in the form 
<FONT SIZE=-1>NAME=TYPE(N),</FONT> where 
<FONT SIZE=-1>NAME</FONT> is the name of the field/column, 
<FONT SIZE=-1>TYPE</FONT> is the 
<FONT SIZE=-1>SQL</FONT> data type reference, and 
<FONT SIZE=-1>N</FONT> is the length (if needed). Most MiniVend fields should be of the fixed-length character type, something like <CODE>char(128).</CODE> In fact that is the default if you do not choose a type for a column. You can have as many lines as needed. This is not a 
<FONT SIZE=-1>DBI</FONT> parameter, it is specific to MiniVend.


<P><DT><STRONG><A NAME="item_NAME">NAME</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> space-separated field of column names for a table.
Normally not used -- MiniVend should resolve the column names properly upon
query. Set this if your catalog errors out with ``dbi: can't find field
names'' or the like. The first field should always be <STRONG>code</STRONG>. This is not a 
<FONT SIZE=-1>DBI</FONT> parameter, it is specific to MiniVend. All columns
must be listed, in order of their position in the table.

<P><DT><STRONG><A NAME="item_NUMERIC">NUMERIC</A></STRONG><DD>

Tells MiniVend to not quote values for this field; allows numeric data types for 
<FONT SIZE=-1>SQL</FONT> databases. Placed as a comma-separated field of column names for a table, in no particular order. This must be defined if you are to use an numeric value, as 
<FONT SIZE=-1>DBI</FONT> does not yet have standard type queries.


<P><DT><STRONG><A NAME="item_UPPERCASE">UPPERCASE</A></STRONG><DD>

Tells MiniVend to force field names to 
<FONT SIZE=-1>UPPER</FONT> case for row accesses using the <CODE>[item-data ...]</CODE>, <CODE>[loop-data ...]</CODE>, <CODE>[item-field ...</CODE>, etc. Typically used for Oracle and some other 
<FONT SIZE=-1>SQL</FONT> implementations.

<P><DT><STRONG><A NAME="item_DELIMITER">DELIMITER</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> MiniVend delimiter type - one of 
<FONT SIZE=-1>TAB,CSV,PIPE,%%,LINE</FONT> or the corresponding numeric type. It can also be a custom delimiter as specified with
 <EM>FieldDelimiter</EM>
and <EM>RecordDelimiter</EM>. The default for 
<FONT SIZE=-1>SQL</FONT> (and Msql) databases is 
<FONT SIZE=-1>TAB</FONT> -- use 
<FONT SIZE=-1>DELIMITER</FONT> if you wish to import another type. This is not a 
<FONT SIZE=-1>DBI</FONT> parameter, it is specific to MiniVend.


<P><DT><STRONG><A NAME="item_KEY">KEY</A></STRONG><DD>

You can change the keying default of <A HREF="#item_code">code</A> in the first column of the database with the 
<FONT SIZE=-1>KEY</FONT> directive. <STRONG>Don't use this unless you know exactly</STRONG>

<STRONG>what you are doing and are prepared to alter all searches, imports, and</STRONG>

<STRONG>exports accordingly.</STRONG>  It is best to just accept the default and make the first column the key for
any MiniVend database.

<P><DT><STRONG><A NAME="item_ChopBlanks">ChopBlanks,LongReadLen,LongTruncOK,RaiseError, etc.</A></STRONG><DD>

Sets the corresponding 
<FONT SIZE=-1>DBI</FONT> attribute. Of particular interest is ChopBlanks,
which should be set on drivers which by default return space-padded
fixed-length character fields (Solid is an example).

<P>
The supported list as of release of MiniVend 3.02 is:

<P>
<PRE>  ChopBlanks
  CompatMode
  LongReadLen
  LongTruncOk
  PrintError
  RaiseError
  Warn
</PRE>
<P>
Issue the shell command <CODE>perldoc DBI</CODE> for more information.

<P></DL>
<P>
Here is an example of a completely set up 
<FONT SIZE=-1>DBI</FONT> database on mySQL, using a comma-separated value input, setting the 
<FONT SIZE=-1>DBI</FONT> attribute LongReadLen to retrieve an entire field, and changing some field definitions from the default <CODE>char(128):</CODE>


<P>
<PRE>  Database   products  products.csv  dbi:mysql:minivend:localhost:3333
  Database   products  USER          mike
  Database   products  PASS          NeVairBE
  Database   products  DELIMITER     CSV
 
  # Set a DBI attribute
  Database   products  LongReadLen   128
 
  # change some fields from the default field type of char(128)
  # Only applies if Minivend is importing from ASCII file
  # If you set a field to a numeric type, you must set the
  # NUMERIC attribute
  Database   products  COLUMN_DEF    price=float, code=char(20), discount=float
  Database   products  COLUMN_DEF    author=char(40), title=char(64)
  Database   products  COLUMN_DEF    nontaxable=char(3)
  Database   products  NUMERIC       price, discount
</PRE>
<P>
You must have mySQL, 
<FONT SIZE=-1>DBI,</FONT> and DBD::mysql completely installed and tested,
and have created the database <CODE>minivend</CODE> for this to work. Permissions are difficult on mySQL -- if you have
trouble, try starting the mySQL daemon with <CODE>safe_mysqld --skip-grant-tables &amp;</CODE> for testing purposes.

<P>
To change to 
<FONT SIZE=-1>ODBC,</FONT> the only changes required might be:

<P>
<PRE>    Database products  DSN         dbi:ODBC:TCP/IP localhost 1313
    Database products  ChopBlanks  1
</PRE>
<P>
The 
<FONT SIZE=-1>DSN</FONT> setting is specific to your 
<FONT SIZE=-1>ODBC</FONT> setup. The
 <STRONG>ChopBlanks</STRONG> setting takes care of the space-padding in Solid and some other databases -- it is not specific to 
<FONT SIZE=-1>ODBC.</FONT> Once again, 
<FONT SIZE=-1>DBI,</FONT> 
<FONT SIZE=-1>DBD::ODBC,</FONT> and the and appropriate 
<FONT SIZE=-1>ODBC</FONT> driver must be installed and tested.


<P>
<HR>


code: 08.04
section: SQL_SUPPORT
type: item
title: SQL Access Methods

<A NAME="SQL_Access_Methods">SQL Access Methods</A></H2>
<P>

<FONT SIZE=-1>A</FONT> MiniVend 
<FONT SIZE=-1>SQL</FONT> database can be accessed with the same tags as any of the other databases can. In addition to those standard methods, direct 
<FONT SIZE=-1>SQL</FONT> support is provided with the
 <CODE>[sql function] TEXT [/sql identifier]</CODE>
tag set. The MiniVend database identifier only needs to be set if the table resides in a different database than the main products database -- if you don't use 
<FONT SIZE=-1>SQL</FONT> for the products database you will 
<FONT SIZE=-1>ALWAYS</FONT> need to set it.


<P>
For any of these, you may pass arguments with the <CODE>[arg]argument[/arg]</CODE>
quoting method, which substitutes the contained value for successive values
of <A HREF="#item__s">%s</A> in the query. For example:

<P>
<PRE>    [sql html]
    [arg][value passed_title][/arg]
    [arg][value passed_artist][/arg]
        select code, title, title from products
            where artist = %s and title = %s
    [/sql]
 
  *    optional parameter
  SQL  Any valid SQL query (usually a select)
</PRE>
<DL>
<DT><STRONG><A NAME="item__sql">[sql type=array base=identifier*] SQL [/sql]</A></STRONG><DD>

Old parser: <CODE>[sql array] SQL [/sql identifier*]</CODE>



<P>

<FONT SIZE=-1>A</FONT> complete array of arrays, suitable for <EM>eval</EM> by Perl, can be returned by this query. This tag pair encloses any valid 
<FONT SIZE=-1>SQL</FONT> query, and returns the results (if any) as a
string representing rows and columns, in Perl array syntax. If placed in an
embedded Perl area as:

<P>
<PRE> [perl interpolate=1]
</PRE>
<P>
<PRE>    my $string =&lt;&lt;'EOF';
 [sql array]select * from arbitrary where code &lt;= '19'[/sql arbitrary]
</PRE>
<P>
<PRE> EOF
    my $ary = eval $string;
    my $out = '';
    my $i;
    foreach $i (@$ary) {
        $out .= $i-&gt;[0];
        $out .= &quot;&lt;BR&gt;&quot;;
    }
    $out;
</PRE>
<P>
<PRE> [/perl]
</PRE>
<P>

<FONT SIZE=-1>NOTE:</FONT> The 
<FONT SIZE=-1>'EOF'</FONT> string terminator must 
<FONT SIZE=-1>START</FONT> the line, and not have trailing characters. 
<FONT SIZE=-1>DOS</FONT> users, beware of carriage returns!


<P><DT><STRONG>[sql type=hash base=identifier*] SQL [/sql]</STRONG><DD>

Old parser: <CODE>[sql hash] SQL [/sql identifier*]</CODE>



<P>

<FONT SIZE=-1>A</FONT> complete hash of hashes, suitable for <EM>eval</EM> by Perl, can be returned by this query. This tag pair encloses any valid 
<FONT SIZE=-1>SQL</FONT> query, and returns the results (if any) as a
string representing rows and columns, in Perl associative array, or hash,
syntax. If placed in an embedded Perl area as:

<P>
<PRE> [perl interpolate=1]
</PRE>
<P>
<PRE>    my $string =&lt;&lt;'EOF';
 [sql type=hash base=arbitrary]select * from arbitrary where code &lt;= '19'[/sql]
</PRE>
<P>
<PRE> EOF
    my $hash = eval $string;
    my $out = '';
    my $key;
    foreach $key (keys %$hash) {
        $out .= $key-&gt;{field1};
        $out .= &quot;&lt;BR&gt;&quot;;
    }
    $out;
</PRE>
<P>
<PRE> [/perl]
</PRE>
<P><DT><STRONG>[sql type=set base=identifier*] SQL [/sql]</STRONG><DD>

Old parser: [sql set] 
<FONT SIZE=-1>SQL</FONT> [/sql identifier*]

<P>
Any arbitrary 
<FONT SIZE=-1>SQL</FONT> query can be passed with this method. No return
text will be sent. This might be used for passing an order to an order
database, perhaps on the order report or receipt page. An example might be:

<P>
<PRE> [sql type=set base=orders interpolate=1]
     insert into orders
     values
      ('[value mv_order_number]',
       '[value name escape]',
       '[value address escape]',
       '[value city escape]',
       '[value state escape]',
       '[value zip escape]',
       '[value phone escape]',
       '[item-list]
         Item: [item-code] Quan: [item-quantity] Price: [item-price]
        [/item-list]'
      )
 [/sql]
</PRE>
<P>
The values entered by the user are escaped, which prevents errors if quote
characters have slipped into their entry.

<P><DT><STRONG>[sql type=param base=identifier*] SQL [/sql]</STRONG><DD>

Old parser: <CODE>[sql param] SQL [/sql identifier*]</CODE>



<P>

<FONT SIZE=-1>A</FONT> list of keys, or in fact any 
<FONT SIZE=-1>SQL</FONT> fields, can be returned as a set of parameters suitable for passing to a program or list primitive. This tag pair encloses any valid 
<FONT SIZE=-1>SQL</FONT> query, and returns the results (if any) as a series of space separated fields, enclosed in quotes. This folds the entire return into a single row, so it may be used as a list of keys.


<P>
This tag is deprecated.

<P><DT><STRONG>[sql type=html base=identifier*] SQL [/sql]</STRONG><DD>

Old parser: <CODE>[sql html] SQL [/sql identifier*]</CODE>



<P>
This tag returns a set of 
<FONT SIZE=-1>HTML</FONT> table rows with <STRONG>bold</STRONG> field names at the top, followed by each row in a set of table cells. The 
<FONT SIZE=-1>&lt;TABLE&gt;</FONT> and 
<FONT SIZE=-1>&lt;/TABLE&gt;</FONT> tags are not supplied, so you can set your own border and shading options. Example:


<P>
<PRE>  &lt;TABLE BORDER=2&gt;
  [sql type=html]select * from arbitrary where code &gt; '19' order by field2[/sql]
  &lt;/TABLE&gt;
</PRE>
<P><DT><STRONG>[sql type=list query=&quot;SQL query&quot; base=identifier*] list [/sql]</STRONG><DD>

This tag differs from the rest in that it passes the query enclosed inside the tag itself. The enclosed text is then evaluated with the same method as with a loop list, with data items (in columns) iterated over for the contents of a list. The following snippet will place a three-column list in an 
<FONT SIZE=-1>HTML</FONT> table:


<P>
<PRE>  &lt;TABLE BORDER=2&gt;
  &lt;TR&gt;&lt;TH&gt;&lt;B&gt;SKU&lt;/B&gt;&lt;/TH&gt;&lt;TH&gt;&lt;B&gt;Description&lt;/B&gt;&lt;/TH&gt;&lt;TH&gt;&lt;B&gt;Price&lt;/B&gt;&lt;/TH&gt;
  [sql type=list
    query=&quot;select code,desc,price from arbitrary where code &gt; '19' order by field2&quot;]
  &lt;TR&gt;
    &lt;TD&gt;[page [sql-code]][sql-code]&lt;/A&gt;&lt;/TD&gt;
    &lt;TD&gt;[sql-param desc]&lt;/TD&gt;
    &lt;TD&gt;[sql-param price]&lt;/TD&gt;
  &lt;/TR&gt;
  [/sql]
  &lt;/TABLE&gt;
</PRE>
<P>
This is the fastest way to return data from an 
<FONT SIZE=-1>SQL</FONT> query.

<P>
It uses the same tags as in the <CODE>[loop ....]</CODE>, except prefixed with <CODE>sql</CODE>. Available are the following, in order of interpolation:

<P>
<PRE>  [sql-param n]        Field n of the returned query (in the row)
  [sql-param name]     Field &quot;name&quot; of the returned query (in the row)
  [if-sql-field fld]   Returns enclosed text only product field not empty
  [/if-sql-field]      Terminator for above
  [if-sql-data db fld] Returns enclosed text only if data field not empty
  [/if-sql-field]      Terminator for above
  [sql-increment]      Returns integer count of row
  [sql-code]           The first field of each row returned
  [sql-data db fld]    Database field for [sql-code]
  [sql-description]    Product description for [sql-code]
  [sql-field fld]      Product field for [sql-code]
  [sql-link]           Same as item-link
  [sql-price q*]       Price for [sql_code], optional quantity q
</PRE>
<P></DL>
<P>
<HR>


code: 09.00
section: SQL_SUPPORT
type: overview
title: SQL SUPPORT

<A NAME="SQL_SUPPORT">SQL SUPPORT</A></H1>
<P>
MiniVend can use any of a number of 
<FONT SIZE=-1>SQL</FONT> databases through the powerful Perl 
<FONT SIZE=-1>DBI/DBD</FONT> access methods. No 
<FONT SIZE=-1>SQL</FONT> database is included with MiniVend, but there are a number widely available on the net, and many are free for non-commercial use. Some examples include mSQL, mySQL, Solid, and Qbase.


<P>
It is beyond the scope of this document to describe 
<FONT SIZE=-1>SQL,</FONT> mSQL, or 
<FONT SIZE=-1>DBI/DBD,</FONT> and we will not attempt to. Sufficient familiarity is assumed.
 

<P>
In most cases, MiniVend cannot perform administrative functions like creating a database or setting access permissions. This must be done with the tools provided with your 
<FONT SIZE=-1>SQL</FONT> distribution. But if given a blank database and the permission to read and write it, MiniVend can import 
<FONT SIZE=-1>ASCII</FONT> files and bootstrap you from there.


<P>
<HR>


code: 09.02
section: MINIVEND_TAG_REFERENCE
type: item
title: New and Old Style tags

<A NAME="New_and_Old_Style_tags">New and Old Style tags</A></H2>
<P>
There are two styles of tag -- HTML/new, and old. Old style is a legacy
from prior versions of MiniVend and is no longer in standard use, but its
positional syntax can <EM>usually</EM> still be used in New/HTML mode for convenience.

<P>
In the new style, you can specify constructs inside an 
<FONT SIZE=-1>HTML</FONT> tag:

<P>
<PRE>    &lt;TABLE MV=&quot;if items&quot;&gt;
    &lt;TR MV=&quot;item-list&quot;&gt;
    &lt;TD&gt; [item-code] &lt;/TD&gt;
    &lt;TD&gt; [item-description] &lt;/TD&gt;
    &lt;TD&gt; [item-price] &lt;/TD&gt;
    &lt;/TR&gt;&lt;/TABLE&gt;
</PRE>
<P>
The above will loop over any items in the shopping cart, displaying their part number, description, and price, but only 
<FONT SIZE=-1>IF</FONT> there are items in the cart.


<P>
The same thing can be achieved with:

<P>
<PRE>    [if items]
    &lt;TABLE&gt;
    [item-list]
    &lt;TR&gt;
    &lt;TD&gt; [item-code] &lt;/TD&gt;
    &lt;TD&gt; [item-description] &lt;/TD&gt;
    &lt;TD&gt; [item-price] &lt;/TD&gt;
    &lt;/TR&gt;
    [/item-list]&lt;/TABLE&gt;
    [/if]
</PRE>
<P>
To use the new more regular syntax by default, set the <EM>NewTags</EM>
directive to <CODE>Yes</CODE>. The demo catalog is distributed with <CODE>NewTags Yes</CODE>
starting at MiniVend 3.07.

<P>
In most cases, tags specified in the old positional fashion will work the
same in the new style. The only time you will need to modify them is when
there is some ambiguity as to which parameter is which (usually due to
whitespace), or when you need to use the output of a tag as the attribute
parameter for another tag.

<P>
<STRONG>TIP:</STRONG> This will not work in the new style as it did in the old:

<P>
<PRE>    [page scan se=[scratch somevar]]
</PRE>
<P>
To get the output of the <CODE>[scratch somevar]</CODE> interpreted, you must place it within a named and quoted attribute:

<P>
<PRE>    [page href=&quot;scan&quot; arg=&quot;se=[scratch somevar]&quot;]
</PRE>
<P>
What is done with the results of the tag depends on whether it is a 
<EM>container</EM> or <EM>standalone</EM> tag. 
<FONT SIZE=-1>A</FONT> container tag is one which has an end tag, i.e. <CODE>[tag] stuff [/tag]</CODE>. 
<FONT SIZE=-1>A</FONT> standalone tag has no end tag, as in <CODE>[area href=somepage]</CODE>. (Note that <CODE>[page ...]</CODE> and <A HREF="#item__order_">[order ..]</A>
are <STRONG>not</STRONG> container tags.)

<P>

<FONT SIZE=-1>A</FONT> container tag will have its output re-parsed for
more MiniVend tags by default. If you wish to inhibit this behavior, you
must explicitly set the attribute <STRONG>reparse</STRONG> to 0. (Prior to MiniVend 3.09, <STRONG>reparse</STRONG>
did not exist.) Note that you will almost always wish the default action.

<P>
With some exceptions (<CODE>[include]</CODE> and <CODE>[buttonbar ..]</CODE>
among them) the output of a standalone tag will not be re-interpreted for
MiniVend tag constructs.  

<P>
Most container tags will not have their contents interpreted before being
passed the container text. Exceptions include <CODE>[calc]</CODE> .. <CODE>[/calc]</CODE> and
<CODE>[currency]</CODE> ... <CODE>[/currency]</CODE>. All tags accept the 
<FONT SIZE=-1>INTERPOLATE=1</FONT> tag modifier, which causes the
interpretation to take place. It is frequent that you will <STRONG>not</STRONG> want to interpret the contents of a <CODE>[set variable]</CODE>

<FONT SIZE=-1>TAGS</FONT> <CODE>[/set]</CODE> pair, as that might contain tags which should only be upon evaluating an
order profile, search profile, or <CODE>mv_click</CODE> operation. If you wish to perform the evaluation at the time a variable is
set, you would use <CODE>[set name=variable interpolate=1] TAGS [/set]</CODE>.

<P>
To use the new syntax only on a particular page, place <STRONG>one</STRONG>  <CODE>[new]</CODE>
tag in your page. Likewise, to use old syntax when new is the default,
place <STRONG>one</STRONG>  <CODE>[old]</CODE> tag in the page.

<P>
If you have regions of the page which work under the old style and fail
with the new style, you can surround them with <CODE>[compat] [/compat]</CODE> tag pair. This will evaluate that region only with the old style repeated
interpolation.

<P>
<STRONG>NOTE WHEN USING THE OLD TAG PARSER (NewTags No) or [compat][/compat]:</STRONG>
MiniVend in old mode interpolates tags in a highly ordered fashion, with
each tag having a precedence. The order of the tag interpolation can be
changed by enclosing the tag in a set of double square brackets, bringing
it forward in the process. The order of interpolation is:

<P>
<PRE>  tag [[ANY TAG]] cart item-list loop default value scratch calc if lookup
  set data msql|sql file finish_order frames_on frames_off 
  framebase body help buttonbar random rotate checked selected
  accessories field pagetarget area areatarget page last_page
  perl order nitems discount subtotal shipping shipping_description
  salestax total_cost price currency description row process_order
  process_search process_target
</PRE>
<P>
<HR>


code: 09.03
section: MINIVEND_TAG_REFERENCE
type: item
title: DATA and FIELD

<A NAME="DATA_and_FIELD">DATA and FIELD</A></H2>
<P>
The <A HREF="#item__data_">[data ...]</A> and <A HREF="#item__field_">[field ...]</A> tags access elements of MiniVend databases. They are the form used outside
of the iterating lists, and can be effectively used to do lookups when the
table, column/field or key/row is conditional based on a previous
operation.

<P>
The following are equivalent for attribute names:

<P>
<PRE>    base  ---&gt; table --&gt; database
    name  ---&gt; field --&gt; column --&gt; col
    code  ---&gt; key   --&gt; row
</PRE>
<DL>
<DT><STRONG><A NAME="item__data">[data area field key &quot;value&quot;* increment*]</A></STRONG><DD>

named attributes: <CODE>[data base=&quot;database&quot; field=&quot;field&quot; key=&quot;key&quot;</CODE>
                        
                        <CODE>value=&quot;value&quot; op=&quot;increment]</CODE> )

<P>

<FONT SIZE=-1>HTML</FONT> example: 
<FONT SIZE=-1>&lt;PARAM</FONT> MV=data MV.TABLE=database MV.COL=field MV.ROW=key&gt;


<P>
Returns the value of the field in any of the arbitrary databases, or from
the variable namespaces. If the optional <STRONG>value</STRONG> is supplied, the database value will be changed to it -- no ] characters
may be present in the value unless using the new tag style. If the option
increment* is present, the field will be atomically incremented with the
value in <STRONG>value</STRONG>.

<P>
If a DBM-based database is to be modified, it must be flagged writable on
the page calling the write tag. Use <CODE>[tag flag write]products[/tag]</CODE>
to mark the <A HREF="#item_products">products</A> database writable, for example.

<P>
In addition, the <A HREF="#item__data_">[data ...]</A> tag can access a number of elements in the MiniVend session database:

<P>
<PRE>    accesses      Accesses within the last 30 seconds
    arg           The argument passed in a [page ...] or [area ...] tag
    browser       The user browser string
    host          MiniVend's idea of the host (modified by DomainTail)
    last_error    The last error from the error logging
    last_url      The current MiniVend path_info
    logged_in     Whether the user is logged in via UserDB
    pageCount     Number of unique URLs generated
    prev_url      The previous path_info
    referer       HTTP_REFERER string
    ship_message  The last error messages from shipping
    source        Source of original entry to MiniVend
    time          Time (seconds since Jan 1, 1970) of last access
    user          The REMOTE_USER string
    username      User name logged in as (UserDB)
</PRE>
<P>
Databases will hide variables, so don't name a database ``session'',
``scratch'', or any of the other reserved names or you won't be able to use
the <A HREF="#item__data_">[data ...]</A> tag to read them. Case is sensitive, so in a pinch you could call the
database ``Session'', but it would be better not to.

<P><DT><STRONG><A NAME="item__field">[field name code]</A></STRONG><DD>

named attributes: <CODE>[field code=&quot;code&quot; name=&quot;fieldname&quot;]</CODE>



<P>

<FONT SIZE=-1>HTML</FONT> example: 
<FONT SIZE=-1>&lt;PARAM</FONT> MV=field MV.COL=column MV.ROW=key&gt;


<P>
Expands into the value of the field <EM>name</EM> for the product identified by <EM>code</EM> as found by searching the products database. It will return the first entry
found in the series of <EM>Product Files</EM>. the products database. If you want to constrain it to a particular
database, use the <CODE>[data base name code]</CODE> tag.

<P></DL>
<P>
<HR>


code: 09.04
section: MINIVEND_TAG_REFERENCE
type: item
title: SET and SCRATCH

<A NAME="SET_and_SCRATCH">SET and SCRATCH</A></H2>
<P>
Scratch variables are maintained in the user session separate from the form variable values set on 
<FONT SIZE=-1>HTML</FONT> forms.


<P>
Many things can be controlled with scratch variables, notable search and
order processing, the <CODE>mv_click</CODE> multiple variable setting facility, and key MiniVend conditions like
whether an item will be ordered on a separate line.

<P>
There are two tags which are used to access the space, <CODE>[set name]value[/set]</CODE>
and <CODE>[scratch name]</CODE>.

<DL>
<DT><STRONG><A NAME="item__set">[set variable]value[/set]</A></STRONG><DD>

named attributes: <CODE>[set name=&quot;variable&quot;] value [/set]</CODE>



<P>

<FONT SIZE=-1>HTML</FONT> example: 
<FONT SIZE=-1>&lt;PRE</FONT> MV=``set variable''&gt; value 
<FONT SIZE=-1>&lt;/PRE&gt;</FONT>


<P>
Sets a scratchpad variable to <EM>value</EM>.

<P>
Most of the mv_* variables that are used for search and order conditionals
are in another namespace -- they can be set by means of hidden fields in a
form.

<P>
You can set an order profile with:

<P>
<PRE>  [set checkout]
  name=required You must give us your name.
  address=required Oops! No address.
  [/set]
  &lt;INPUT TYPE=hidden NAME=mv_order_profile VALUE=&quot;checkout&quot;&gt;
</PRE>
<P>

<FONT SIZE=-1>A</FONT> search profile would be set with:

<P>
<PRE>  [set substring_case]
  mv_substring_match=yes
  mv_case=yes
  [/set]
  &lt;INPUT TYPE=hidden NAME=mv_profile VALUE=&quot;substring_case&quot;&gt;
</PRE>
<P><DT><STRONG><A NAME="item__scratch">[scratch name]</A></STRONG><DD>

Returns the contents of a scratch variable to the page.

<P><DT><STRONG><A NAME="item__if">[if scratch name op* compare*] .... [/if]</A></STRONG><DD>

Tests a scratch variable (see <EM>IF</EM>).

<P></DL>
<P>
<HR>


code: 09.05
section: MINIVEND_TAG_REFERENCE
type: item
title: DEFAULT and LOOKUP

<A NAME="DEFAULT_and_LOOKUP">DEFAULT and LOOKUP</A></H2>
<P>
Sometimes you want to use a form value that the user has set, but want it
to be initialized if not already present. The <CODE>[default ...]</CODE> tag will do that.

<P>
Other times, you want to initialize a variable based on a database value.
The <CODE>[lookup ...]</CODE> tag will perform a lookup in an arbitrary database and set return that
value only if the user form value is not set.

<DL>
<DT><STRONG><A NAME="item__default">[default variable value*]</A></STRONG><DD>

named attributes: <CODE>[default name=&quot;variable&quot; default=&quot;default value&quot; set=1*]</CODE>



<P>

<FONT SIZE=-1>HTML</FONT> example: 
<FONT SIZE=-1>&lt;PARAM</FONT> MV=``default'' MV.NAME=variable MV.DEFAULT=``default'' 
<FONT SIZE=-1>MV.</FONT> set=1&gt;


<P>
Returns the value of the user form variable <CODE>variable</CODE> if it is non-empty. Otherwise returns <CODE>default</CODE>, which is the string ``default'' if there is no default supplied. Got
that?

<P>
If the flag <CODE>set</CODE> is present and non-zero, then the variable will be set to the <CODE>default</CODE> and <EM>no value returned to the page</EM>. This allows you to initialize things like country, shipping mode, and
other values on a checkout page.

<P><DT><STRONG><A NAME="item__lookup">[lookup table column row &quot;a quoted value&quot;]</A></STRONG><DD>

named attributes: <CODE>[lookup table=&quot;database&quot; col=&quot;column&quot; key=row value=&quot;[value name]&quot;]</CODE>



<P>
This is essentially same as the following:

<P>
<PRE>    [if value name]
    [then][value name][/then]
    [else][data database column row][/else]
    [/if]
</PRE>
<P></DL>
<P>
<HR>


code: 09.06
section: MINIVEND_TAG_REFERENCE
type: item
title: LOOP and TAG EACH

<A NAME="LOOP_and_TAG_EACH">LOOP and TAG EACH</A></H2>
<P>
Loop lists can be used to construct arbitrary lists based on the contents
of a database field or other value. The <CODE>[tag each table] [/tag]</CODE> construct uses the same interior tags, but iterates over every key of a
particular database table.

<P>
Both can be sorted with <CODE>[sort table:field:mod -start +number]</CODE> modifiers. See <EM>SORTING</EM>.

<DL>
<DT><STRONG><A NAME="item__loop">[loop item item item] LIST [/loop]</A></STRONG><DD>

named attributes: <CODE>[loop with=&quot;-a&quot;* arg=&quot;item item item&quot; search=&quot;se=whatever&quot;]</CODE>



<P>

<FONT SIZE=-1>HTML</FONT> example: 

<P>
<PRE>    &lt;TABLE&gt;&lt;TR MV=&quot;loop 1 2 3&quot;&gt;&lt;TD&gt;[loop-code]&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;
</PRE>
<P>
Returns a string consisting of the 
<FONT SIZE=-1>LIST,</FONT> repeated for every item in a comma-separated or
space-separated list. Operates in the same fashion as the <CODE>[item-list]</CODE> tag, except for order-item-specific values. Intended to pull multiple
attributes from an item modifier -- but can be useful for other things,
like building a pre-ordained product list on a page.

<P>
Loop lists can be nested reliably in MiniVend 3.06 by using the
with=``tag'' parameter. New syntax:

<P>
<PRE>    [loop arg=&quot;A B C&quot;]
        [loop with=&quot;-a&quot; arg=&quot;[loop-code]1 [loop-code]2 [loop-code]3&quot;]
            [loop with=&quot;-b&quot; arg=&quot;X Y Z&quot;]
                [loop-code-a]-[loop-code-b]
            [/loop]
        [/loop]
    [/loop]
</PRE>
<P>
An example in the old syntax:

<P>
<PRE>    [compat]
    [loop 1 2 3]   
        [loop-a 1 2 3 ]
        [loop-b 1 2 3]
            [loop-code].[loop-code-a].[loop-code-b]
        [/loop-b]
        [/loop-a]
    [/loop]
    [/compat]
</PRE>
<P>
All loop items in the inner loop-a loop need to have the <CODE>with</CODE> value appended, i.e. <CODE>[loop-field-a name]</CODE>, <CODE>[loop-price-a]</CODE>, etc. Nesting is arbitrarily large, though it will be slow for many
levels.

<P>
You can do an arbitrary search with the search=``args'' parameter, just as
in a one-click search:

<P>
<PRE>    [loop search=&quot;se=Americana/sf=category&quot;]
        [loop-code] [loop-field title]
    [/loop]
</PRE>
<P>
The above will show all items with a category containing the whole world
``Americana'', and will work the same in both old and new syntax.

<P><DT><STRONG><A NAME="item__if_loop_data">[if-loop-data table field] IF [else] ELSE [/else][/if-loop-field]</A></STRONG><DD>

Outputs the 
<FONT SIZE=-1>IF</FONT> if the <A HREF="#item_field">field</A> in <A HREF="#item_table">table</A> is non-empty, and the 
<FONT SIZE=-1>ELSE</FONT> (if any) otherwise.

<P>

<FONT SIZE=-1>NOTE:</FONT> This tag does not nest with other <CODE>[if-loop-data ...]</CODE> tags.

<P><DT><STRONG><A NAME="item__if_loop_field">[if-loop-field field] IF [else] ELSE [/else][/if-loop-field]</A></STRONG><DD>

Outputs the <STRONG>IF</STRONG> if the <A HREF="#item_field">field</A> in the <A HREF="#item_products">products</A> table is non-empty, and the <STRONG>ELSE</STRONG> (if any) otherwise.

<P>

<FONT SIZE=-1>NOTE:</FONT> This tag does not nest with other <CODE>[if-loop-field ...]</CODE> tags.

<P><DT><STRONG><A NAME="item__loop_accessories_">[loop-accessories]</A></STRONG><DD>

Evaluates to the value of the Accessories database entry for the item.

<P><DT><STRONG><A NAME="item__loop_change">[loop-change marker]</A></STRONG><DD>

Same as <CODE>[on-change]</CODE> but within loop lists.

<P><DT><STRONG><A NAME="item__loop_code_">[loop-code]</A></STRONG><DD>

Evaluates to the product code for the current item.

<P><DT><STRONG><A NAME="item__loop_data">[loop-data database fieldname]</A></STRONG><DD>

Evaluates to the field name <EM>fieldname</EM> in the arbitrary database table <EM>database</EM>, for the current item.

<P><DT><STRONG><A NAME="item__loop_description_">[loop-description]</A></STRONG><DD>

Evaluates to the product description (from the products file) for the
current item.

<P><DT><STRONG><A NAME="item__loop_field">[loop-field fieldname]</A></STRONG><DD>

Evaluates to the field name <EM>fieldname</EM> in the database, for the current item.

<P><DT><STRONG><A NAME="item__loop_increment_">[loop-increment]</A></STRONG><DD>

Evaluates to the number of the item in the list. Used for numbering items
in the list.

<P><DT><STRONG><A NAME="item__loop_last_tags_loop_last_">[loop-last]tags[/loop-last]</A></STRONG><DD>

Evaluates the output of the MiniVend tags encased inside, and if it
evaluates to a numerical non-zero number (i.e. 1, 23, or -1) then the loop
iteration will terminate. If the evaluated number is
<STRONG>negative</STRONG>, then the item itself will be skipped. If the evaluated number is <STRONG>positive</STRONG>, then the item itself will be shown but will be last on the list.

<P>
<PRE>      [loop-last][calc]
        return -1 if '[loop-field weight]' eq '';
        return 1 if '[loop-field weight]' &lt; 1;
        return 0;
        [/calc][/loop-last]
</PRE>
<P>
If this is contained in your <CODE>[loop list]</CODE> and the weight field is empty, then a numerical <CODE>-1</CODE> will be output from the <CODE>[calc][/calc]</CODE> tags; the list will end and the item will <STRONG>not</STRONG> be shown. If the product's weight field is less than 1, a numerical 1 is
output. The item will be shown, but will be the last item shown.

<P><DT><STRONG><A NAME="item__loop_next_tags_loop_next_">[loop-next]tags[/loop-next]</A></STRONG><DD>

Evaluates the output of the MiniVend tags encased inside, and if it
evaluates to a numerical non-zero number (i.e. 1, 23, or -1) then the loop
will be skipped with no output. Example:

<P>
<PRE>      [loop-next][calc][loop-field weight] &lt; 1[/calc][/loop-next]
</PRE>
<P>
If this is contained in your <CODE>[loop list]</CODE> and the product's weight field is less than 1, then a numerical <CODE>1</CODE> will be output from the
<CODE>[calc][/calc]</CODE> operation. The item will not be shown.

<P><DT><STRONG><A NAME="item__loop_price">[loop-price n* noformat*]</A></STRONG><DD>

Evaluates to the price for optional quantity n (from the products file) of
the current item, with currency formatting. If the optional ``noformat'' is
set, then currency formatting will not be applied.

<P></DL>
<P>
<HR>


code: 09.07
section: MINIVEND_TAG_REFERENCE
type: item
title: IF

<A NAME="IF">IF</A></H2>
<DL>
<DT><STRONG>[if type field op* compare*]</STRONG><DD>

named attributes: <CODE>[if type=&quot;type&quot; term=&quot;field&quot; op=&quot;op&quot; compare=&quot;compare&quot;]</CODE>



<P><DT><STRONG>[if !type field op* compare*]</STRONG><DD>

named attributes: <CODE>[if type=&quot;!type&quot; term=&quot;field&quot; op=&quot;op&quot; compare=&quot;compare&quot;]</CODE>



<P></DL>
<P>
Allows conditional building of 
<FONT SIZE=-1>HTML</FONT> based on the setting of various MiniVend session
and database values. The general form is:

<P>
<PRE>    [if type term op compare]
    [then]
                                If true, this is printed on the document.
                                The [then] [/then] is optional in most
                                cases. If ! is prepended to the type
                                setting, the sense is reversed and
                                this will be output for a false condition.
    [/then]
    [elsif type term op compare]
                                Optional, tested when if fails
    [/elsif] 
    [else]
                                Optional, printed when all above fail
    [/else]
    [/if]
</PRE>
<P>
The <CODE>[if]</CODE> tag can also have some variants:

<P>
<PRE>    [if explicit][condition] CODE [/condition]
                Displayed if valid Perl CODE returns a true value.
    [/if]
</PRE>
<P>
You can do some Perl-style regular expressions, and combine conditions:

<P>
<PRE>    [if value name =~ /^mike/i]
                                This is the if with Mike.
    [elsif value name =~ /^sally/i]
                                This is an elsif with Sally.
    [/elsif]
    [elsif value name =~ /^barb/i]
    [or value name =~ /^mary/i]
                                This is an elsif with Barb or Mary.
    [elsif value name =~ /^pat/i]
    [and value othername =~ /^mike/i]
                                This is an elsif with Pat and Mike.
    [/elsif]
    [else]
                                This is the else, no name I know.
    [/else]
    [/if]
</PRE>
<P>
While the new tag syntax works for <CODE>[if ...]</CODE>, it is more convenient to use the old in most cases. It will work fine
with both parsers. The only exception is if you are planning on doing a
test on the results of another tag sequence: [if value name =~ /[value
b_name]/] Shipping name matches billing name. [/if]

<P>
Oops! This will not work with the new parser. You must do instead

<P>
<PRE>    [compat]
    [if value name =~ /[value b_name]/]
        Shipping name matches billing name.
    [/if]
    [/compat]
</PRE>
<P>
or

<P>
<PRE>    [if type=value term=name op=&quot;=~&quot; compare=&quot;/[value b_name]/&quot;]
        Shipping name matches billing name.
    [/if]
</PRE>
<P>
The latter has the advantage of working with any tag:

<P>
<PRE>    [if type=value term=high_water op=&quot;&lt;&quot; compare=&quot;[shipping]&quot;]
        Shipping cost is too high, charter a truck.
    [/if]
</PRE>
<P>
If you wish to do 
<FONT SIZE=-1>AND</FONT> and 
<FONT SIZE=-1>OR</FONT> operations, you will have to use
 
<CODE>[if explicit]</CODE>. This allows complex testing and parsing of values.

<P>
There are many test targets available:

<DL>
<DT><STRONG>config Directive</STRONG><DD>

The MiniVend configuration variables. These are set by the directives in
your MiniVend configuration file (or the defaults).

<P>
<PRE>    [if config CreditCardAuto]
    Auto credit card validation is enabled.
    [/if]
</PRE>
<P><DT><STRONG><A NAME="item_data">data  database::field::key</A></STRONG><DD>

The MiniVend databases. Retrieves a field in the database and returns true
or false based on the value.

<P>
<PRE>    [if data products::size::99-102]
    There is size information.
    [else]
    No size information.
    [/else]
    [/if]
</PRE>
<P>
<PRE>    [if data products::size::99-102 =~ /small/i]
    There is a small size available.
    [else]
    No small size available.
    [/else]
    [/if]
</PRE>
<P><DT><STRONG><A NAME="item_discount">discount</A></STRONG><DD>

Checks to see if a discount is present for an item.

<P>
<PRE>    [if discount 99-102]
    Item is discounted.
    [/if]
</PRE>
<P><DT><STRONG><A NAME="item_explicit">explicit</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> test for an explicit value. If perl code is placed
between a <CODE>[condition]</CODE>  <CODE>[/condition]</CODE> tag pair, it will be used to make the comparison. Arguments can be passed
to import data from user space, just as with the <CODE>[perl]</CODE> tag.

<P>
<PRE>    [if explicit]
    [condition]
        $country = '[value country]';
        return 1 if $country =~ /u\.?s\.?a?/i;
        return 0;
    [/condition]
    You have indicated a US address.
    [else]
    You have indicated a non-US address. 
    [/else]
    [/if]
</PRE>
<P>
This example is a bit contrived, as the same thing could be accomplished
with <CODE>[if value country =~ /u\.?s\.?a?/i]</CODE>, but you will run into many situations where it is useful.

<P>
This will work for <EM>Variable</EM> values:

<P>
<PRE>    [if explicit &quot;__MYVAR__&quot;] .. [/if]
</PRE>
<P><DT><STRONG><A NAME="item_file">file</A></STRONG><DD>

Tests for existence of a file. Useful for placing image tags only if the
image is present.

<P>
<PRE>    [if file /home/user/www/images/[item-code].gif]
    &lt;IMG SRC=&quot;[item-code].gif&quot;&gt;
    [/if]
</PRE>
<P>
The <A HREF="#item_file">file</A> test requires that the <EM>SafeUntrap</EM> directive contains
<CODE>ftfile</CODE> (which is the default).

<P><DT><STRONG><A NAME="item_items">items</A></STRONG><DD>

The MiniVend shopping carts. If not specified, the cart used is the main
cart. Usually used as a litmus test to see if anything is in the cart, for
example:

<P>
<PRE>  [if items]You have items in your shopping cart.[/if]
  
  [if items layaway]You have items on layaway.[/if]
</PRE>
<P><DT><STRONG><A NAME="item_ordered">ordered</A></STRONG><DD>

Order status of individual items in the MiniVend shopping carts. If not
specified, the cart used is the main cart. The following items refer to a
part number of 99-102.

<P>
<PRE>  [if ordered 99-102] ... [/if]
    Checks the status of an item on order, true if item
    99-102 is in the main cart.
</PRE>
<P>
<PRE>  [if ordered 99-102 layaway] ... [/if]
    Checks the status of an item on order, true if item
    99-102 is in the layaway cart.
</PRE>
<P>
<PRE>  [if ordered 99-102 main size] ... [/if]
    Checks the status of an item on order in the main cart,
    true if it has a size attribute.
</PRE>
<P>
<PRE>  [if ordered 99-102 main size =~ /large/i] ... [/if]
    Checks the status of an item on order in the main cart,
    true if it has a size attribute containing 'large'.
    THE CART NAME IS REQUIRED IN THE OLD SYNTAX. The new
    syntax for that one would be:
</PRE>
<P>
<PRE>    [if type=ordered term=&quot;99-102&quot; compare=&quot;size =~ /large/i&quot;]
</PRE>
<P>
<PRE>    To make sure it is exactly large, you could use:
</PRE>
<P>
<PRE>    [if ordered 99-102 main size eq 'large'] ... [/if]
</PRE>
<P>
<PRE>  [if ordered 99-102 main lines] ... [/if]
      Special case -- counts the lines that the item code is
      present on. (Only useful, of course, when mv_separate_items
      or SeparateItems is defined.)
</PRE>
<P><DT><STRONG><A NAME="item_salestax">salestax</A></STRONG><DD>

The salestax database.

<P>
<PRE>    [if salestax [value state] &gt; 0]
    There is salestax for your state.
    [else]
    No salestax for your state.
    [/else]
    [/if]
</PRE>
<P>
Key matching is case-insensitive.

<P><DT><STRONG><A NAME="item_scratch">scratch</A></STRONG><DD>

The MiniVend scratchpad variables, which can be set with the <CODE>[set name]value[/set]</CODE> element. 

<P>
<PRE>    [if scratch mv_separate_items]
    Ordered items will be placed on a separate line.
    [else]
    Ordered items will be placed on the same line.
    [/else]
    [/if]
</PRE>
<P><DT><STRONG>session</STRONG><DD>

The MiniVend session variables. Of particular interest are <EM>login</EM>, <EM>frames</EM>, <EM>secure</EM>, and <EM>browser</EM>.

<P><DT><STRONG><A NAME="item_shipping">shipping</A></STRONG><DD>

The shipping database.

<P><DT><STRONG><A NAME="item_validcc">validcc</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> special case, takes the form <CODE>[if validcc no type exp_date]</CODE>. Evaluates to true if the supplied credit card number, type of card, and expiration date pass a validity test. Does a 
<FONT SIZE=-1>LUHN-10</FONT> calculation to weed out typos or phony card numbers.


<P><DT><STRONG><A NAME="item_value">value</A></STRONG><DD>

The MiniVend user variables, typically set in search, control, or order
forms. Variables beginning with <CODE>mv_</CODE>
are MiniVend special values, and should be tested/used with caution.

<P></DL>
<P>
The <EM>field</EM> term is the specifier for that area. For example,
<CODE>[if session frames]</CODE> would return true if the <A HREF="#item_frames">frames</A>
session parameter was set.

<P>
As an example, consider buttonbars for frame-based setups. It would be nice
to display a different buttonbar (with no frame targets) for sessions that
are not using frames:

<P>
<PRE>    [if session frames]
        [buttonbar 1]
    [else]
        [buttonbar 2]
    [/else]
    [/if]
</PRE>
<P>
Another example might be the when search matches are displayed. If you use
the string <CODE>[value mv_match_count] titles found</CODE>, it will display a plural for only one match. Use:

<P>
<PRE>    [if value mv_match_count != 1]
        [value mv_match_count] matches found.
    [else]
        Only one match was found.
    [/else]
    [/if]
</PRE>
<P>
The <EM>op</EM> term is the compare operation to be used. Compare operations are as in
Perl:

<P>
<PRE>    ==  numeric equivalence
    eq  string equivalence
    &gt;   numeric greater-than
    gt  string greater-than
    &lt;   numeric less-than
    lt  string less-than
    !=  numeric non-equivalence
    ne  string equivalence
</PRE>
<P>
Any simple perl test can be used, including some limited regex matching.
More complex tests are best done with <CODE>[if explicit]</CODE>.

<DL>
<DT><STRONG><A NAME="item__then_">[then] text [/then]</A></STRONG><DD>

This is optional if you are not nesting if conditions, as the text
immediately following the <CODE>[if ..]</CODE> tag is used as the conditionally substituted text. If nesting <CODE>[if ...]</CODE> tags you should use a <CODE>[then][/then]</CODE>
on any outside conditions to ensure proper interpolation.

<P><DT><STRONG><A NAME="item__elsif">[elsif type field op* compare*]</A></STRONG><DD>

named attributes: <CODE>[elsif type=&quot;type&quot; term=&quot;field&quot; op=&quot;op&quot; compare=&quot;compare&quot;]</CODE>



<P>
Additional conditions for test, applied if the initial <CODE>[if ..]</CODE> test fails.

<P><DT><STRONG><A NAME="item__else_">[else] text [/else]</A></STRONG><DD>

The optional else-text for an if or if_field conditional.

<P><DT><STRONG><A NAME="item__condition_">[condition] text [/condition]</A></STRONG><DD>

Only used with the <CODE>[if explicit]</CODE> tag. Allows an arbitrary expression
<STRONG>in Perl</STRONG> to be placed inside, with its return value interpreted as the result of the
test. If arguments are added to <CODE>[if explicit args]</CODE>, those will be passed as arguments are in the <CODE>[perl]</CODE> construct.

<P><DT><STRONG><A NAME="item__if_">[/if]</A></STRONG><DD>

Terminates an if conditional.

<P></DL>
<P>
<HR>


code: 09.08
section: MINIVEND_TAG_REFERENCE
type: item
title: TAG -- the catch all

<A NAME="TAG_the_catch_all">TAG -- the catch all</A></H2>
<P>
Many MiniVend functions can be controlled or specified with <CODE>[tag ...][/tag]</CODE>
pairs.

<P>
Named syntax:

<P>
<PRE>    [tag op=operation arg=&quot;arg1 arg2 ...&quot;]other[/tag]
</PRE>
<DL>
<DT><STRONG><A NAME="item__tag">[tag arg* arg*]text[/tag]</A></STRONG><DD>

Performs any of a number of operations, based on the presence of <A HREF="#item_arg">arg</A>. The arguments that may be given are:

<P><DL>
<DT><STRONG><A NAME="item_each">each database</A></STRONG><DD>

Returns a loop-list with every key in <A HREF="#item_database">database</A> evaluated as the <CODE>[loop-code]</CODE>. This will return the key and field <A HREF="#item_name">name</A>
for every record in the <A HREF="#item_products">products</A> database:

<P>
<PRE>    [tag each products][loop-code]  [loop-field name]&lt;BR&gt;[/tag]
</PRE>
<P><DT><STRONG><A NAME="item_export">export database file* type*</A></STRONG><DD>

Exports a complete MiniVend database to its text source file (or any
specified file). The integer <CODE>n</CODE>, if specified, will select export in one of the enumerated MiniVend export
formats. The following tag will export the products database to
products.txt (or whatever you have defined its source file as), in the
format specified by the
<EM>Database</EM> directive:

<P>
<PRE>    [tag export products][/tag]
</PRE>
<P>
Same thing, except to the file products/new_products.txt:

<P>
<PRE>    [tag export products products/newproducts.txt][/tag]
</PRE>
<P>
Same thing, except the export is done with a 
<FONT SIZE=-1>PIPE</FONT> delimiter:

<P>
<PRE>    [tag export products products/newproducts.txt 5][/tag]
</PRE>
<P>
The file is relative to the catalog directory, and only may be an absolute
path name if <EM>NoAbsolute</EM> is set to <CODE>No</CODE>.

<P><DT><STRONG><A NAME="item_flag">flag arg</A></STRONG><DD>

Sets a MiniVend condition.

<P>
The following enables writes on the <A HREF="#item_products">products</A> and <CODE>sizes</CODE> databases held in MiniVend internal 
<FONT SIZE=-1>DBM</FONT> format:

<P>
<PRE>    [tag flag write]products sizes[/tag]
</PRE>
<P>

<FONT SIZE=-1>SQL</FONT> databases are always writable if allowed by the 
<FONT SIZE=-1>SQL</FONT> database itself -- in-memory databases will never be written.


<P>
The <CODE>[tag flag build][/tag]</CODE> combination forces static build of a page, even if dynamic elements are
contained. Similarly, the <CODE>[tag flag cache][/tag]</CODE>
forces search or page caching (not usually wise).

<P><DT><STRONG><A NAME="item_log">log dir/file</A></STRONG><DD>

Logs a message to a file, fully interpolated for MiniVend tags. The
following tag will send every item code and description in the user's
shopping cart to the file logs/transactions.txt:

<P>
<PRE>    [tag log logs/transactions.txt]
    [item_list][item-code]  [item-description]
    [/item_list][/tag]
</PRE>
<P>
The file is relative to the catalog directory, and only may be an absolute
path name if <EM>NoAbsolute</EM> is set to <CODE>No</CODE>.

<P><DT><STRONG><A NAME="item_mime">mime description_string</A></STRONG><DD>

Returns a MIME-encapsulated message with the boundary as employed in the
other mime tags, and the <CODE>description_string</CODE> used as the Content-Description. For example

<P>
<PRE>   [tag mime My Plain Text]Your message here.[/tag]
</PRE>
<P>
will return

<P>
<PRE>  Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
  Content-ID: [sequential, lead as in mime boundary]
  Content-Description: My Plain Text
  
  Your message here.
</PRE>
<P>
<CODE>When used in concert with [tag mime boundary]&lt;CODE&gt;&lt;/CODE&gt;, [tag mime header]</CODE>, and
<CODE>[tag mime id]</CODE>, allows 
<FONT SIZE=-1>MIME</FONT> attachments to be included -- typically with
PGP-encrypted credit card numbers. See the demo page ord/report.html for an
example.

<P><DT><STRONG>mime boundary</STRONG><DD>

Returns a 
<FONT SIZE=-1>MIME</FONT> message boundary with unique string keyed on session 
<FONT SIZE=-1>ID,</FONT> page count, and time.


<P><DT><STRONG>mime header</STRONG><DD>

Returns a 
<FONT SIZE=-1>MIME</FONT> message header with the proper boundary for that session 
<FONT SIZE=-1>ID,</FONT> page count, and time.


<P><DT><STRONG>mime id</STRONG><DD>

Returns a 
<FONT SIZE=-1>MIME</FONT> message id with the proper boundary for that session 
<FONT SIZE=-1>ID,</FONT> page count, and time.


<P><DT><STRONG>[tag scan/options]encased text[/tag]</STRONG><DD>

Builds a one-click search based on the enclosed text. Properly translates
whitespace and non-word characters to be parseable by MiniVend. You can add
the normal scan options, just the se=searchtext parameter will be affected.
These two sequences evaluate the same:

<P>
<PRE>    [tag scan/sf=category]Renaissance[/tag]
    [page scan sf=category/se=Renaissance]Renaissance[/page]
</PRE>
<P>
Where it is useful is in adding long strings that would otherwise be
difficult to encode, like

<P>
<PRE>    [tag scan/sf=author/os=yes]John F. Kennedy[/tag]
</PRE>
<P>
instead of:

<P>
<PRE>    [page scan sf=author/se=John%20F.%20Kennedy]John F. Kennedy[/page]
</PRE>
<P><DT><STRONG><A NAME="item_show_tags">show_tags</A></STRONG><DD>

The encased text will not be substituted for with MiniVend tags, with &lt; and [ characters changed to <CODE>&amp;</CODE>#lt; and <CODE>&amp;</CODE>#91; respectively.

<P>
<PRE>    [tag show_tags][value whatever][/tag]
</PRE>
<P><DT><STRONG><A NAME="item_time">time</A></STRONG><DD>

Formats the current time according to 
<FONT SIZE=-1>POSIX</FONT> strftime arguments. The following is the string
for Thursday, April 30, 1997.

<P>
<PRE>    [tag time]%A, %B %d, %Y[/tag]
</PRE>
<P><DT><STRONG><A NAME="item_touch">touch</A></STRONG><DD>

Touches a database to allow use of the <CODE>tag_data()</CODE> routine in
user-defined subroutines. If this is not done, the routine will error out
if the database has not previously been accessed on the page.

<P>
<PRE>    [tag touch products][/tag]
</PRE>
<P></DL>
<DT><STRONG><A NAME="item__comment_">[comment] code [/comment]</A></STRONG><DD>

Comments out MiniVend tags (and anything else) from a page. The contents
are not displayed unless DisplayComments is set in minivend.cfg. Can be
nested.

<P><DT><STRONG><A NAME="item__perl">[perl args] code [/perl]</A></STRONG><DD>

See the section on <EM>Embedded Perl Code</EM>.

<P></DL>
<P>
<HR>


code: 09.09
section: MINIVEND_TAG_REFERENCE
type: item
title: User-defined Tags

<A NAME="User_defined_Tags">User-defined Tags</A></H2>
<P>
MiniVend 3.04 allows the definition of user tags when using the new parsed 
<FONT SIZE=-1>HTML</FONT> syntax (a <CODE>[new]</CODE> tag is on the page). They will not work with the old syntax. 3.06 adds the
tags on a server-wide basis, defined in <CODE>minivend.cfg</CODE>.

<P>
To define a tag that is catalog-specific, place <EM>UserTag</EM> directives in your catalog.cfg file. For server-wide tags, define them in
minivend.cfg. Catalog-specific tags take precedence if both are defined --
in fact, you can override the base MiniVend tag set with them. The
directive takes the form:

<P>
<PRE>   UserTag  tagname  property  value
</PRE>
<P>
where <CODE>tagname</CODE> is the name of the tag, <CODE>property</CODE> is the attribute (described below), and <A HREF="#item_value">value</A> is the value of the property for that tagname.

<P>
The user tags can either be based on Perl subroutines or just be aliases
for existing tags. Some quick examples are below.

<P>
An alias:

<P>
<PRE>    UserTag product_name Alias     data products title
</PRE>
<P>
This will change <CODE>[product_name 99-102]</CODE> into <CODE>[data products title 99-102]</CODE>, which will output the <CODE>title</CODE> database field for product code <CODE>99-102</CODE>. Don't use this with <CODE>[item-data ...]</CODE> and <CODE>[item-field ...]</CODE>, as they are parsed separately. You can do <CODE>[product-name [item-code]]</CODE>, though.

<P>

<FONT SIZE=-1>A</FONT> simple subroutine:

<P>
<PRE>    UserTag company_name Routine   sub { &quot;Your company name&quot; }
</PRE>
<P>
When you place a <CODE>[company-name]</CODE> tag in a MiniVend page, the text 
<CODE>Your company name</CODE> will be substituted.

<P>

<FONT SIZE=-1>A</FONT> subroutine with a passed text as an argument:

<P>
<PRE>    UserTag caps   Routine   sub { return &quot;\U@_&quot; }
    UserTag caps   HasEndTag 
</PRE>
<P>
The tag <CODE>[caps]This text should be all upper case[/caps]</CODE> will become
<CODE>THIS TEXT SHOULD BE ALL UPPER CASE</CODE>.

<P>
Here is a useful one you might wish to use:

<P>
<PRE>    UserTag quick_table HasEndTag
    UserTag quick_table Interpolate
    UserTag quick_table Order   border
    UserTag quick_table Routine &lt;&lt;EOF
    sub {
        my ($border,$input) = @_;
        $border = &quot; BORDER=$border&quot; if $border;
        my $out = &quot;&lt;TABLE ALIGN=LEFT$border&gt;&quot;;
        my @rows = split /\n+/, $input;
        my ($left, $right);
        for(@rows) {
            $out .= '&lt;TR&gt;&lt;TD ALIGN=RIGHT VALIGN=TOP&gt;';
            ($left, $right) = split /\s*:\s*/, $_, 2;
            $out .= '&lt;B&gt;' unless $left =~ /&lt;/;
            $out .= $left;
            $out .= '&lt;/B&gt;' unless $left =~ /&lt;/;
            $out .= '&lt;/TD&gt;&lt;TD VALIGN=TOP&gt;';
            $out .= $right;
            $out .= '&lt;/TD&gt;&lt;/TR&gt;';
            $out .= &quot;\n&quot;;
        }
        $out .= '&lt;/TABLE&gt;';
    }
    EOF
</PRE>
<P>
Called with:

<P>
<PRE>    [quick-table border=2]
    Name: [value name]
    City: [value city][if value state], [value state][/if] [value country]
    [/quick_table]
</PRE>
<P>
The properties for UserTag are are:

<DL>
<DT><STRONG><A NAME="item_AddAttr">AddAttr</A></STRONG><DD>

Add the attribute hash to the parameters already defined to be sent by the <EM>Order</EM> setting. This includes the canned attributes <A HREF="#item_true">true</A>,
<A HREF="#item_false">false</A>, <CODE>undef</CODE>, <CODE>interpolate</CODE>, and any other attributes you have set in the tag. Allows your tag routine
to take a hash reference with the important parameters. Example:

<P>
<PRE>    UserTag echo-params AddAttr
    UserTag echo-params Routine &lt;&lt;EOR
    sub {
        my($ref) = @_;
        my $out;
        for (sort keys %$ref) {
            # skip these meaningless parameters
            next if /^(undef|true|false)$/;
</PRE>
<P>
<PRE>            $out .= &quot;$_=&quot;;
            $out .= '&quot;';
            $out .= $ref-&gt;{$_};
            $out .= '&quot;'
            $out .= &quot;\n&quot;;
        }
        return $out;
    }
    EOR
</PRE>
<P>
If you define the above UserTag and put put this on a MiniVend page

<P>
<PRE>    &lt;PRE&gt;
    [echo-params  Param1=1 param2=2 param3=three]
    &lt;/PRE&gt;
</PRE>
<P>
the resulting output will be:

<P>
<PRE>    interpolate=&quot;0&quot;
    param1=&quot;1&quot;
    param2=&quot;2&quot;
    param3=&quot;three&quot;
</PRE>
<P>
The <CODE>interpolate</CODE> parameter is always present for every tag, and defines the behavior of
container text or output depending on the value of <A HREF="#item_HasEndTag">HasEndTag</A>.

<P><DT><STRONG><A NAME="item_Alias">Alias</A></STRONG><DD>

An alias for an existing (or other user-defined) tag. It takes the form:

<P>
<PRE>    UserTag tagname Alias    tag to insert
</PRE>
<P>
An Alias is the only property that does not require a <EM>Routine</EM>
to process the tag.

<P><DT><STRONG><A NAME="item_attrAlias">attrAlias</A></STRONG><DD>

An alias for an existing attribute for defined tag. It takes the form:

<P>
<PRE>    UserTag tagname attrAlias   alias attr
</PRE>
<P>
As an example, the standard MiniVend <A HREF="#item_value">value</A> tag takes a named attribute of <A HREF="#item_name">name</A> for the variable name, meaning that <CODE>[value name=var]</CODE>
will display the value of form field <CODE>var</CODE>. If you put this line in catalog.cfg:

<P>
<PRE>    UserTag value attrAlias   identifier name
</PRE>
<P>
then <CODE>[value identifier=var]</CODE> will be an equivalent tag.

<P><DT><STRONG><A NAME="item_CanNest">CanNest</A></STRONG><DD>

Notifies MiniVend that this tag must be checked for nesting. Only applies
to tags that have <EM>HasEndTag</EM> defined, of course. 
<FONT SIZE=-1>NOTE:</FONT> Your routine must handle the subtleties of
nesting, so don't use this unless you are quite conversant with parsing
routines. See the routines <CODE>tag_loop_list</CODE> and <CODE>tag_if</CODE> in lib/Vend/Interpolate.pm for an example of a nesting tag.

<P>
<PRE>    UserTag tagname CanNest
</PRE>
<P><DT><STRONG><A NAME="item_HasEndTag">HasEndTag</A></STRONG><DD>

Defines an ending <CODE>[/tag]</CODE> to encapsulate your text -- the text in between the beginning <CODE>[tagname]</CODE> and ending <CODE>[/tagname]</CODE> will be the last argument sent to the defined subroutine.

<P>
<PRE>    UserTag tagname HasEndTag
</PRE>
<P><DT><STRONG><A NAME="item_Implicit">Implicit</A></STRONG><DD>

This defines an attribute as implicit, meaning it can just be an <CODE>attribute</CODE> 
instead of an <CODE>attribute=value</CODE> pair. It must be a recognized attribute in the tag definition, or there
will be big problems. Use this with caution!

<P>
<PRE>    UserTag tagname Implicit attribute value
</PRE>
<P>
If you want to set a standard include file to a fixed value by default, but
don't want to have to specify <CODE>[include file=&quot;/long/path/to/file&quot;]</CODE>
every time, you can just put:

<P>
<PRE>    UserTag include Implicit file file=/long/path/to/file
</PRE>
<P>
and <CODE>[include file]</CODE> will be the equivalent. You can still specify another value with <CODE>[include file=&quot;/another/path/to/file&quot;]</CODE>



<P><DT><STRONG><A NAME="item_InsertHTML">InsertHTML</A></STRONG><DD>

This attribute makes 
<FONT SIZE=-1>HTML</FONT> tag output be inserted into the containing tag,
in effect adding an attribute=value pair (or pairs).

<P>
<PRE>    UserTag tagname InsertHTML   htmltag  mvtag|mvtag2|mvtagN
</PRE>
<P>
In MiniVend's standard tags, among others, the &lt;
<FONT SIZE=-1>OPTION</FONT> ...&gt; tag has the
<CODE>[selected ..]</CODE> and <CODE>[checked ...]</CODE> tags included with them, so that you can do:

<P>
<PRE>   &lt;INPUT TYPE=checkbox
        MV=&quot;checked mvshipmode upsg&quot; NAME=mv_shipmode&gt; UPS Ground shipping
</PRE>
<P>
to expand to this:

<P>
<PRE>   &lt;INPUT TYPE=checkbox CHECKED NAME=mv_shipmode&gt; UPS Ground shipping
</PRE>
<P>
Providing, of course, that <CODE>mv_shipmode</CODE>  <STRONG>is</STRONG> equal to <A HREF="#item_upsg">upsg</A>. If you want to turn off this behavior on a per-tag basis, add the
attribute mv.noinsert=1 to the tag on your page.

<P><DT><STRONG><A NAME="item_InsideHTML">InsideHTML</A></STRONG><DD>

To make a container tag be placed <STRONG>after</STRONG> the containing 
<FONT SIZE=-1>HTML</FONT> tag, use the InsideHTML setting.

<P>
<PRE>    UserTag tagname InsideHTML   htmltag  mvtag|mvtag2|mvtagN
</PRE>
<P>
In MiniVend's standard tags, the only InsideHTML tag is the &lt;
<FONT SIZE=-1>SELECT&gt;</FONT> tag when used with <EM>loop</EM>, which causes this:

<P>
<PRE>   &lt;SELECT MV=&quot;loop upsg upsb upsr&quot; NAME=mv_shipmode&gt;
   &lt;OPTION VALUE=&quot;[loop-code]&quot;&gt; [shipping-desc [loop-code]]
   &lt;/SELECT&gt;
</PRE>
<P>
to expand to this:

<P>
<PRE>   &lt;SELECT NAME=mv_shipmode&gt;
   [loop upsg upsb upsr]
   &lt;OPTION VALUE=&quot;[loop-code]&quot;&gt; [shipping-desc [loop-code]]
   [/loop]
   &lt;/SELECT&gt;
</PRE>
<P>
Without the InsideHTML setting, the <CODE>[loop ...]</CODE> would have been <STRONG>outside</STRONG>
of the select -- not what you want. If you want to turn off this behavior
on a per-tag basis, add the attribute mv.noinside=1 to the tag on your
page.

<P><DT><STRONG><A NAME="item_Interpolate">Interpolate</A></STRONG><DD>

The behavior for this attribute depends on whether the tag is a container
(i.e. <A HREF="#item_HasEndTag">HasEndTag</A> is defined). If it is not a container, the <A HREF="#item_Interpolate">Interpolate</A>
attribute causes the <STRONG>the resulting HTML</STRONG> from the <CODE>UserTag</CODE> will be re-parsed for more MiniVend tags. If it is a container, <A HREF="#item_Interpolate">Interpolate</A>
causes the contents of the tag to be parsed <STRONG>before</STRONG> the tag routine is run.

<P>
<PRE>    UserTag tagname Interpolate
</PRE>
<P><DT><STRONG><A NAME="item_InvalidateCache">InvalidateCache</A></STRONG><DD>

If this is defined, the presence of the tag on a page will prevent search
cache, page cache, and static builds from operating on the page.

<P>
<PRE>    UserTag tagname InvalidateCache
</PRE>
<P>
It does not override <CODE>[tag flag build][/tag]</CODE>, though.

<P><DT><STRONG><A NAME="item_Order">Order</A></STRONG><DD>

The optional arguments that can be sent to the tag. This defines not only
the order in which they will be passed to <EM>Routine</EM>, but the name of the tags. If encapsulated text is appropriate (<EM>HasEndTag</EM> is set), it will be the last argument.

<P>
<PRE>    UserTag tagname Order param1 param2
</PRE>
<P><DT><STRONG><A NAME="item_PosRoutine">PosRoutine</A></STRONG><DD>

Identical to the Routine argument -- a subroutine that will be called when
the new syntax is not used for the call, i.e. <CODE>[usertag argument]</CODE> instead of <CODE>[usertag ARG=argument]</CODE>. If not defined, <EM>Routine</EM> is used, and MiniVend will usually do the right thing.

<P><DT><STRONG><A NAME="item_ReplaceAttr">ReplaceAttr</A></STRONG><DD>

Works in concert with InsertHTML, defining a <STRONG>single</STRONG> attribute which will be replaced in the insertion operation.

<P>
<PRE>  UserTag tagname ReplaceAttr  htmltag attr
</PRE>
<P>
An example is the standard 
<FONT SIZE=-1>HTML</FONT> &lt;
<FONT SIZE=-1>A</FONT> 
<FONT SIZE=-1>HREF=...&gt;</FONT> tag. If you want to use the MiniVend tag
 <CODE>[area pagename]</CODE> inside of it, then you would normally want to replace the 
<FONT SIZE=-1>HREF</FONT> attribute. So the equivalent to the following is
defined within MiniVend:

<P>
<PRE>  UserTag  area  ReplaceAttr  a  href
</PRE>
<P>
Causing this

<P>
<PRE>    &lt;A MV=&quot;area pagename&quot; HREF=&quot;a_test_page.html&quot;&gt;
</PRE>
<P>
to become

<P>
<PRE>    &lt;A HREF=&quot;<A HREF="http://yourserver/cgi/simple/pagename?X8sl2lly">http://yourserver/cgi/simple/pagename?X8sl2lly</A>;;44&quot;&gt;
 
when intepreted.
    
=item ReplaceHTML
</PRE>
<P>
For HTML-style tag use only. Causes the tag containing the MiniVend tag to
be stripped and the result of the tag to be inserted, for certain tags. For
example:

<P>
<PRE>  UserTag company_name Routine sub { my $l = shift; return &quot;$l: XYZ Company&quot; }
  UserTag company_name HasEndTag
  UserTag company_name ReplaceHTML  b    company_name
</PRE>
<P>

<FONT SIZE=-1>&lt;BR&gt;</FONT> is the 
<FONT SIZE=-1>HTML</FONT> tag, and ``company_name'' is the MiniVend tag. At that point, the usage:


<P>
<PRE>    &lt;B MV=&quot;company-name&quot;&gt; Company &lt;/B&gt;  ---&gt;&gt;  Company: XYZ Company
</PRE>
<P>
Tags not in the list will not be stripped:

<P>
<PRE>    &lt;I MV=&quot;company-name&quot;&gt; Company &lt;/I&gt; ---&gt;&gt;  &lt;I&gt;Company: XYZ Company&lt;/I&gt;
</PRE>
<P><DT><STRONG><A NAME="item_Routine">Routine</A></STRONG><DD>

An inline subroutine that will be used to process the arguments of the tag.
It must not be named, and will be allowed to access unsafe elements only if
the <CODE>minivend.cfg</CODE> parameter <EM>AllowGlobal</EM> is set for the catalog.

<P>
<PRE>    UserTag tagname Routine  sub { &quot;your perl code here!&quot; }
</PRE>
<P>
The routine may use a ``here'' document for readability:

<P>
<PRE>    UserTag tagname Routine &lt;&lt;EOF
    sub {
        my ($param1, $param2, $text) = @_;
        return &quot;Parameter 1 is $param1, Parameter 2 is $param2&quot;;
    }
    EOF
</PRE>
<P>
The usual <EM>here documents</EM> caveats apply.

<P>
Parameters defined with the <EM>Order</EM> property will be sent to the routine first, followed by any encapsulated
text (<EM>HasEndTag</EM> is set).

<P></DL>
<P>
Note that the UserTag facility, combined with AllowGlobal, allows the user
to define tags just as powerful as the standard MiniVend tags. This is not
recommended for the novice, though -- keep it simple. 8-)

<P>
<HR>


code: 09.10
section: MINIVEND_TAG_REFERENCE
type: item
title: PRICE, DESCRIPTION, ACCESSORIES

<A NAME="PRICE_DESCRIPTION_ACCESSORIES">PRICE, DESCRIPTION, ACCESSORIES</A></H2>
<DL>
<DT><STRONG><A NAME="item__price">[price code quantity* database* noformat*]</A></STRONG><DD>

named attributes: <CODE>[price code=&quot;code&quot; quantity=&quot;quantity&quot; base=&quot;database&quot; noformat=1*]</CODE>



<P>
Expands into the price of the product identified by code as found in the
products database. If there is more than one products file defined, they
will be searched in order unless constrained by the optional argument <STRONG>base</STRONG>. The optional argument <STRONG>quantity</STRONG> selects an entry from the quantity price list. To receive a raw number,
with no currency formatting, use the option <CODE>noformat=1</CODE>.

<P><DT><STRONG><A NAME="item__description">[description code database*]</A></STRONG><DD>

named attributes: <CODE>[description code=&quot;code&quot; base=&quot;database&quot;]</CODE>



<P>
Expands into the description of the product identified by code as found in
the products database. If there is more than one products file defined,
they will be searched in order unless constrained by the optional argument <STRONG>base</STRONG>.

<P><DT><STRONG><A NAME="item__accessories">[accessories code attribute*, type*, field*, database*, name*, outboard*]</A></STRONG><DD>

named attributes: <CODE>[accessories code=&quot;code&quot;</CODE>

<CODE>arg=&quot;attribute*, type*, field*, database*, name*, outboard*&quot;]</CODE>



<P>
If not given one of the optional arguments, expands into the value of the
accessories database entry for the product identified by <EM>code</EM> as found in the products database.

<P>
If passed any of the optional arguments, initiates special processing of
item attributes based on entries in the product database.

<P>
See <EM>Item Attributes</EM> for a complete description of the arguments.

<P>
When called with an attribute, the database is consulted and looks for a
comma-separated list of attribute options. They take the form:

<P>
<PRE>    name=Label Text, name=Label Text*
</PRE>
<P>
The label text is optional -- if none is given, the <STRONG>name</STRONG> will be used.

<P>
If an asterisk is the last character of the label text, the item is the
default selection. If no default is specified, the first will be the
default. An example:

<P>
<PRE>    [accessories TK112 color]
</PRE>
<P>
This will search the product database for a field named ``color''. If an
entry ``beige=Almond, gold=Harvest Gold, White*, green=Avocado'' is found,
a select box like this will be built:

<P>
<PRE>    &lt;SELECT NAME=&quot;mv_order_color&quot;&gt;
    &lt;OPTION VALUE=&quot;beige&quot;&gt;Almond
    &lt;OPTION VALUE=&quot;gold&quot;&gt;Harvest Gold
    &lt;OPTION SELECTED&gt;White
    &lt;OPTION VALUE=&quot;green&quot;&gt;Avocado
    &lt;/SELECT&gt;
</PRE>
<P>
In combination with the <CODE>mv_order_item</CODE> and <CODE>mv_order_quantity</CODE> variables this can be used to allow entry of an attribute at time of order.

<P></DL>
<P>
<HR>


code: 09.11
section: MINIVEND_TAG_REFERENCE
type: item
title: FILE and INCLUDE

<A NAME="FILE_and_INCLUDE">FILE and INCLUDE</A></H2>
<P>
These elements read a file from the disk and insert the contents in the
location of the tag. <CODE>[include ...]</CODE> will allow insertion of MiniVend variables.

<DL>
<DT><STRONG><A NAME="item__file">[file ...]</A></STRONG><DD>

named: [file name=``name'' type=``dos|mac|unix''*]

<P>
positional: [file name]

<P>
Inserts the contents of the named file. The file should normally be
relative to the catalog directory -- file names beginning with / or .. are
only allowed if the MiniVend server administrator has disabled <EM>NoAbsolute</EM>.

<P>
The optional <A HREF="#item_type">type</A> parameter will do an appropriate 
<FONT SIZE=-1>ASCII</FONT> translation on the file before it is sent.

<P><DT><STRONG><A NAME="item__include">[include file]</A></STRONG><DD>

named attributes: <CODE>[include file=&quot;name&quot;]</CODE>



<P>
<STRONG>NOTE:</STRONG> New to MiniVend 3.04.

<P>
Same as <CODE>[file name]</CODE> except interpolates for all MiniVend tags and variables.

<P></DL>
<P>
<HR>


code: 09.12
section: MINIVEND_TAG_REFERENCE
type: item
title: BODY, BUTTONBAR, RANDOM, ROTATE

<A NAME="BODY_BUTTONBAR_RANDOM_ROTATE">BODY, BUTTONBAR, RANDOM, ROTATE</A></H2>
<P>
Tags to help manage page appearance and advertising links:

<DL>
<DT><STRONG><A NAME="item__body">[body n extra*]</A></STRONG><DD>

named attributes: <CODE>[body type=&quot;n&quot; extra=&quot;ATTRIBUTE&quot;]</CODE>



<P>
Selects from the predefined color schemes and/or backgrounds, and just
becomes a &lt;
<FONT SIZE=-1>BODY&gt;</FONT> tag if none are defined. The <CODE>extra</CODE> parameter is always appended. See <EM>CONTROLLING PAGE APPEARANCE</EM>.

<P><DT><STRONG><A NAME="item__buttonbar">[buttonbar n]</A></STRONG><DD>

named attributes: <CODE>[buttonbar type=&quot;n&quot;]</CODE>



<P>
Selects from the predefined buttonbars, and is stripped if it doesn't
exist. See <EM>CONTROLLING PAGE APPEARANCE</EM>.

<P><DT><STRONG><A NAME="item__random_">[random]</A></STRONG><DD>

Selects from the predefined random messages, and is stripped if none exist.
See <EM>CONTROLLING PAGE APPEARANCE</EM>.

<P><DT><STRONG><A NAME="item__rotate">[rotate ...]</A></STRONG><DD>

named: [rotate floor=``n'' ceiling=``n'']

<P>
positional: [rotate ceiling* floor*]

<P>

<FONT SIZE=-1>AUTOINTERPOLATE:</FONT> Yes, can be turned off with 
<FONT SIZE=-1>INTERPOLATE=0</FONT>


<P>
Selects from the predefined rotating banner messages, and is stripped if
none exist. The optional <CODE>ceiling</CODE> sets the highest number that will be selected -- likewise <CODE>floor</CODE> sets the lowest. The default is to sequence through all defined rotating
banners. Each user has a separate rotation pattern, and each floor/ceiling
combination has a separate rotation value.

<P></DL>
<P>
<HR>


code: 09.13
section: MINIVEND_TAG_REFERENCE
type: item
title: Tags for summarizing shopping basket/cart

<A NAME="Tags_for_summarizing_shopping_ba">Tags for summarizing shopping basket/cart</A></H2>
<P>
The following elements are used to access common items which need to be
displayed on baskets and checkout pages.

<P>
<STRONG>* marks an optional parameter</STRONG>



<DL>
<DT><STRONG><A NAME="item__item_list">[item-list cart*]</A></STRONG><DD>

named attributes: <CODE>[item-list name=&quot;cart&quot;]</CODE>



<P>
Places an iterative list of the items in the specified shopping cart, the
main cart by default. See <EM>Item Lists</EM> for a description.

<P><DT><STRONG><A NAME="item__item_list_">[/item-list]</A></STRONG><DD>

Terminates the <CODE>[item-list]</CODE> tag.

<P><DT><STRONG>[value field flag*]</STRONG><DD>

Expands into the current value of the customer input field named by field.
If <EM>flag</EM> is present, single and double quotes will be escaped with a backslash; this allows reliable 
<FONT SIZE=-1>SQL</FONT> inserts. See the section on input fields for more information.


<P><DT><STRONG><A NAME="item__nitems">[nitems cart*]</A></STRONG><DD>

Expands into the total number of items ordered so far. Takes an optional
cart name as a parameter.

<P><DT><STRONG><A NAME="item__subtotal_">[subtotal]</A></STRONG><DD>

Expands into the subtotal cost, exclusive of sales tax, of all the items
ordered so far.

<P><DT><STRONG><A NAME="item__salestax">[salestax cart*]</A></STRONG><DD>

Expands into the sales tax on the subtotal of all the items ordered so far.
If there is no key field to derive the proper percentage, such as state or
zip code, it is set to 0. See <EM>Sales Tax</EM> for more information.

<P><DT><STRONG><A NAME="item__shipping_description">[shipping-description mode*]</A></STRONG><DD>

named attributes: <CODE>[shipping-description name=&quot;mode&quot;]</CODE>



<P>
The text description of <STRONG>mode</STRONG> -- the default is the shipping mode currently selected.

<P><DT><STRONG><A NAME="item__shipping">[shipping mode*]</A></STRONG><DD>

named attributes: <CODE>[shipping name=&quot;mode&quot;]</CODE>



<P>
The shipping cost of the items in the basket via <CODE>mode</CODE> -- the default mode is the shipping mode currently selected in the <CODE>mv_shipmode</CODE>
variable. See <EM>SHIPPING</EM>.

<P><DT><STRONG><A NAME="item__total_cost">[total-cost cart*]</A></STRONG><DD>

Expands into the total cost of all the items in the current shopping cart,
including sales tax (if any).

<P><DT><STRONG><A NAME="item__calc_">[calc]</A></STRONG><DD>

Starts a region where the arguments are calculated according to normal
arithmetic symbols. For instance:

<P>
<PRE>    [calc] 2 + 2 [/calc]
</PRE>
<P>
will display:

<P>
<PRE>    4
</PRE>
<P><DT><STRONG><A NAME="item__calc_">[/calc]</A></STRONG><DD>

Terminates the calculated region.

<P>
The <CODE>[calc]</CODE> tag is really the same as the <CODE>[perl]</CODE> tag, except that it doesn't accept arguments, is more efficient to parse,
and is interpolated at a higher precedence.

<P>

<FONT SIZE=-1>TIP:</FONT> The <CODE>[calc]</CODE> tag will remember variable values inside one page, so you can do the
equivalent of a memory store and memory recall for a loop.

<P><DT><STRONG><A NAME="item__currency">[currency convert*]</A></STRONG><DD>

named attributes: <CODE>[currency convert=1*]</CODE>



<P>
When passed a value of a single number, formats it according to the
currency specification. For instance:

<P>
<PRE>    [currency]4[/currency]
</PRE>
<P>
will display:

<P>
<PRE>    4.00
</PRE>
<P>
Uses the <EM>Locale</EM> and <EM>PriceCommas</EM> settings as appropriate, and can contain a <CODE>[calc]</CODE> region. If the optional ``convert'' parameter is set, it will convert
according to PriceDivide&gt; for the current locale. If Locale is set to <CODE>fr_FR</CODE>, and <EM>PriceDivide</EM> for <CODE>fr_FR</CODE> is 0.167, the following sequence

<P>
<PRE>    [currency convert=1] [calc] 500.00 + 1000.00 [/calc] [/currency]
</PRE>
<P>
will cause the number 8.982,04 to be displayed.

<P><DT><STRONG><A NAME="item__currency_">[/currency]</A></STRONG><DD>

Terminates the currency region.

<P><DT><STRONG><A NAME="item__cart">[cart name]</A></STRONG><DD>

named attributes: <CODE>[cart name=&quot;name&quot;]</CODE>



<P>
Sets the name of the current shopping cart for display of shipping, price,
total, subtotal, and nitems tags. If you wish to use a different price for
the cart, all of the above except <A HREF="#item__shipping_">[shipping]</A> will reflect the normal price field. You must emulate those operations with
embedded Perl or the
<CODE>[item-list]</CODE>, <CODE>[calc]</CODE>, and <CODE>[currency]</CODE> tags, or use the <EM>PriceAdjustment</EM>
feature to set it.

<P><DT><STRONG><A NAME="item__row">[row nn]</A></STRONG><DD>

named attributes: <CODE>[row width=&quot;nn&quot;]</CODE>



<P>
Formats text in tables. Intended for use in emailed reports or &lt;
<FONT SIZE=-1>PRE&gt;&lt;</FONT>
<FONT SIZE=-1>/PRE&gt;</FONT> 
<FONT SIZE=-1>HTML</FONT> areas. The parameter
 <EM>nn</EM> gives the number of columns to use. Inside the row tag, <CODE>[col param=value ...]</CODE> tags may be used. 

<P><DT><STRONG><A NAME="item__row_">[/row]</A></STRONG><DD>

Terminates a <CODE>[row nn]</CODE> element.

<P><DT><STRONG><A NAME="item__col">[col width=nn wrap=yes|no gutter=n align=left|right|input spacing=n]</A></STRONG><DD>

Sets up a column for use in a <CODE>[row]</CODE>. This parameter can only be contained inside a <CODE>[row nn] [/row]</CODE> tag pair. Any number of columns (that fit within the size of the row) can
be defined.

<P>
The parameters are:

<P>
<PRE>    width=nn        The column width, I&lt;including the gutter&gt;. Must be
                    supplied, there is no default. A shorthand method
                    is to just supply the number as the I&lt;first&gt; parameter,
                    as in [col 20].
        
    gutter=n        The number of spaces used to separate the column (on
                    the right-hand side) from the next. Default is 2.
        
    spacing=n       The line spacing used for wrapped text. Default is 1,
                    or single-spaced.
        
    wrap=(yes|no)   Determines whether text that is greater in length than
                    the column width will be wrapped to the next line. Default
                    is I&lt;yes&gt;.
        
    align=(L|R|I)   Determines whether text is aligned to the left (the default),
                    the right, or in a way that might display an HTML text
                    input field correctly.
</PRE>
<P><DT><STRONG><A NAME="item__col_">[/col]</A></STRONG><DD>

Terminates the column field.

<P></DL>
<P>
<HR>


code: 09.14
section: MINIVEND_TAG_REFERENCE
type: item
title: Item Lists

<A NAME="Item_Lists">Item Lists</A></H2>
<P>
Within any page, the <CODE>[item-list cart*]</CODE> element shows a list of all the items ordered by the customer so far. It
works by repeating the source between <CODE>[item-list]</CODE> and <CODE>[/item-list]</CODE> once for each item ordered.

<P>

<FONT SIZE=-1>NOTE:</FONT> The special tags that reference item within the list are not normal MiniVend tags, do not take named attributes, and cannot be contained in an 
<FONT SIZE=-1>HTML</FONT> tag (other than to substitute for one of its values or provide a conditional container). They are interpreted only inside their corresponding list container. Normal MiniVend tags can be interspersed, though they will be interpreted
 <EM>after</EM> all of the list-specific tags.

<P>
Between the item_list markers the following elements will return
information for the current item:

<DL>
<DT><STRONG><A NAME="item__if_data">[if-data table column]</A></STRONG><DD>

If the database field <CODE>column</CODE> in table <EM>table</EM> is non-blank, the following text up to the <CODE>[/if_data]</CODE> tag is substituted. This can be used to substitute 
<FONT SIZE=-1>IMG</FONT> or other tags only if the corresponding source
item is present. Also accepts a <CODE>[else]else text[/else]</CODE> pair for the opposite condition.

<P>

<FONT SIZE=-1>NOTE:</FONT> This tag does not nest with other <CODE>[if-data ...]</CODE> tags.

<P><DT><STRONG>[if-data ! table column]</STRONG><DD>

Reverses sense for <CODE>[if-data]</CODE>.

<P><DT><STRONG><A NAME="item__if_data_">[/if-data]</A></STRONG><DD>

Terminates an <CODE>[if_data table column]</CODE> element.

<P><DT><STRONG><A NAME="item__if_field">[if-field fieldname]</A></STRONG><DD>

If the products database field <EM>fieldname</EM> is non-blank, the following text up to the <CODE>[/if_field]</CODE> tag is substituted. If you have more than one products database table (see <EM>ProductFiles</EM>), it will check them in order until a matching key is found. This can be used to substitute 
<FONT SIZE=-1>IMG</FONT> or other tags only if the corresponding source item is present. Also accepts a
 <CODE>[else]else text[/else]</CODE> pair for the opposite condition.

<P>

<FONT SIZE=-1>NOTE:</FONT> This tag does not nest with other <CODE>[if-field ...]</CODE> tags.

<P><DT><STRONG>[if-field ! fieldname]</STRONG><DD>

Reverses sense for <CODE>[if-field]</CODE>.

<P><DT><STRONG><A NAME="item__if_field_">[/if-field]</A></STRONG><DD>

Terminates an <CODE>[if_field fieldname]</CODE> element.

<P><DT><STRONG><A NAME="item__item_accessories">[item-accessories attribute*, type*, field*, database*, name*]</A></STRONG><DD>

Evaluates to the value of the Accessories database entry for the item. If
passed any of the optional arguments, initiates special processing of item
attributes based on entries in the product database.

<P><DT><STRONG><A NAME="item__item_code_">[item-code]</A></STRONG><DD>

Evaluates to the product code for the current item.

<P><DT><STRONG><A NAME="item__item_data">[item-data database fieldname]</A></STRONG><DD>

Evaluates to the field name <EM>fieldname</EM> in the arbitrary database table <EM>database</EM>, for the current item.

<P><DT><STRONG><A NAME="item__item_description_">[item-description]</A></STRONG><DD>

Evaluates to the product description (from the products file) for the
current item.

<P><DT><STRONG><A NAME="item__item_field">[item-field fieldname]</A></STRONG><DD>

Evaluates to the field name <EM>fieldname</EM> in the products database, for the current item. If the item is not found in
the first of the
<EM>ProductFiles</EM>, all will be searched in sequence.

<P><DT><STRONG><A NAME="item__item_increment_">[item-increment]</A></STRONG><DD>

Evaluates to the number of the item in the match list. Used for numbering
search matches or order items in the list.

<P><DT><STRONG><A NAME="item__item_last_tags_item_last_">[item-last]tags[/item-last]</A></STRONG><DD>

Evaluates the output of the MiniVend tags encased inside the tags, and if
it evaluates to a numerical non-zero number (i.e. 1, 23, or -1) then the
list iteration will terminate. If the evaluated number is
<STRONG>negative</STRONG>, then the item itself will be skipped. If the evaluated number is <STRONG>positive</STRONG>, then the item itself will be shown but will be last on the list.

<P>
<PRE>      [item-last][calc]
        return -1 if '[item-field weight]' eq '';
        return 1 if '[item-field weight]' &lt; 1;
        return 0;
        [/calc][/item-last]
</PRE>
<P>
If this is contained in your <CODE>[item-list]</CODE> (or <CODE>[search-list]</CODE> or flypage) and the weight field is empty, then a numerical <CODE>-1</CODE> will be output from the <CODE>[calc][/calc]</CODE> tags; the list will end and the item will <STRONG>not</STRONG> be shown. If the product's weight field is less than 1, a numerical 1 is
output. The item will be shown, but will be the last item shown. (If it is
an <CODE>[item-list]</CODE>, any price for the item will still be added to the subtotal.) 
<FONT SIZE=-1>NOTE:</FONT> no 
<FONT SIZE=-1>HTML</FONT> style.


<P><DT><STRONG><A NAME="item__item_modifier">[item-modifier attribute]</A></STRONG><DD>

Evaluates to the modifier value of <CODE>attribute</CODE> for the current item.

<P><DT><STRONG><A NAME="item__item_next_tags_item_next_">[item-next]tags[/item_next]</A></STRONG><DD>

Evaluates the output of the MiniVend tags encased inside, and if it
evaluates to a numerical non-zero number (i.e. 1, 23, or -1) then the item
will be skipped with no output. Example:

<P>
<PRE>      [item-next][calc][item-field weight] &lt; 1[/calc][/item-next]
</PRE>
<P>
If this is contained in your <CODE>[item-list]</CODE> (or <CODE>[search-list]</CODE> or flypage) and the product's weight field is less than 1, then a numerical <CODE>1</CODE> will be output from the [calc][/calc] operation. The item will not be
shown. (If it is an <CODE>[item-list]</CODE>, any price for the item will still be added to the subtotal.)

<P><DT><STRONG><A NAME="item__item_price">[item-price n* noformat*]</A></STRONG><DD>

Evaluates to the price for quantity <CODE>n</CODE> (from the products file) of the current item, with currency formatting. If
the optional ``noformat'' is set, then currency formatting will not be
applied.

<P><DT><STRONG><A NAME="item__discount_price">[discount-price n* noformat*]</A></STRONG><DD>

Evaluates to the discount price for quantity <CODE>n</CODE> (from the products file) of the current item, with currency formatting. If
the optional ``noformat'' is set, then currency formatting will not be
applied. Returns regular price if not discounted.

<P><DT><STRONG><A NAME="item__item_discount_">[item-discount]</A></STRONG><DD>

Returns the difference between the regular price and the discounted price.

<P><DT><STRONG><A NAME="item__item_quantity_">[item-quantity]</A></STRONG><DD>

Evaluates to the quantity ordered for the current item.

<P><DT><STRONG><A NAME="item__item_subtotal_">[item-subtotal]</A></STRONG><DD>

Evaluates to the subtotal (quantity * price) for the current item. Quantity
price breaks are taken into account.

<P><DT><STRONG><A NAME="item__modifier_name">[modifier-name attribute]</A></STRONG><DD>

Evaluates to the name to give an input box in which the customer can
specify the modifier to the ordered item.

<P><DT><STRONG><A NAME="item__quantity_name_">[quantity-name]</A></STRONG><DD>

Evaluates to the name to give an input box in which the customer can enter
the quantity to order.

<P></DL>
<P>
<HR>


code: 09.15
section: MINIVEND_TAG_REFERENCE
type: item
title: Embedded Perl Code

<A NAME="Embedded_Perl_Code">Embedded Perl Code</A></H2>
<P>
Perl code can be directly embedded in MiniVend pages. The code is specified
as <CODE>[perl arguments*] any_legal_perl_code [/perl]</CODE>. The value returned by the code will be inserted on the page.

<P>
named attributes: <CODE>[perl arg=&quot;arguments&quot;* interpolate=1*]</CODE>



<P>

<FONT SIZE=-1>HTML</FONT> example:

<P>
<PRE>    &lt;PRE mv=perl mv.arg=&quot;values browser&quot;&gt;
        $name = $Safe{'values'}{'name'};
        $name = $Safe{'browser'};
        return &quot;Hi, $name! How do you like your $browser?
    &lt;/PRE&gt;
</PRE>
<P>
<STRONG>IMPORTANT NOTE:</STRONG> The <CODE>[perl]</CODE> tag enforces <EM>Safe.pm</EM> checking, and many standard Perl operators are not available. This is a <CODE>good</CODE> thing, as you would not want users having access to all files and programs
on the system with the MiniVend daemon's permissions! See <EM>GlobalSub</EM>
and <EM>UserTag</EM> for ways to make external files and programs available to MiniVend.

<P>
You can insert Minivend tags inside the Perl code, though when using the new syntax, you will need to pass an 
<FONT SIZE=-1>INTERPOLATE=1</FONT> parameter to have tags inside
 <CODE>[perl] and [/perl]</CODE> interpreted. (In the old syntax, most tags are evaluated before <CODE>[perl]</CODE>, though there are exceptions.)

<P>
More often you will want to use the tag access routine <STRONG>&safe_tag</STRONG>, which takes the tag name and any arguments as parameters. This has the advantage of only performing the operation when the code is executed. 
<FONT SIZE=-1>(A</FONT> few tags can't be used with safe_tag, notably ones accessing a database that has not previously been accessed on the page.)


<P>
Examples:

<P>
<PRE>    # New syntax
    # If the item might contain a single quote
    [perl interpolate=1]
    $comments = '[value comments escaped]';
    [/perl]
</PRE>
<P>
<PRE>    # Simple example, old syntax
    [compat][perl]
    $comments = '[value comments]';
    [/perl][/compat]
</PRE>
<P>
<PRE>    # Another method to avoid escape problems
    $comments = q{[value comments]};
</PRE>
<P>
<PRE>    # Works with all, only executed if code is reached
    $comments = safe_tag('value', 'comments');
</PRE>
<P>
This allows you to pass user-space variables for most needed operations.
You can pass whole lists of items with constructs like:

<P>
<PRE>    # Perl ignores the trailing comma
    my(%prices) = ( [item_list]
                    '[item_code]', '[item-price]',
                    [/item_list]);
</PRE>
<P>
The arguments that can be passed are any to all of:

<DL>
<DT><STRONG><A NAME="item_browser">browser</A></STRONG><DD>

The browser string from the users browser, read-only. Referred to in your
code as $Safe{browser}.

<P><DT><STRONG><A NAME="item_carts">carts</A></STRONG><DD>

Gives read-write access to all of the shopping carts. on order. This is an
array of hashes, and includes the product code, quantity, and any modifiers
you have specified. Referred to in your code as a reference to the array,
$Safe{items} or @{$Safe{items}}.

<P>
<PRE>    # Move contents of 'layaway' cart to main cart
    $Safe{carts}-&gt;{main} = $Safe{carts}-&gt;{layaway};
    $Safe{carts}-&gt;{main} = [];
</PRE>
<P>
Careful with this -- you can lose the items on order with improper code,
though syntax errors will be caught before the code is run.

<P><DT><STRONG><A NAME="item_cgi">cgi</A></STRONG><DD>

Gives read-only access to the actual variables that were passed in the current 
<FONT SIZE=-1>CGI</FONT> session. This is useful for testing what the user actually placed on the form, not just what MiniVend placed in the session. Called with


<P>
<PRE>  # Set if the user had a value for name in the *current* form
  $name = $Safe{'cgi'}-&gt;{name};
</PRE>
<P><DT><STRONG>config</STRONG><DD>

Gives read-write access to the configuration of the catalog. 
<FONT SIZE=-1>USE</FONT> 
<FONT SIZE=-1>WITH</FONT> 
<FONT SIZE=-1>EXTREME</FONT> 
<FONT SIZE=-1>CAUTION</FONT> -- many of the variables are references to anonymous arrays and hashes. You can crash your catalog if you modify the wrong thing. Referred to in your code as $Safe{config}, a reference to the hash containing the configuration structure. If you use this, it is recommended that you refer frequently to the MiniVend source code.


<P><DT><STRONG>discount</STRONG><DD>

Gives read-write access to session discounts, an anonymous hash. Referred
to in your code as $Safe-&gt;{discounts}.

<P><DT><STRONG>file</STRONG><DD>

If specified, the anchor text is a file name to read the Perl code from.
This allows code to be maintained in separate files, though you need to
remember that any MiniVend tags contained will generally not be
interpolated (depending on interpolation order and use of the <CODE>[[any]]</CODE>
and <CODE>[post]</CODE> modifiers). The file name is relative to the MiniVend base directory unless
specified as an absolute path.

<P><DT><STRONG><A NAME="item_frames">frames</A></STRONG><DD>

The true/false value determining whether frames processing is enabled.
Read-only -- you can set the value with <CODE>[frames-off]</CODE> or
<CODE>[frames-on]</CODE>. Referred to in your code as $Safe{frames}.

<P><DT><STRONG>items</STRONG><DD>

Gives read-only access to the items on order, <EM>for the current cart</EM>. This is an array of hashes, and includes the product code, quantity, and
any modifiers you have specified. Referred to in your code as a reference
to the array, $Safe{items} or @{$Safe{items}}.

<P>
<PRE>    # Product code of first item in cart
    $item_code = $Safe{items}-&gt;[0]-&gt;{code};  
</PRE>
<P>
<PRE>    # Quantity for third item in cart
    $item_code = $Safe{items}-&gt;[2]-&gt;{quantity};  
</PRE>
<P>
<PRE>    # Color of second item in cart
    $item_code = $Safe{items}-&gt;[2]-&gt;{color};  
</PRE>
<P><DT><STRONG>scratch</STRONG><DD>

Gives read-write access to the scratch variables, a reference to an
anonymous hash. Referred to in your code as $Safe{scratch}.

<P><DT><STRONG><A NAME="item_sub">sub</A></STRONG><DD>

If specified, the anchor text is a subroutine name and optional parameters
to be passed. The subroutine can be defined in three ways; as a global
subroutine (works for entire server); as a catalog-wide pre-defined
subroutine; or in a scratchpad variable. All are called with the same
syntax -- the arguments are passed in via the <CODE>@_</CODE> argument
array.

<P>
<STRONG>IMPORTANT NOTE:</STRONG> Global subroutines are not subject to the stringent security checking of
the <EM>Safe</EM> module, so almost anything goes there. The subroutine will be able to
modify any variable in MiniVend, and will be able to write to read and
write any file that the MiniVend daemon has permission to write. Though
this gives great power, it should be used with caution. Careful! They are
defined in the main minivend.cfg file, so should be safe from individual
users in a multi-catalog system.

<P>
Global subroutines are defined in <EM>minivend.cfg</EM> with the
<EM>GlobalSub</EM> directive, or in user catalogs which have been enabled via <EM>AllowGlobal</EM>. Global subroutines are much faster than the others as they are
pre-compiled. (Faster still are <EM>UserTag</EM>
definitions.)

<P>
Catalog subroutines are defined in <EM>catalog.cfg</EM>, with the <EM>Sub</EM> directive. They are subject to the stringent <EM>Safe.pm</EM>
security restrictions that are controlled by <EM>SafeUntrap</EM>. If you wish to have default arguments supplied to them, use the <EM>SubArgs</EM>
directive.

<P>
Scratch subroutines are defined in the pages, and are also subject to <EM>Safe.pm</EM> checking. See the beginning of this section for an example of a subroutine
definition. There is no ``sub name { }'' that surrounds it -- the
subroutine is named from the name of the scratch variable.

<P><DT><STRONG><A NAME="item_values">values</A></STRONG><DD>

Gives read-write access to the user variables, including the MiniVend
special variables, an anonymous hash. Referred to in your code as
%{Safe{'values'}} or $Safe{'values'}-&gt;{variable}.

<P>
<PRE>    # Read the user's selected shipping mode
    my $shipmode = $Safe{values}-&gt;{mv_shipmode};
</PRE>
<P></DL>
<P>
The code can be as complex as desired, but cannot use any operators that
modify the file system or use ``unsafe'' operations like ``system'',
``exec'', or backticks. These constraints are enforced with the default
permissions of the standard Perl module <EM>Safe</EM> -- operations may be untrapped on a system-wide basis with the <EM>SafeUntrap</EM> directive.

<P>
The result of the tag will be the result of the last expression evaluated,
just as in a subroutine. If there is a syntax error or other problem with
the code, there will be no output.

<P>
Here is a simple one which does the equivalent of the classic hello.pl
program:

<P>
<PRE>    [perl] my $tmp = &quot;Hello, world!&quot;; $tmp; [/perl]
</PRE>
<P>
Of course you wouldn't need to set the variable -- it is just there to show
the capability.

<P>
To echo the user's browser, but within some 
<FONT SIZE=-1>HTML</FONT> tags:

<P>
<PRE>    [perl arg=browser]
    my $html = '&lt;H5&gt;';
    $html .= $Safe{'browser'};
    $html .= '&lt;/H5&gt;';
    $html;
    [/perl]
</PRE>
<P>
To show the user their name, and the current time:

<P>
<PRE>    [perl arg=values]
</PRE>
<P>
<PRE>    my $string = &quot;Hi, &quot; . $Safe{'values'}{'name'} &quot;. The time is now &quot;;
    $string .= localtime;
    $string;
</PRE>
<P>
<PRE>    [/perl]
</PRE>
<P>
<HR>


code: 09.16
section: MINIVEND_TAG_REFERENCE
type: item
title: On-the-fly Catalog Pages

<A NAME="On_the_fly_Catalog_Pages">On-the-fly Catalog Pages</A></H2>
<P>
If an item is displayed on the search list (or order list) and there is a
link to a special page keyed on the item, MiniVend will attempt to build
the page ``on the fly''. It will look for the special page
<EM>flypage.html</EM>, which is used as a template for building the page. If
<CODE>[item-field fieldname]</CODE>, <CODE>[item-price]</CODE>, (etc.) elements are used on the page, quite complex and
information-packed pages can be built. The
<CODE>[if_field fieldname]</CODE> 
<FONT SIZE=-1>HTML</FONT> <CODE>[/if_field]</CODE> pair can be used to insert 
<FONT SIZE=-1>HTML</FONT> only if there is a non-blank value in a
particular field.

<P>
Because the tags are the same, an <CODE>[item-list]</CODE> cannot be used on an on-the-fly page. The <CODE>[loop arg=&quot;item item&quot;]</CODE> tag is still usable. If you want to have an on-the-fly page mixed in, use
the <CODE>[fly-list CODE BASE]</CODE>

<CODE>[/flylist]</CODE> pair, which essentially encapsulates a flypage within a page.

<DL>
<DT><STRONG><A NAME="item__fly_list">[fly-list code=&quot;product_code&quot; base=&quot;table&quot;] ... [/fly-list]</A></STRONG><DD>

(New tags mode only.)

<P>
Defines an area in a random page which performs the flypage lookup
function, implementing the tags below.

<P>
<PRE>   [fly-list code=&quot;[data session arg]&quot;]
    (contents of flypage.html)
   [/fly-list]
</PRE>
<P>
If you place the above around the contents of the demo flypage, in a file
named <CODE>flypage2.html</CODE>, it will make these two calls display identical pages:

<P>
<PRE>    [page 00-0011] One way to display the Mona Lisa [/page]
    [page flypage2 00-0011] Another way to display the Mona Lisa [/page]
</PRE>
<P></DL>
<P>
If the directive <EM>PageSelectField</EM> is set to a valid product database field which contains a valid MiniVend
page name (relative to the catalog pages directory, without the .html
suffix) it will be used to build the on-the-fly page.

<P>
Active tags in their order of interpolation:

<P>
<PRE> [if-field field]         Tests for a non-empty value in B&lt;field&gt;
 [if-data db field]       Tests for a non-empty B&lt;field&gt; in B&lt;db&gt;
 [item-code]              Product code of the displayed item
 [item-accessories args]  Accessory information (see I&lt;accessories&gt;)
 [item-description]       Description field information
 [item-price quantity*]   Product price (at B&lt;quantity&gt;)
 [item-field field]       Product database B&lt;field&gt;
 [item-data db field]     Database B&lt;db&gt; entry for B&lt;field&gt;
</PRE>
<P>
<HR>


code: 09.17
section: MINIVEND_TAG_REFERENCE
type: item
title: Checking Page HTML

<A NAME="Checking_Page_HTML">Checking Page HTML</A></H2>
<P>
MiniVend, as of release 3.02, allows you to debug your page 
<FONT SIZE=-1>HTML</FONT> with an external page checking program. Because
leaving this enabled on a production system is potentially a very bad
performance degradation, the program is set in a the global configuration
file with the <EM>CheckHTML</EM>
directive.

<P>
To check a page for validity, set the global directive <EM>CheckHTML</EM> 
to the name of the program (don't do any output redirection). 
<FONT SIZE=-1>A</FONT> good choice is the freely available program <EM>weblint</EM> -- it would be set in <EM>minivend.cfg</EM> with:

<P>
<PRE>    CheckHTML  /usr/local/bin/weblint -s -
</PRE>
<P>
Of course you must restart the server for it to be recognized. The full
path to the program should be used -- if you have trouble, check it from
the command line (as you should with all external programs called by
MiniVend).

<P>
Insert <CODE>[tag flag checkhtml][/tag]</CODE> at the top or bottom of pages you want to check, and the output of your
checker should be appended to the browser output as a comment, visible if
you view the page or frame source.

<P>
To do this only at times, use a <EM>Variable</EM> setting:

<P>
<PRE>    Variable  CHECK_HTML    [tag flag checkhtml][/tag]
</PRE>
<P>
and place 
<FONT SIZE=-1>__CHECK_HTML__</FONT> in your pages. You can then set the
Variable to the empty string if you wish to disable it.

<P>
<HR>


code: 09.17
section: MINIVEND_TAG_REFERENCE
type: item
title: Tags for controlling old syntax interpolation order

<A NAME="Tags_for_controlling_old_syntax_">Tags for controlling old syntax interpolation order</A></H2>
<DL>
<DT><STRONG><A NAME="item__any_">[[any]]</A></STRONG><DD>


<FONT SIZE=-1>NOTE:</FONT> This is not used in the new parser. If you are
using this mechanism you should be changing the way you do things, for this
style of tag will disappear in the next version of MiniVend.

<P>
Forces early interpolation of any tag. Sometimes needed if the order of
interpolation does not achieve the desired result (meaning you see MiniVend
tags displayed on the page).

<P>
<STRONG>NOTE:</STRONG> This is ignored if using the new syntax.

<P><DT><STRONG><A NAME="item__">[ n [any] HTML n ]</A></STRONG><DD>


<FONT SIZE=-1>NOTE:</FONT> This is not used in the new parser. If you are
using this mechanism you should be changing the way you do things, for this
style of tag will disappear in the next version of MiniVend.

<P>
Where n is a single digit in the range 0-9. If present, it forces early
interpolation of that region of MiniVend tags, and is differentiated from
other early interpolation areas. The enclosed MiniVend tags will still be
interpolated in the normal order, but it can usually be combined with the <CODE>[post]</CODE>  <CODE>[/post]</CODE> pair to achieve the desired order.

<P>
<STRONG>NOTE:</STRONG> This is ignored if using the new syntax.

<P><DT><STRONG><A NAME="item__post_">[post]</A></STRONG><DD>


<FONT SIZE=-1>NOTE:</FONT> This is not used in the new parser. If you are
using this mechanism you should be changing the way you do things, for this
style of tag will disappear in the next version of MiniVend.

<P>
Selects an area that will not be interpolated until after the rest of the
page is interpolated. If followed by a number, will match a terminating
<CODE>[/post]</CODE> tag with the corresponding number.

<P>
<STRONG>NOTE:</STRONG> This is ignored if using the new syntax.

<P><DT><STRONG><A NAME="item__post_">[/post]</A></STRONG><DD>

Terminates a <CODE>[post]</CODE> region.

<P></DL>
<P>
<HR>


code: 09.18
section: MINIVEND_TAG_REFERENCE
type: item
title: Required Pages

<A NAME="Required_Pages">Required Pages</A></H2>
<P>

<FONT SIZE=-1>A</FONT> number of 
<FONT SIZE=-1>HTML</FONT> pages are required for MiniVend operation. Typically they are used to transmit error messages, status of search or order operations, and other out of boundary conditions.


<P>
<STRONG>NOTE:</STRONG> The distributed demo does not use these default values.

<P>
The names of these pages can be set with the <EM>SpecialPage</EM>
directive. The standard pages and their default locations:

<DL>
<DT><STRONG><A NAME="item_badsearch">badsearch (pages/badsearch.html)</A></STRONG><DD>

The error page displayed if there is a system or user error with the search
engine. Overridden by mv_failpage if set on current form.

<P><DT><STRONG><A NAME="item_canceled">canceled (pages/canceled.html)</A></STRONG><DD>

The page displayed by MiniVend when an order has been canceled by the user.

<P><DT><STRONG><A NAME="item_catalog">catalog (pages/catalog.html)</A></STRONG><DD>

The main catalog page presented by MiniVend when another page is not
specified.

<P><DT><STRONG><A NAME="item_checkout">checkout (pages/order.html)</A></STRONG><DD>

The page the customer is sent to when checking out (the location pointed to
by a <CODE>[finish_order]</CODE> tag.

<P><DT><STRONG><A NAME="item_confirmation">confirmation (pages/confirmation.html)</A></STRONG><DD>

After the order is completed, the confirmation page is displayed.

<P><DT><STRONG><A NAME="item_failed">failed (pages/failed.html)</A></STRONG><DD>

If the sendmail program could not be invoked to email the completed order,
the failed.html page is displayed. (Sadly we don't know if the email was
successfully delivered).

<P><DT><STRONG><A NAME="item_flypage">flypage (pages/flypage.html)</A></STRONG><DD>

If the catalog page for an item was not found when its <CODE>[item-link]</CODE>
is clicked, this page is used as a template to build an on-the-fly page.
See <EM>On-the-fly Catalog Pages</EM>. If frames are in use, the special order page can be overridden with the
one configured with the directive
<EM>FrameFlyPage</EM>.

<P><DT><STRONG><A NAME="item_interact">interact (pages/interact.html)</A></STRONG><DD>

Displayed if an unexpected response was received from the browser, such as
not getting expected fields from submitting a form. This would probably
happen from typos in the html pages, but could be a browser bug.

<P><DT><STRONG><A NAME="item_missing">missing (pages/missing.html)</A></STRONG><DD>

This page is displayed if the 
<FONT SIZE=-1>URL</FONT> from the browser specifies a page that does not
have a matching .html file in the pages directory. This can happen if the
customer saved a bookmark to a page that was later removed from the
database.

<P><DT><STRONG><A NAME="item_needfield">needfield (pages/needfield.html)</A></STRONG><DD>

Displayed if the user did not fill in a required field in the order form.
See <EM>REQUIRED FIELDS</EM>.

<P><DT><STRONG><A NAME="item_nomatch">nomatch (pages/nomatch.html)</A></STRONG><DD>

This page is displayed if the search engine is used, but there is no match
for the search specification and no <A HREF="#item__no_match_">[no-match]</A>
region found on the search page.

<P><DT><STRONG><A NAME="item_noproduct">noproduct (pages/noproduct.html)</A></STRONG><DD>

This page is displayed if the 
<FONT SIZE=-1>URL</FONT> from the browser specifies the ordering of a
product code which is not in the products file.

<P><DT><STRONG><A NAME="item_order">order (pages/order.html)</A></STRONG><DD>

This page is displayed when the customer orders an item. It can contain any
or all of the customer-entered values, but is commonly used as a status
display (or ``shopping basket''). If frames are in use, the special order
page can be overridden with the one configured with the directive
<EM>FrameOrderPage</EM>.

<P><DT><STRONG><A NAME="item_search">search (pages/search.html)</A></STRONG><DD>

Contains the default output page for the search engine results. Also
required is an input page, which can be the same as search.html or an
additional page.

<P><DT><STRONG><A NAME="item_violation">violation (pages/violation.html)</A></STRONG><DD>

Displayed if a security violation is noted, such as an attempt to submit a
credit card number on a non-secured form when in ExtraSecure mode.

<P></DL>
<P>
<HR>


code: 10.00
section: MINIVEND_TAG_REFERENCE
type: overview
title: MINIVEND TAG REFERENCE

<A NAME="MINIVEND_TAG_REFERENCE">MINIVEND TAG REFERENCE</A></H1>
<P>
To build complex order forms and reports, MiniVend has a complete tag
language with over 80 different functions. It allows you access to and
control over any of an unlimited number of database tables, multiple
shopping carts, user name/address information, discount, tax, and shipping
information, search of files and databases, and much more.

<P>
There is conditional capability with the <CODE>[if ...]</CODE> text <CODE>[else]</CODE> else-text
<CODE>[/else][/if]</CODE> construct. It allows for testing for a condition within the MiniVend session, and if true, inserting text and/or 
<FONT SIZE=-1>HTML.</FONT> If the condition is not true, no text (or the optional
 <CODE>[else]</CODE> text) will be inserted. <CODE>[and ...]</CODE>,
<CODE>[or ...]</CODE> and <CODE>[elsif ...]</CODE> are also supported.

<P>
Most of the tests use Perl code, but MiniVend uses the Safe.pm module with
its default restrictions to help ensure that improper code will not crash
the server or modify the wrong data.

<P>
Perl can also be embedded with in the page, and if given the proper
permission by the system administrator, can call upon resources from other
computers and networks.

<P>
<HR>


code: 10.02
section: FORMS_AND_MINIVEND
type: item
title: Special Form Fields

<A NAME="Special_Form_Fields">Special Form Fields</A></H2>
<P>
MiniVend treats some form fields specially, to link to the search engine
and provide more control over user presentation. It has a number of
predefined variables, most of whose names are prefixed with
<CODE>mv_</CODE> to prevent name clashes. It also uses a few variables which are postfixed
with integer digits -- those are used to provide control in its iterating
lists.

<P>
These special fields all begin with <CODE>mv_</CODE>, and include:

<P>

<FONT SIZE=-1>(O</FONT> = order, 
<FONT SIZE=-1>S</FONT> = search, 
<FONT SIZE=-1>C</FONT> = control, 
<FONT SIZE=-1>A</FONT> = all, 
<FONT SIZE=-1>X</FONT> in scratch space)


<P>
<PRE> Name               scan Type  Description
</PRE>
<P>
<PRE> mv_all_chars         ac  S   Turns on punctuation matching
 mv_arg[0-9]+             A   Parameters for mv_subroutine (mv_arg0,mv_arg1,...)
 mv_base_directory    bd  S   Sets base directory for search file names
 mv_begin_string      bs  S   Pattern must match beginning of field
 mv_case              cs  S   Turns on case sensitivity
 mv_cartname              O   Sets the shopping cart name
 mv_cache_params          S   Determines caching of searches
 mv_change_frame          A   Any form, changes frame target of form output
 mv_check                 A   Any form, sets multiple user variables after update
 mv_checkout              O   Sets the checkout page
 mv_click                 A   Any form, sets multiple form variables before update
 mv_click                 XA  Default mv_click routine, click is mv_click_arg
 mv_click &lt;name&gt;          XA  Routine for a click &lt;name&gt;, sends click as arg
 mv_click_arg             XA  Argument name in scratch space
 mv_coordinate        co  S   Enables field/spec matching coordination
 mv_column_op         op  S   Operation for coordinated search
 mv_credit_card*          O   Discussed in order security (some are read-only)
 mv_delay_page        dp  S   Delay search until after inital page display
 mv_dict_end          de  S   Upper bound for binary search
 mv_dict_fold         df  S   Non-case sensitive binary search
 mv_dict_limit        di  S   Sets upper bound based on character position
 mv_dict_look         dl  S   Search specification for binary search
 mv_dict_order        do  S   Sets dictionary order mode
 mv_doit                  A   Common to all forms, sets default action
 mv_email                 O   Reply-to address for orders
 mv_errorpage             O   Sets error page if order check fails
 mv_exact_match       em  S   Sets word-matching mode
 mv_failpage              O,S Sets page to display on failed order check/search
 mv_field_names       fn  S   Sets field names for search, starting at 1
 mv_first_match       fm  S   Start displaying search at specified match
 mv_head_skip         hs  S   Sets skipping of header line(s) in index
 mv_index_delim       id  S   Delimter for search fields (TAB default)
 mv_matchlimit        ml  S   Sets match page size
 mv_max_matches       mm  S   Sets maximum match return (only for Glimpse)
 mv_min_string        ms  S   Sets minimum search spec size
 mv_negate            ne  S   Records NOT matching will be found
 mv_nextpage              A   Sets next page user will go to after submission
 mv_numeric           nu  S   Comparision numeric in coordinated search
 mv_order_group           O   Allows grouping of master item/sub item
 mv_order_item            O   Causes the order of an item
 mv_order_number          O   Order number of the last order (read-only)
 mv_order_quantity        O   Sets the quantity of an ordered item
 mv_order_profile         O   Selects the order check profile 
 mv_order_receipt         O   Sets the receipt displayed
 mv_order_report          O   Sets the order report sent
 mv_order_subject         O   Sets the subject line of order email
 mv_orderpage             O   Sets the page to display on refresh
 mv_orsearch          os  S   Selects AND/OR of search words
 mv_profile           mp  S   Selects search profile
 mv_range_alpha       rg  S   Sets alphanumeric range searching
 mv_range_look        rl  S   Sets the field to do a range check on
 mv_range_max         rx  S   Upper bound of range check
 mv_range_min         rm  S   Lower bound of range check
 mv_record_delim      dr  S   Search index record delimiter
 mv_return_all        ra  S   Return all lines found (subject to range search)
 mv_return_delim      rd  S   Return record delimiter
 mv_return_fields     rf  S   Fields to return on a search
 mv_return_file_name  rn  S   Set return of file name for searches
 mv_return_spec       rs  S   Return the search string as the only result
 mv_save_session          C   Set to non-zero to prevent expiration of user session
 mv_search_field      sf  S   Sets the fields to be searched
 mv_search_file       fi  S   Sets the file(s) to be searched
 mv_search_line_return lr S   Each line is a return code (loop search)
 mv_search_match_count    S   Returns the number of matches found (read-only)
 mv_search_over_msg       S   Returns string indicating search overflow (read-only)
 mv_search_page       sp  S   Sets the page for search display
 mv_searchspec        se  S   Search specification
 mv_searchtype        st  S   Sets search type (text, glimpse, db or sql)
 mv_separate_items        O   Sets separate order lines (one per item ordered)
 mv_shipmode              O   Sets shipping mode for custom shipping
 mv_sort_command      tc  S   Sets the command to use for sorting searches
 mv_sort_crippled         S   Sets crippled sort mode
 mv_sort_field        tf  S   Field(s) to sort on
 mv_sort_option       to  S   Options for sort
 mv_spelling_errors   er  S   Number of spelling errors for Glimpse
 mv_substring_match   su  S   Turns off word-matching mode
 mv_subroutine            A   Subroutine to processing based on form 
 mv_successpage           O   Page to display on successful order check
 mv_todo                  A   Common to all forms, sets form action
 mv_todo.map              A   Contains form imagemap
 mv_todo.checkout.x       O   Causes checkout action on click of image
 mv_todo.return.x         O   Causes return action on click of image
 mv_todo.submit.x         O   Causes submit action on click of image
 mv_todo.x                A   Set by form imagemap
 mv_todo.y                A   Set by form imagemap
 mv_unique            un  S   Return unique search results only
 mv_value             va  S   Sets value on one-click search (va=var=value)
</PRE>
<P>
<HR>


code: 10.03
section: FORMS_AND_MINIVEND
type: item
title: Form Actions

<A NAME="Form_Actions">Form Actions</A></H2>
<P>
Any MiniVend form can be used for any number of actions. The actions are
mapped by the <EM>ActionMap</EM> directive in the catalog configuration file, and are selected on the form
with either the <EM>mv_todo</EM> or <EM>mv_doit</EM>
variables.

<P>
Mapping of actions in the ActionMap directive means that the <EM>value</EM> of the submit button is scanned to determine the action. To map the string
``Place Order'' to the action submit, you would put in the <EM>catalog.cfg</EM> file:

<P>
<PRE>    ActionMap    submit place order
</PRE>
<P>
And on the form you would make a submit button:

<P>
<PRE>    &lt;INPUT TYPE=&quot;submit&quot; NAME=&quot;mv_todo&quot; VALUE=&quot;Place Order&quot;&gt;
</PRE>
<P>
When the button is clicked by the user, the <EM>submit</EM> action will be performed.

<P>
To set a default action for a form, set the variable <A HREF="#item_mv_doit">mv_doit</A> as a hidden variable:

<P>
<PRE>    &lt;INPUT TYPE=&quot;hidden&quot; NAME=&quot;mv_doit&quot; VALUE=&quot;refresh&quot;&gt;
</PRE>
<P>
When any other submit button (for a meaningless variable, the MiniVend
demos use <CODE>mv_submit</CODE>) is pressed, the <EM>mv_todo</EM> value will not be found, so the <EM>refresh</EM> action defined in <EM>mv_doit</EM> will be used.

<P>
The defined actions are:

<DL>
<DT><STRONG><A NAME="item_cancel">cancel</A></STRONG><DD>

All user information (with the exception of the frames and secure variable
settings) is erased, and the shopping cart is emptied. The user is then
mv_nextpage or mv_orderpage.

<P><DT><STRONG>checkout</STRONG><DD>

The shopping cart and user variables are updated, and the user is sent to
the page defined in the variable <A HREF="#item_mv_checkout">mv_checkout</A> or the CheckoutPage directive.

<P><DT><STRONG><A NAME="item_control">control</A></STRONG><DD>

The user help, frames, security, and color/background information is
examined and settings changed if appropriate. The shopping cart and user
variables are also updated.

<P><DT><STRONG><A NAME="item_refresh">refresh</A></STRONG><DD>

Simply updates the user variables and returns to the page defined in
mv_orderpage.

<P><DT><STRONG><A NAME="item_return">return</A></STRONG><DD>

Updates the user variables and returns to the page defined in mv_nextpage,
or the user's last non-order/non-search page. This is difficult to use, for
it is hard to predict what that page will be. Setting mv_nextpage with the
value of a scratch variable works well.

<P><DT><STRONG>search</STRONG><DD>

The shopping cart and user variables are updated, then the form variables
are interpreted and the search specification contained therein is
dispatched to the search engine -- results are returned on the defined
search page (set by <EM>mv_search_page</EM> or the search page directives).

<P><DT><STRONG><A NAME="item_submit">submit</A></STRONG><DD>

Submit the form for order processing. If no order profile is defined with
the <A HREF="#item_mv_order_profile">mv_order_profile</A> variable, the order will be checked to see if the current cart contains any
items and be checked against the fields defined in the <EM>RequiredFields</EM> directive. Assuming those checks pass, the order will be submitted.

<P>
If there is an order profile defined, the form will be checked against the
definition in the order profile and submitted if the pragma
<CODE>&amp;final</CODE> is set to <STRONG>yes</STRONG>. If <CODE>&amp;final</CODE> is set to <STRONG>no</STRONG> (the default), and the check succeeds, the user will be routed to the
MiniVend page defined in mv_successpage, mv_nextpage, or mv_orderpage.
Finally, if the check fails, the user will be routed to mv_failpage,
mv_nextpage, or mv_orderpage in that order.

<P></DL>
<P>
<HR>


code: 10.04
section: FORMS_AND_MINIVEND
type: item
title: One-click Multiple Variables

<A NAME="One_click_Multiple_Variables">One-click Multiple Variables</A></H2>
<P>
MiniVend can set multiple variables with a single button or form control.
You first define the variable set (or profile, as in search and order
profiles) inside a scratch variable:

<P>
<PRE>  [set Search by Category]
  mv_search_field=category
  mv_search_file=categories
  mv_todo=search
  [/set]
</PRE>
<P>
The special variable <CODE>mv_click</CODE> sets variables just as if they were put in on the form. It is controlled by
a single button, as in:

<P>
<PRE>    &lt;INPUT TYPE=&quot;submit&quot; NAME=&quot;mv_click&quot; VALUE=&quot;Search by Category&quot;&gt;
</PRE>
<P>
When the user clicks the submit button, all three variables will take on
the values defined in the ``Search by Category'' scratch variable. You can
set the scratch variable on the same form as the button is on -- in fact
that is recommended for clarity.

<P>
The variable will not be carried from form to form, it must be set on the
form being submitted.

<P>
The special variable <CODE>mv_check</CODE> sets variables for the form actions
<EM>checkout, control, refresh, return, search,</EM> and <EM>submit</EM>. This function operates after all of the values are set from the form,
including the ones set by <CODE>mv_click</CODE>, and can be used to condition input to search routines or orders.

<P>
The variable sets can contain and be generated by most MiniVend tags -- the
profile is interpolated for MiniVend tags before being used. Careful of
interpolation order, and don't use the <CODE>[post]</CODE> tag -- it will not work. Embedded Perl <STRONG>will</STRONG> work, and is recommended for most conditional operations within the
profile.

<P>
Any setting of variables already containing a value will overwrite the
variable, so to build sets of fields (as in mv_search_field and
mv_return_fields) you must use comma separation or place the null character
with a <CODE>&amp;#0;</CODE> literal.

<P>
Here is a small example which will set the value of <A HREF="#item_mv_nextpage">mv_nextpage</A> to route the user to a special page if their search inputs are invalid:

<P>
<PRE>    &lt;FORM ...
    &lt;INPUT TYPE=hidden NAME=mv_check VALUE=&quot;Invalid Input&quot;&gt;
    ...
    &lt;/FORM&gt;
</PRE>
<P>
<PRE>    [set Invalid Input]
    [perl cgi]
    my $type        = $Safe-&gt;{cgi}-&gt;{mv_searchtype};
    my $spell_check = $Safe-&gt;{cgi}-&gt;{mv_spelling_errors};
    my $out = '';
    if($spell_check and $type eq 'text') {
        $out .= &quot;mv_todo=return\n&quot;;
        $out .= &quot;mv_nextpage=special/cannot_spell_check\n&quot;;
    }
    return $out;
    [/perl]
    [/set]
</PRE>
<DL>
<DT><STRONG><A NAME="item_mv_subroutine">mv_subroutine</A></STRONG><DD>

The special variable mv_subroutine defines a named subroutine that will be
called if defined on the current form. (This variable can have been set by
mv_click.)

<P>
It takes arguments based on the special form variables mv_arg<EM>N</EM>, where
<EM>N</EM> is an integer that corresponds to the argument number (starting at zero).
Arguments can be of four types:

<P><DT><STRONG><A NAME="item_identifier">identifier</A></STRONG><DD>

Identifies a form variable (on the current form) the value of which will be
supplied as that argument.

<P><DT><STRONG><A NAME="item_HASH">HASH(identifier)</A></STRONG><DD>

Identifies a variable that will be parsed as a series of key-value pairs
and supplied as a hash *reference*.

<P><DT><STRONG><A NAME="item_ARRAY">ARRAY(identifier)</A></STRONG><DD>

Identifies a variable that will be parsed as a series of values and
supplied as an array *reference*.

<P><DT><STRONG><A NAME="item_LITERAL">LITERAL(string)</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> string that will be passed unchanged.

<P><DT><STRONG><A NAME="item_CODE">CODE(routine)</A></STRONG><DD>

Identifies a named Perl subroutine that will be called to produce the argument. The arguments are a null-separated list placed in a variable of the same name, which will be parsed as above for 
<FONT SIZE=-1>HASH,</FONT> 
<FONT SIZE=-1>ARRAY,</FONT> 
<FONT SIZE=-1>LITERAL,</FONT> identifier, and 
<FONT SIZE=-1>CODE</FONT> references. The return value (hash reference, scalar, etc.) depends on the subroutine. This is recursive.


<P><DT><STRONG><A NAME="item_SAFE">SAFE(list)</A></STRONG><DD>

Identifies additional arguments passed to the subroutine parser, as in <CODE>[perl sub values]</CODE>. It will not be placed in the argument list, so you should use mv_arg9999
or some such to pass it from the original form. Never necessary or
desirable when calling a GlobalSub.

<P></DL>
<P>
The return value for the subroutine is available in the fixed session
variable <EM>return_value</EM>, accessible as <CODE>[data session return_value]</CODE>.

<P>
An example would be a password-protected message. Here is a form:

<P>
<PRE>  &lt;FORM METHOD=POST ACTION=&quot;[process-target]&quot;&gt;
  &lt;INPUT TYPE=hidden NAME=mv_subroutine VALUE=disclose_secret&gt;
  &lt;INPUT TYPE=hidden NAME=mv_arg0     VALUE=message&gt;
  &lt;INPUT TYPE=hidden NAME=mv_arg1     VALUE=password&gt;
  &lt;INPUT TYPE=hidden NAME=mv_doit     VALUE=return&gt;
  &lt;INPUT TYPE=hidden NAME=mv_nextpage VALUE=secret&gt;
  Select
  &lt;SELECT NAME=message&gt;
      &lt;OPTION VALUE=&quot;secret&quot;&gt; Secret
      &lt;OPTION VALUE=&quot;top_secret&quot;&gt; Top Secret
  &lt;/SELECT&gt;
  Password &lt;INPUT TYPE=password NAME=password VALUE=&quot;&quot;&gt;
  &lt;INPUT TYPE=submit VALUE=&quot;See a Secret&quot;&gt;
  &lt;/FORM&gt;
</PRE>
<P>
And a subroutine:

<P>
<PRE>  [set disclose_secret]
  my($message, $password) = @_;
  my $out = '';
  if($message =~ /^secret/) {
      return &quot;Password is wrong.&quot;
          unless $password eq 'foo';
      $out = &quot;Software documentation might as well be a secret sometimes.&quot;;
  }
  elsif($message =~ /top_secret/) {
      return &quot;Password is wrong.&quot;
          unless $password eq 'bar';
      $out = &quot;You can do a lot with software if you read the documentation!&quot;;
  }
  return $out || 'No message like that';
  [/set]
</PRE>
<P>
And a results page secret.html (remember, set the destination for the <EM>return</EM>
action with <A HREF="#item_mv_nextpage">mv_nextpage</A>):

<P>
<PRE>    &lt;HTML&gt;
    &lt;HEAD&gt;
    &lt;TITLE&gt;Secret?&lt;/TITLE&gt;
    &lt;/HEAD&gt;
    [body 1]
</PRE>
<P>
<PRE>    Secret: [data session return_value]
    &lt;/BODY&gt;
    &lt;/HTML&gt;
</PRE>
<P>
<HR>


code: 10.05
section: FORMS_AND_MINIVEND
type: item
title: Checks and Selections

<A NAME="Checks_and_Selections">Checks and Selections</A></H2>
<P>
You can provide a ``memory'' for drop-down menus, radio buttons, and
checkboxes with the <CODE>[checked]</CODE> and <CODE>[selected]</CODE> tags.

<DL>
<DT><STRONG><A NAME="item__checked">[checked var_name value]</A></STRONG><DD>

named attributes: [checked name=``var_name'' value=``value'' multiple=0|1
default=0|1]

<P>
This will output 
<FONT SIZE=-1>CHECKED</FONT> if the variable <CODE>var_name</CODE> is equal to
<A HREF="#item_value">value</A>. Not case sensitive. 

<P>
As of 3.11: If the <CODE>multiple</CODE> attribute is defined and set to a non-zero value (1 is implicit) then if the value matches on a word/non-word boundary it will be 
<FONT SIZE=-1>CHECKED.</FONT> If the
 <CODE>default</CODE> attribute is set to a non-zero value, then the box will be checked if the
variable <CODE>var_name</CODE>
is empty or zero.

<P><DT><STRONG><A NAME="item__selected">[selected var_name value MULTIPLE*]</A></STRONG><DD>

named attributes: <CODE>[selected name=&quot;var_name&quot; value=&quot;value&quot; multiple=&quot;yes&quot;]</CODE>



<P>
This will output 
<FONT SIZE=-1>SELECTED</FONT> if the variable <CODE>var_name</CODE> is equal to
<A HREF="#item_value">value</A>. If the optional 
<FONT SIZE=-1>MULTIPLE</FONT> argument is present, it will look for any of
a variety of values. Not case sensitive.

<P>
Here is a drop-down menu that remembers an item-modifier color selection:

<P>
<PRE>    &lt;SELECT NAME=&quot;color&quot;&gt;
    &lt;OPTION [selected color blue]&gt; Blue
    &lt;OPTION [selected color green]&gt; Green
    &lt;OPTION [selected color red]&gt; Red
    &lt;/SELECT&gt;
</PRE>
<P>
Here is the same thing, but for a shopping-basket color selection

<P>
<PRE>    &lt;SELECT NAME=&quot;[modifier-name color]&quot;&gt;
    &lt;OPTION [selected [modifier-name color] blue]&gt; Blue
    &lt;OPTION [selected [modifier-name color] green]&gt; Green
    &lt;OPTION [selected [modifier-name color] red]&gt; Red
    &lt;/SELECT&gt;
</PRE>
<P></DL>
<P>
<HR>


code: 10.06
section: FORMS_AND_MINIVEND
type: item
title: Integrated Image Maps

<A NAME="Integrated_Image_Maps">Integrated Image Maps</A></H2>
<P>
Imagemaps can also be defined on forms, with the special form variable
<CODE>mv_todo.map</CODE>. 
<FONT SIZE=-1>A</FONT> series of map actions can be defined -- the action
specified in the <EM>default</EM> entry will be applied if none of the other coordinates match. The image is specified with a standard 
<FONT SIZE=-1>HTML</FONT> 2.0 form field of type
 <EM>IMAGE</EM>. Here is an example:

<P>
<PRE> &lt;INPUT TYPE=&quot;HIDDEN&quot; NAME=&quot;mv_todo.map&quot; VALUE=&quot;rect submit 0,0 100,20&quot;&gt;
 &lt;INPUT TYPE=&quot;HIDDEN&quot; NAME=&quot;mv_todo.map&quot; VALUE=&quot;rect cancel 290,2 342,18&quot;&gt;
 &lt;INPUT TYPE=&quot;HIDDEN&quot; NAME=&quot;mv_todo.map&quot; VALUE=&quot;default refresh&quot;&gt;
 &lt;INPUT TYPE=&quot;IMAGE&quot; NAME=&quot;mv_todo&quot; SRC=&quot;url_of_image&quot;&gt;
</PRE>
<P>
All of the actions will be combined together into one image map with NCSA-style functionality -- see the 
<FONT SIZE=-1>NCSA</FONT> imagemap documentation for details -- except that MiniVend form actions are defined instead of URLs. The standard actions are:


<P>
<PRE> submit   Submit order
 refresh  Refresh order page (update quantities, etc.)
 cancel   Cancel order and wipe credit card numbers
 return   Go to previous page (or page defined in mv_nextpage variable)
 control  Control help, colors, etc.
 search   Search for an item in the catalog
</PRE>
<P>
<HR>


code: 10.07
section: FORMS_AND_MINIVEND
type: item
title: Setting Form Security

<A NAME="Setting_Form_Security">Setting Form Security</A></H2>
<P>
You can ensure that a form will be submitted securely (to the base 
<FONT SIZE=-1>URL</FONT> in the SecureURL directive, that is) by specifying
your form input to be ACTION=``[process-target frame secure]''. If you are
not using frames, just specify the special frame ``_self'' or ``none''.

<P>
To submit a form to the regular non-secure server, just omit the
<CODE>secure</CODE> modifier.

<P>
<HR>


code: 10.08
section: FORMS_AND_MINIVEND
type: item
title: Stacking Variables on the Form

<A NAME="Stacking_Variables_on_the_Form">Stacking Variables on the Form</A></H2>
<P>
Many MiniVend variables can be ``stacked'', meaning they can have multiple
values for the same variable name. As an example -- to allow the user to
order multiple items with one click, you can set up a form like this:

<P>
<PRE> &lt;FORM METHOD=POST ACTION=&quot;[process-order]&quot;&gt;
 &lt;input type=checkbox name=&quot;mv_order_item&quot; value=&quot;M3243&quot;&gt; Item M3243
 &lt;input type=checkbox name=&quot;mv_order_item&quot; value=&quot;M3244&quot;&gt; Item M3244
 &lt;input type=checkbox name=&quot;mv_order_item&quot; value=&quot;M3245&quot;&gt; Item M3245
 &lt;input type=hidden name=&quot;mv_doit&quot; value=&quot;refresh&quot;&gt;
 &lt;input type=submit name=&quot;mv_junk&quot; value=&quot;Order Checked Items&quot;&gt;
 &lt;/FORM&gt;
</PRE>
<P>
The stackable <CODE>mv_order_item</CODE> variable with be decoded with multiple values, causing the order of any
items that are checked.

<P>
To place a ``delete'' checkbox on your shopping basket display:

<P>
<PRE> &lt;FORM METHOD=POST ACTION=&quot;[process-order]&quot;&gt;
 [item-list]
   &lt;input type=checkbox name=&quot;[quantity-name]&quot; value=&quot;0&quot;&gt; Delete
   Part number: [item-code]
   Quantity: &lt;input type=text name=&quot;[quantity-name]&quot; value=&quot;[item-quantity]&quot;&gt;
   Description: [item-description]
 [/item-list]
 &lt;input type=hidden name=&quot;mv_doit&quot; value=&quot;refresh&quot;&gt;
 &lt;input type=submit name=&quot;mv_junk&quot; value=&quot;Order Checked Items&quot;&gt;
 &lt;/FORM&gt;
</PRE>
<P>
In this case, <STRONG>first</STRONG> instance of the variable name set by <CODE>[quantity-name]</CODE>
will be used as the order quantity, deleting the item from the form.

<P>
Of course, not all variables are stackable. Check the documentation for
which ones can be stacked -- or experiment on your own.

<P>
<HR>


code: 10.08
section: FORMS_AND_MINIVEND
type: item
title: Updating MiniVend database tables with a form

<A NAME="Updating_MiniVend_database_table">Updating MiniVend database tables with a form</A></H2>
<P>
Any MiniVend database can be updated with a form using the following
method.

<P>

<FONT SIZE=-1>NOTE:</FONT> All operations are performed on the <STRONG>database</STRONG>, not the 
<FONT SIZE=-1>ASCII</FONT> source file. You will have to perform a <CODE>[tag export table_name][/tag]</CODE> operation if you want the 
<FONT SIZE=-1>ASCII</FONT> source file to reflect the results of the
update.

<P>
You of course may insert or update records in any <EM>SQL</EM> database with the
<CODE>[sql set]</CODE> tag, but you may also do form-based updates or inserts.

<P>
In an update form, special MiniVend variables are used to select the
database parameters:

<DL>
<DT><STRONG><A NAME="item_mv_data_table">mv_data_table</A></STRONG><DD>

The table to update.

<P><DT><STRONG><A NAME="item_mv_data_key">mv_data_key</A></STRONG><DD>

The field that is the primary key in the table. Must match the existing
database definition.

<P><DT><STRONG><A NAME="item_mv_data_function">mv_data_function</A></STRONG><DD>


<FONT SIZE=-1>UPDATE,</FONT> 
<FONT SIZE=-1>INSERT</FONT> or 
<FONT SIZE=-1>DELETE.</FONT> The variable
 <A HREF="#item_mv_data_verify">mv_data_verify</A> must be set true on the form for a 
<FONT SIZE=-1>DELETE</FONT> to occur.

<P><DT><STRONG><A NAME="item_mv_data_verify">mv_data_verify</A></STRONG><DD>

Confirms a 
<FONT SIZE=-1>DELETE.</FONT>

<P><DT><STRONG><A NAME="item_mv_data_fields">mv_data_fields</A></STRONG><DD>

Fields from the form which should be inserted or updated. Must be existing
columns in the table in question.

<P></DL>
<P>
The MiniVend action <STRONG>set</STRONG> causes the update. Here is an pair of example forms. One is used to set the
key to access the record (careful with the name, this one goes into the
user session values). The second actually performs the update. It uses the <CODE>[loop]</CODE> tag with only one value to place default/existing values in the form based
on the input from the first form:

<P>
<PRE>    &lt;FORM METHOD=POST ACTION=&quot;[process-target]&quot;&gt;
    &lt;INPUT TYPE=HIDDEN name=&quot;mv_doit&quot; value=&quot;return&quot;&gt;
    &lt;INPUT TYPE=HIDDEN name=&quot;mv_nextpage&quot; value=&quot;update_proj&quot;&gt;
    Sales Order Number &lt;INPUT TYPE=TEXT SIZE=8
                            NAME=&quot;update_code&quot;
                            VALUE=&quot;[value update_code]&quot;&gt;
    &lt;INPUT TYPE=SUBMIT name=&quot;mv_submit&quot;  Value=&quot;Select&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
<PRE>    [new]
    &lt;FORM METHOD=POST ACTION=&quot;[process-target]&quot;&gt;
    &lt;INPUT TYPE=HIDDEN NAME=&quot;mv_data_table&quot;    VALUE=&quot;ship_status&quot;&gt;
    &lt;INPUT TYPE=HIDDEN NAME=&quot;mv_data_key&quot;      VALUE=&quot;code&quot;&gt;
    &lt;INPUT TYPE=HIDDEN NAME=&quot;mv_data_function&quot; VALUE=&quot;update&quot;&gt;
    &lt;INPUT TYPE=HIDDEN NAME=&quot;mv_nextpage&quot;      VALUE=&quot;updated&quot;&gt;
    &lt;INPUT TYPE=HIDDEN NAME=&quot;mv_data_fields&quot;
                VALUE=&quot;code,custid,comments,status&quot;&gt;
    &lt;PRE&gt;
</PRE>
<P>
<PRE>    [loop arg=&quot;[value update_code]&quot;]
    Sales Order &lt;INPUT TYPE=TEXT NAME=&quot;code    SIZE=10 VALUE=&quot;[loop-code]&quot;&gt;
   Customer No. &lt;INPUT TYPE=TEXT NAME=&quot;custid&quot; SIZE=30
                    VALUE=&quot;[loop-field custid]&quot;&gt;
       Comments &lt;INPUT TYPE=TEXT NAME=&quot;comments&quot; 
                    SIZE=30 VALUE=&quot;[loop-field comments]&quot;&gt;
         Status &lt;INPUT TYPE=TEXT NAME=&quot;status&quot;
                    SIZE=10 VALUE=&quot;[loop-field status]&quot;&gt;
    [/loop]
    &lt;/PRE&gt;
</PRE>
<P>
<PRE>        &lt;INPUT TYPE=hidden NAME=&quot;mv_todo&quot; VALUE=&quot;set&quot;&gt;
        &lt;INPUT TYPE=submit VALUE=&quot;Update table&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
The variables in the form do <STRONG>not</STRONG> update the user's session values, so they can correspond to database field
names without fear of corrupting the user session.

<P>
<HR>


code: 10.09
section: FORMS_AND_MINIVEND
type: item
title: Extended Value Access and File Upload

<A NAME="Extended_Value_Access_and_File_U">Extended Value Access and File Upload</A></H2>
<P>
MiniVend as of 3.12 has a facility for greater control over the display of
form variables; it also can parse <CODE>multipart/form-data</CODE> forms for file upload. 

<P>
File upload is simple. You define a form like:

<P>
<PRE>    &lt;FORM ACTION=&quot;[process-target] METHOD=POST ENCTYPE=&quot;multipart/form-data&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_todo VALUE=&quot;return&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_nextpage VALUE=&quot;test&quot;&gt;
    &lt;INPUT TYPE=file NAME=newfile&gt;
    &lt;INPUT TYPE=hidden NAME=testvar VALUE=&quot;value0&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=testvar VALUE=&quot;value1&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=testvar VALUE=&quot;value2&quot;&gt;
    &lt;INPUT TYPE=submit VALUE=&quot;Go!&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
The [value-extended ...] tag allows access to all of these things. If you
put on the <CODE>test.html</CODE> page and use with the above form you can see how it is used:

<P>
<PRE>    &lt;PRE&gt;
    testvar element 0: [value-extended name=testvar index=0]
    testvar element 1: [value-extended name=testvar index=1]
    testvar elements:
     joined with a space:   |[value-extended name=testvar]|
     joined with a newline: |[value-extended
                                joiner=&quot;\n&quot;
                                name=testvar
                                index=&quot;*&quot;]|
     first two only:    |[value-extended
                                name=testvar
                                index=&quot;0..1&quot;]|
     first and last:    |[value-extended
                                name=testvar
                                index=&quot;0,2&quot;]|
    Uploaded file name: [value-extended name=newfile]
    Is newfile a file? [value-extended name=newfile yes=Yes no=No test=isfile]
 
    Write the file. [value-extended name=newfile outfile=junk.upload]
    Write again with
     indication: [value-extended name=newfile
                                outfile=junk.upload
                                yes=&quot;Written.&quot;]
                                no=FAILED]
 
    And the file contents:
    [value-extended name=newfile file_contents=1]
    &lt;/PRE&gt;
</PRE>
<P>
The syntax for <CODE>[value-extended ...]</CODE> is:

<P>
<PRE> named: [value-extended 
            name=formfield
            outfile=filename*
            ascii=1*
            yes=&quot;Yes&quot;*
            no=&quot;No&quot;*
            joiner=&quot;char|string&quot;*
            test=&quot;isfile|length|defined&quot;*
            index=&quot;N|N..N|*&quot;
            file_contents=1*
            elements=1*]
</PRE>
<P>
positional: [value-extended name]

<P>

<FONT SIZE=-1>HTML</FONT> examples:

<P>
<PRE>   No match found for &lt;PARAM MV=&quot;value-extended&quot;
                        MV.JOINER=&quot; and &quot;
                        MV.NAME=mv_searchspec&gt;
   &lt;INPUT TYPE=&quot;text&quot; NAME=&quot;mv_searchspec&quot;
        VALUE=&quot;[value-extended name=mv_searchspec index=0]&quot;&gt;
   &lt;INPUT TYPE=&quot;text&quot; NAME=&quot;mv_searchspec&quot;
        VALUE=&quot;[value-extended name=mv_searchspec index=1]&quot;&gt;
</PRE>
<P>
Expands into the current value of the customer/form input field named by
field. If there are multiple elements of that variable, it will return the
value at <A HREF="#item_index">index</A>; by default all joined together with a space.

<P>
If the variable is a file variable coming from a multipart/form-data file
upload, then the contents of that upload can be returned to the page or
optionally written to the <A HREF="#item_outfile">outfile</A>.

<DL>
<DT><STRONG><A NAME="item_name">name</A></STRONG><DD>

The form variable 
<FONT SIZE=-1>NAME.</FONT> If no other parameters are present, then the
value of the variable will be returned. If there are multiple elements,
then by default they will all be returned joined by a space. If <A HREF="#item_joiner">joiner</A>
is present, then they will be joined by its value.

<P>
In the special case of a file upload, the value returned is the name of the
file as passed for upload.

<P><DT><STRONG><A NAME="item_joiner">joiner</A></STRONG><DD>

The character or string that will join the elements of the array. Will
accept string literals such as ``\n'' or ``\r''.

<P><DT><STRONG><A NAME="item_test">test</A></STRONG><DD>

Three tests -- <CODE>isfile</CODE> returns true if the variable is a file upload.
<CODE>length</CODE> returns the length. <CODE>defined</CODE> returns whether the value has ever been set at all on a form.

<P><DT><STRONG><A NAME="item_index">index</A></STRONG><DD>

The index of the element to return if not all are wanted. This is useful
especially for pre-setting multiple search variables. If set to <CODE>*</CODE>, will return all (joined by <A HREF="#item_joiner">joiner</A>). If a range, such as <CODE>0 .. 2</CODE>, will return multiple elements.

<P><DT><STRONG><A NAME="item_file_contents">file_contents</A></STRONG><DD>

Returns the contents of a file upload if set to a non-blank, non-zero
value. If the variable is not a file, returns nothing.

<P><DT><STRONG><A NAME="item_outfile">outfile</A></STRONG><DD>

Names a file to write the contents of a file upload to. It will not accept an absolute file name; the name must be relative to the catalog directory. If you wish to write images or other files that would go to 
<FONT SIZE=-1>HTML</FONT> space, you must use the 
<FONT SIZE=-1>HTTP</FONT> server's
 <A HREF="#item_Alias">Alias</A> facilities or make a symbolic link.

<P><DT><STRONG><A NAME="item_ascii">ascii</A></STRONG><DD>

To do an auto-ASCII translation before writing the <A HREF="#item_outfile">outfile</A>, set the <A HREF="#item_ascii">ascii</A> parameter to a non-blank, non-zero value. Default is no translation.

<P><DT><STRONG><A NAME="item_yes">yes</A></STRONG><DD>

The value that will be returned if a test is true or a file is written
successfully. Defaults to <CODE>1</CODE> for tests and the empty string for uploads.

<P><DT><STRONG><A NAME="item_no">no</A></STRONG><DD>

The value that will be returned if a test is false or a file write fails.
Defaults to the empty string.

<P></DL>
<P>
<HR>


code: 11.00
section: FORMS_AND_MINIVEND
type: overview
title: FORMS AND MINIVEND

<A NAME="FORMS_AND_MINIVEND">FORMS AND MINIVEND</A></H1>
<P>
MiniVend uses 
<FONT SIZE=-1>HTML</FONT> forms for order, search, and control operations.
Order operations possibly include ordering an item, selecting item size or
other attributes, and reading user information for payment and shipment.
Search operations may also be triggered by a form. In addition, the user
can control certain aspects of the session, such as order security, frames
presentation, and background display via a control form.

<P>
MiniVend as of 3.12 supports file upload with the <CODE>multipart/form-data</CODE>
type. The file is placed in memory and discarded if not accessed with the <CODE>[value-extended name=filevar file_contents=1]</CODE> tag or written with <CODE>[value-extended name=filevar outfile=your_file_name]</CODE>. See
<EM>Extended Value Access and File Upload</EM>.

<P>
<HR>


code: 11.02
section: THE_SEARCH_ENGINE
type: item
title: The Search Form

<A NAME="The_Search_Form">The Search Form</A></H2>
<P>

<FONT SIZE=-1>A</FONT> number of variables can be set on search forms to
determine which search will be used, what fields in the database it will
search, and what search behavior will be.

<P>
Here is a simple search form:

<P>
<PRE>  &lt;FORM ACTION=&quot;[process-search]&quot; METHOD=POST&gt;
  &lt;INPUT TYPE=&quot;text&quot; SIZE=&quot;30&quot; NAME=&quot;mv_searchspec&quot;&gt;
  &lt;INPUT TYPE=&quot;submit&quot; NAME=&quot;mv_todo&quot; VALUE=&quot;Search&quot;&gt;
  &lt;/FORM&gt;
</PRE>
<P>
When the ``Search'' submit button is pressed (or &lt;
<FONT SIZE=-1>ENTER&gt;</FONT> is pressed) MiniVend will search the <CODE>products.asc</CODE> file for the string entered into the text field <A HREF="#item_mv_searchspec">mv_searchspec</A>, and return the product code pertaining to that line.

<P>
The same search for a fixed string, say ``shirt'', could be performed with
the use of a hot link, using the special <EM>scan</EM> 
<FONT SIZE=-1>URL:</FONT>

<P>
<PRE>  [page scan se=shirt]See our shirt collection![/page]
</PRE>
<P>
The default is to search every field on the line. If you only wished to
match on the string shirt in the product database field ``description'',
you could modify the search:

<P>
<PRE>  &lt;INPUT TYPE=&quot;hidden&quot; NAME=&quot;mv_search_field&quot; VALUE=&quot;description&quot;&gt;
</PRE>
<P>
In the hot-linked 
<FONT SIZE=-1>URL</FONT> search:

<P>
<PRE>  [page scan se=shirt/sf=description]See our shirt collection![/page]
</PRE>
<P>
If you want to let the user decide on the search parameters, you can use
checkboxes or radiobox fields to set the fields:

<P>
<PRE>    Search by author
       &lt;INPUT TYPE=&quot;checkbox&quot; NAME=&quot;mv_search_field&quot; VALUE=&quot;author&quot;&gt;
    Search by title
        &lt;INPUT TYPE=&quot;checkbox&quot; NAME=&quot;mv_search_field&quot; VALUE=&quot;title&quot;&gt;
</PRE>
<P>
Fields can be stacked -- if more than one is checked, all checked fields
will be searched. (This doesn't work for Glimpse in the return_file_name
mode, though).

<P>
<HR>


code: 11.03
section: THE_SEARCH_ENGINE
type: item
title: Glimpse

<A NAME="Glimpse">Glimpse</A></H2>
<P>
<STRONG>To use the Glimpse search</STRONG>, you must build the Glimpse index based on files in your <EM>ProductDir</EM>, or wherever the files to be searched will be located. If you installed
MiniVend in the default
<CODE>/usr/local/lib/minivend</CODE>, the command line to build the index for the products file would be:

<P>
<PRE>    glimpseindex -b -H /usr/local/lib/minivend/products products.asc
</PRE>
<P>
There are several ways to improve search speed for large catalogs.

<P>
One method that works well for large <CODE>products.asc</CODE> files is to split the <CODE>products.asc</CODE> file into small index files (in the example, 100 lines) with the <CODE>split(1)</CODE> 
<FONT SIZE=-1>UNIX/POSIX</FONT> command, then index it with glimpse:


<P>
<PRE>    split -100 products.asc index.asc.
    glimpseindex -H /usr/local/lib/minivend/products index.asc.*
</PRE>
<P>
This will dramatically increase search speeds for large catalogs, at least
if the search term is relatively unique. If it is a common string, as you
might have in a category search, you will be better off to use the
text-based search.

<P>
If you are intending to search for numbers, add the -n option to the
Glimpse command line.

<P>

<FONT SIZE=-1>(A</FONT> large catalog is one of more than several thousand
items -- smaller ones have acceptable speed in any of the search modes.)

<P>
If the Glimpse executable is not found at MiniVend startup, the Glimpse
search will be disabled and the regular text-based search used instead.

<P>
There are several things you have to watch for while using <STRONG>glimpse</STRONG>, and a liberal dose of the Glimpse documentation is suggested. In
particular, the spelling error capability will not work in combination with
the field-specific search -- Glimpse selects the line, but MiniVend's
text-based search routines disqualify it when checking to see if the search
string is within one of the specified fields.

<P>
<HR>


code: 11.04
section: THE_SEARCH_ENGINE
type: item
title: Fast Binary Search

<A NAME="Fast_Binary_Search">Fast Binary Search</A></H2>
<P>
<STRONG>Fast binary searching</STRONG> is useful for scanning large databases for strings that match the beginning
of a line. They use the standard Perl module Search::Dict, and are enabled
through use of the <A HREF="#item_mv_dict_look">mv_dict_look</A>,
<A HREF="#item_mv_dict_end">mv_dict_end</A>, <A HREF="#item_mv_dict_limit">mv_dict_limit</A>, <A HREF="#item_mv_dict_fold">mv_dict_fold</A>, and <A HREF="#item_mv_dict_order">mv_dict_order</A>
variables.

<P>
The field to search is the first field in the file, then the product code
should be in the second field, delimited by <EM>Delimiter</EM>. You will also have to set mv_return_fields=1 to return the product code
in the search.

<P>
The search must be done on a <STRONG>dictionary-ordered</STRONG> pre-built index, which can be produced with the database 
<FONT SIZE=-1>INDEX</FONT> modifier. See 
<EM>Dictionary indexing with INDEX</EM>.

<P>
If you use the <A HREF="#item_mv_dict_look">mv_dict_look</A> parameter by itself, and the proper index file is present, MiniVend should
set the options:

<P>
<PRE>    mv_return_fields=1
    mv_dict_limit=-1
</PRE>
<P>
This will make the search behave much like the simple search described
above, except it will be <STRONG>much</STRONG> faster on large files and will match only from the <STRONG>beginning</STRONG> of the field.

<P>
<HR>


code: 11.05
section: THE_SEARCH_ENGINE
type: item
title: Coordinated and joined searching

<A NAME="Coordinated_and_joined_searching">Coordinated and joined searching</A></H2>
<P>
MiniVend will do a complete range of tests on individual columns in the
database. To use this function, set <A HREF="#item_mv_coordinate">mv_coordinate</A> to <STRONG>yes</STRONG> (co=yes in the one-click syntax).

<P>
In order to use coordinated searching, the number of <EM>search fields</EM>

<STRONG>must equal</STRONG> the number of <EM>search strings</EM>. This makes sense if you think about it a bit.

<P>
If you want to make sure that is the case, use the <CODE>mv_search_map</CODE>
variable. It allows you to map variables to others in the search
specification. For example:

<P>
<PRE>    &lt;INPUT TYPE=hidden NAME=mv_search_map VALUE=&quot;
        mv_searchspec=search1
        mv_searchspec=search2
        mv_searchspec=search3
        &quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=title&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=artist&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=category&gt;
    Artist: &lt;INPUT NAME=search1 VALUE=&quot;[value search1]&quot;&gt;
    Title:  &lt;INPUT NAME=search2 VALUE=&quot;[value search2]&quot;&gt;
    Genre:  &lt;INPUT NAME=search3 VALUE=&quot;[value search3]&quot;&gt;
</PRE>
<P>
Even if the user leaves one blank, the search will work.

<P>
Leading/trailing whitespace is stripped from all lines in the mv_search_map
variable, so you can position it as shown for convenience.

<P>
Coordinated searches may be joined with the output of another table if you
set one of the <A HREF="#item_mv_search_field">mv_search_field</A> values to a <CODE>table:column</CODE>
pair. Note that this will slow down large searches considerably unless you
have another search specification, as the database must be accessed for
every search line! If you have a search field that qualifies for a regular
expression search function, or are doing a binary search with
<A HREF="#item_mv_dict_look">mv_dict_look</A>, or are not doing an <CODE>OR</CODE> search, the penalty should not be too great as only matching lines will
cause an access to the database.

<P>
Individual field operations can then be specified with the <CODE>mv_column_op</CODE>
(or <STRONG>op</STRONG>) parameter. The operations include:

<P>
<PRE>    operation            string     numeric   equivalent
    ---------           
    equal to               eq         ==           =
    not equal              ne         !=           &lt;&gt;
    greater than           gt         &gt; 
    less than              lt         &lt; 
    less than/equal to     le         &lt;= 
    greater than/equal to  ge         &gt;= 
    regular expression     rm                       =~ , LIKE
    regular expression NOT rn                       !~
    exact match            em
</PRE>
<P>
An example:

<P>
<PRE>    [page scan
            co=yes
            sf=title
            se=Sunflowers
            op=em
            sf=artist
            se=Van Gogh
            op=rm          ] Sunflowers, Van Gogh [/page]
</PRE>
<P>
<PRE>    [page scan
            co=yes
  
            sf=title
            se=Sunflowers
            nu=0
            op=!~
  
            sf=artist
            se=Van Gogh
            op=rm    
            nu=0
</PRE>
<P>
<PRE>            sf=inventory:qty
            se=1
            op=&gt;=
            nu=1      ] Any in stock except Sunflowers, Van Gogh [/page]
</PRE>
<P>
The second search will check the stock status of the painting provided
there is an <CODE>inventory</CODE> table as in some of the MiniVend demo catalogs. If the <CODE>qty</CODE> field is greater than or equal to 1, then the product will be picked. If
out of stock, it will not be found.

<P>
It always helps to have an <CODE>rm</CODE> type included in the search. This is used to pre-screen records so that
database accesses only need be made for already-matching entries. If
accesses must be made for every record large searches can get quite slow.

<P>
<HR>


code: 11.06
section: THE_SEARCH_ENGINE
type: item
title: Specifying a text-based search with SQL-like syntax

<A NAME="Specifying_a_text_based_search_w">Specifying a text-based search with SQL-like syntax</A></H2>
<P>
If you have installed Jochen Wiedmann's <CODE>SQL::Statement</CODE> module, you can specify an 
<FONT SIZE=-1>SQL</FONT> syntax for the text-based search. (This is <STRONG>not</STRONG> the same as the the 
<FONT SIZE=-1>SQL</FONT> search, treated below separately. It would work on an 
<FONT SIZE=-1>SQL</FONT> table but only on the 
<FONT SIZE=-1>ASCII</FONT> text source file, not on the actual database.)


<P>
This syntax allows this rather nice form setup:

<P>
<PRE>    Artist: &lt;INPUT NAME=&quot;artist&quot;&gt;
    Title:  &lt;INPUT NAME=&quot;title&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=&quot;mv_sql_query&quot;
            VALUE=&quot;
                SELECT code FROM products
                WHERE artist LIKE artist
                AND    title LIKE title&quot;&gt;                             
</PRE>
<P>
If the right hand side of an expression looks like a column, i.e. is not
quoted, then the appropriate form variable is substituted. (If used in a
one-click, the corresponding <EM>scratch</EM> variable is used instead.) The assumption is reversed for the left-hand
side -- if it is a quoted string then the column name is read from the
passed values -- otherwise the column name is literal.                     

<P>
<PRE>    Search for: &lt;INPUT NAME=&quot;searchstring&quot;&gt;&lt;BR&gt;                
    Search in   &lt;INPUT TYPE=&quot;radio&quot; NAME=&quot;column&quot; VALUE=&quot;title&quot;&gt; title
        &lt;INPUT TYPE=&quot;radio&quot; NAME=&quot;column&quot; VALUE=&quot;artist&quot;&gt; artist
        &lt;INPUT TYPE=hidden NAME=&quot;mv_sql_query&quot;                            
          VALUE=&quot;SELECT code FROM products WHERE 'column' LIKE searchstring&quot;&gt;
</PRE>
<P>
Once again, this does not do a search on an 
<FONT SIZE=-1>SQL</FONT> database, but formats a corresponding text-based search. Parentheses will have no effect, and an 
<FONT SIZE=-1>OR</FONT> condition will cause all conditions to be 
<FONT SIZE=-1>OR.</FONT> The searches above would be similar to:


<P>
<PRE>    [page href=scan  
          arg=&quot;
                co=yes
                sf=artist
                op=rm
                se=[value artist]
                sf=title
                op=rm
                se=[value title]
            &quot;  ]
        Search for [value artist], [value title]
    [/page]
   
    [page href=scan  
          arg=&quot;
                co=yes
                sf=[value column]
                op=rm
                se=[value searchstring]
            &quot;  ] 
    Search for [value searchstring]
           in  [value column]
    [/page]
</PRE>
<P>
<HR>


code: 11.07
section: THE_SEARCH_ENGINE
type: item
title: Range Searching

<A NAME="Range_Searching">Range Searching</A></H2>
<P>
Range searching allows you to qualify your search returns with a field that
must be within a certain numeric or alphanumeric range. To use it, set the
mv_range_look variable to the products database field, or a column/field
number for another file. Then set the corresponding
<A HREF="#item_mv_range_min">mv_range_min</A> and <A HREF="#item_mv_range_max">mv_range_max</A> variables with a selectable field.

<P>
<PRE>    &lt;INPUT TYPE=&quot;hidden&quot; NAME=&quot;mv_range_look&quot; VALUE=&quot;price&quot;&gt;
        Search on Price
    Min &lt;SELECT NAME=&quot;mv_range_min&quot;&gt;
             &lt;OPTION value=0 SELECTED&gt; Free
             &lt;OPTION value=1000000&gt; $1,000,000
             &lt;OPTION value=10000000&gt; $10,000,000
             &lt;OPTION value=20000000&gt; $20,000,000
             &lt;OPTION value=40000000&gt; $40,000,000
        &lt;/SELECT&gt;&lt;BR&gt;
    Max &lt;SELECT NAME=&quot;mv_range_max&quot;&gt;
            &lt;OPTION value=0 SELECTED&gt; no object
            &lt;OPTION value=1000000&gt; $1,000,000
            &lt;OPTION value=10000000&gt; $10,000,000
            &lt;OPTION value=20000000&gt; $20,000,000
            &lt;OPTION value=40000000&gt; $40,000,000
        &lt;/SELECT&gt;
</PRE>
<P>
The value of 0 for mv_range_max is equivalent to infinity if doing a
numeric search. (This makes it impossible to search for a ceiling of 0 with
a negative mv_range_min, just in case you were planning on trying that.)

<P>
The fields are stackable, so you can set more than one range to check. The
order is significant, in the sense that the array of field names and
minimum/maximum values must be kept in order to achieve correspondence.

<P>
The optional <A HREF="#item_mv_range_alpha">mv_range_alpha</A> specification allows alphanumeric range matching for the corresponding
field -- if it is set, and you have stacked the fields, they must all be
set. The <A HREF="#item_mv_case">mv_case</A> field does apply if it is set -- otherwise the comparison is without regard
to case.

<P>
If you wish to do 
<FONT SIZE=-1>ONLY</FONT> a range search, you must select all lines with <CODE>mv_return_all</CODE>=yes in order to make the search operate. Range-only searches will be quite
slow for large databases, since every line must be scanned. It should be
quite usable for catalogs of less than 10,000 items in size, given a fast
machine. Using it in combination with another search technique (in the same
query) will yield faster search returns.

<P>
<HR>


code: 11.08
section: THE_SEARCH_ENGINE
type: item
title: SQL searches

<A NAME="SQL_searches">SQL searches</A></H2>
<P>
MiniVend can formulate and execute 
<FONT SIZE=-1>SQL</FONT> searches in much the same way as it does text or Glimpse searches. Because of the 
<FONT SIZE=-1>SQL</FONT> language and the limitations a common subset places on the operation, not all parameters are supported.


<P>
The following variables are in effect for 
<FONT SIZE=-1>SQL</FONT> searches:

<P>
<PRE> mv_delay_page        S   Sets the page for delayed search display
 mv_matchlimit        S   Sets match page size
 mv_numeric           S   Determines numeric status of column for ? bind
 mv_orsearch          S   Selects AND/OR of search terms
 mv_range_look        S   Sets the column to do a range check on
 mv_range_max         S   Upper bound of range check
 mv_range_min         S   Lower bound of range check
 mv_return_fields     S   Columns to return from query
 mv_search_field      S   Sets the column(s) to be searched
 mv_search_file       S   Sets the table to be searched
 mv_search_page       S   Sets the page for search display
 mv_searchspec        S   Search specification(s)
 mv_searchtype        S   Sets search type (text, glimpse, db, or sql)
 mv_sort_field        S   Column(s) to sort on
 mv_sort_option       S   Options for sort (only global reverse)
 mv_sql_query         S   SQL query text for simple query
 mv_substring_match   S   Turns off word-matching mode
</PRE>
<P>
Their two-letter abbreviations are in effect (as below), so you may easily do a one-click 
<FONT SIZE=-1>SQL</FONT> search.


<P>
If you are using 
<FONT SIZE=-1>SQL</FONT> for the products database, and the table you are searching is in the same 
<FONT SIZE=-1>SQL</FONT> database, you don't need to specify the table other than in the query. If you are not using 
<FONT SIZE=-1>SQL</FONT> for products, or it resides in a different database, then you must specify a MiniVend database identifier located in the same 
<FONT SIZE=-1>SQL</FONT> database as the table you are querying. Use the mv_search_file variable:


<P>
<PRE>   &lt;INPUT TYPE=hidden NAME=mv_search_file VALUE=&quot;inventory&quot;&gt;
</PRE>
<P>
Once you have selected the database, you may query any table that is located within the same 
<FONT SIZE=-1>SQL</FONT> data source.


<P>
There are two modes for 
<FONT SIZE=-1>SQL</FONT> search:

<DL>
<DT><STRONG><A NAME="item_Simple">Simple query substitution</A></STRONG><DD>

To do a simple query, define the variable mv_sql_query to be a valid 
<FONT SIZE=-1>SQL</FONT> query. In its simplest form:

<P>
<PRE>    &lt;FORM METHOD=POST ACTION=&quot;[process-search]&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_searchtype VALUE=&quot;sql&quot;&gt; 
    &lt;INPUT TYPE=hidden NAME=mv_sql_query
        VALUE=&quot;select code from products where category = 'Americana'&quot;&gt;
    &lt;INPUT TYPE=SUBMIT VALUE=&quot;Americana&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
When the user clicks the button, the query will be done and the results
returned using the default search return page. You may set the return page
with mv_search_page as in the other searches, but most other variables have
no effect.

<P>
Another exception is the mv_searchspec variable, which when set with either
user-entered text or by another method, will be inserted in place of a
single question mark in the query:

<P>
<PRE>    &lt;FORM METHOD=POST ACTION=&quot;[process-search]&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_searchtype VALUE=&quot;sql&quot;&gt; 
    &lt;INPUT TYPE=hidden NAME=mv_sql_query
        VALUE=&quot;select code from products where category = ? &quot;&gt;
    &lt;SELECT NAME=mv_searchspec&gt;
        &lt;OPTION&gt; Americana
        &lt;OPTION&gt; Contemporary
        &lt;OPTION&gt; Impressionists
        &lt;OPTION&gt; Renaissance
        &lt;OPTION&gt; Surrealists
    &lt;/SELECT&gt;
    &lt;INPUT TYPE=SUBMIT VALUE=&quot;Go&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
When the user selects one of the search categories, the value of
mv_searchspec will be substituted for the question mark, and quoted if the
field is not numeric in nature.

<P>
The spaces necessary in 
<FONT SIZE=-1>SQL</FONT> queries make hand generation of one-click URLs
pretty tedious. You may generate one-click searches easily using
<CODE>[tag sql] SQL [/tag]</CODE>. For example, the query

<P>
<PRE>    &lt;A HREF=&quot;[tag sql]SELECT code from products where category = 'Americana'[/tag]&quot;&gt;
        Americana
    &lt;/A&gt;
</PRE>
<P>
generates 
<FONT SIZE=-1>HTML</FONT> that starts out:

<P>
<PRE>    &lt;A HREF=&quot;<A HREF="http://your.com/cgi-bin/simple/scan/sq=SELECT%20code%20from%20...&quot">http://your.com/cgi-bin/simple/scan/sq=SELECT%20code%20from%20...&quot</A>;&gt;
       Americana
    &lt;/A&gt;
</PRE>
<P>
The actual 
<FONT SIZE=-1>URL</FONT> is a bit too long to show. The same result would
be generated by:

<P>
<PRE>    [page scan sf=category/se=Americana/st=sql]
      Americana
    [/page]
</PRE>
<P>
The first example may be more intuitive for some; it is marginally faster.

<P><DT><STRONG><A NAME="item_Complex">Complex form-based query</A></STRONG><DD>

Within the confines of the variables in use for 
<FONT SIZE=-1>SQL</FONT> searches, you may generate some pretty complex
queries. The principles are much the same as for the other searches, but
the implementation differs a bit.

<P>
For example, if you don't specify a field or fields in the table to search,
MiniVend will search all fields as is the default for the text and Glimpse
searches. This can be quite inefficient, as the resulting query looks
something like:

<P>
<PRE>    select code from products
        WHERE title  = 'Van Gogh'
        OR    artist = 'Van Gogh'
        OR    description = 'Van Gogh'
        OR    price = 'Van Gogh'
        etc.
</PRE>
<P>
You get the picture. Each field is checked in turn. Much better is to set
the mv_search_field variable to the <CODE>field(s)</CODE> you wish
searched, skipping the ones that make no sense:

<P>
<PRE>    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=artist&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=title&gt;
</PRE>
<P>
This generates a much more limited query.

<P>
If there are more mv_searchspec values than fields, then only the first
search field is used. The below query will fail, as the second and
subsequent search fields are ignored.

<P>
<PRE>    &lt;INPUT NAME=mv_searchspec VALUE=&quot;Van Gogh&quot;&gt;
    &lt;INPUT NAME=mv_searchspec VALUE=&quot;Dali&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=&quot;title&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=&quot;artist&quot;&gt;
</PRE>
<P>
If there are more mv_search_field values than mv_searchspec values, then
only the first search specification will be used:

<P>
<PRE>    &lt;INPUT NAME=mv_searchspec VALUE=&quot;Van Gogh&quot;&gt;
    &lt;INPUT NAME=mv_searchspec VALUE=&quot;Dali&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=&quot;title&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=&quot;artist&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=&quot;museum&quot;&gt;
</PRE>
<P>
The string 'Dali' will never be looked for.

<P>
If the number of search fields and search specs are the same, a coordinated 
<FONT SIZE=-1>AND</FONT> search is done, and only rows matching all search specs will be found.


<P>
The mv_range_look facility is in use for the complex form query as well,
and operates in exactly the same way.

<P>
The following search will find all Van Gogh paintings that are between $1,000,000 and $20,000,000, providing the price field is a numeric data type. It also illustrates the use of some other MiniVend variables that are usable for 
<FONT SIZE=-1>SQL</FONT> searches.


<P>
<PRE>    &lt;FORM METHOD=POST ACTION=&quot;[process-search]&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_searchtype VALUE=&quot;sql&quot;&gt; 
    &lt;INPUT NAME=mv_searchspec               VALUE=&quot;Van Gogh&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_field VALUE=&quot;artist&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_range_look   VALUE=&quot;price&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_range_min    VALUE=&quot;1000000&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_range_max    VALUE=&quot;20000000&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_return_fields VALUE=&quot;code,description&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_sort_field    VALUE=&quot;price&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_sort_option   VALUE=&quot;r&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
It will generate the query:

<P>
<PRE>    SELECT code, description FROM products WHERE artist = 'Van Gogh'
          AND price &gt;= 1000000 AND price &lt;= 20000000
          ORDER BY price DESC
</PRE>
<P></DL>
<P>
<HR>


code: 11.09
section: THE_SEARCH_ENGINE
type: item
title: One-click searches

<A NAME="One_click_searches">One-click searches</A></H2>
<P>
MiniVend allows you to pass a search in a 
<FONT SIZE=-1>URL.</FONT> Just specify the search with the special page
reference <CODE>scan</CODE>. Here is an example:

<P>
<PRE>     [page scan se=Impressionists/sf=category]
        Impressionist Paintings
     [/page]
</PRE>
<P>
Here is the same thing from a home page (assuming /cgi-bin/vlink is the 
<FONT SIZE=-1>CGI</FONT> path for MiniVend's vlink):

<P>
<PRE>     &lt;A HREF=&quot;/cgi-bin/vlink/scan/se=Impressionists/sf=category&quot;&gt;
        Impressionist Paintings
     &lt;/A&gt;
</PRE>
<P>
The two-letter abbreviations are mapped with these letters:

<P>
<PRE>  DL  mv_raw_dict_look        ms  mv_min_string
  MM  mv_more_matches         ne  mv_negate
  SE  mv_raw_searchspec       nu  mv_numeric
  ac  mv_all_chars            op  mv_column_op
  bd  mv_base_directory       os  mv_orsearch
  bs  mv_begin_string         ra  mv_return_all
  co  mv_coordinate           rd  mv_return_delim
  cs  mv_case                 rf  mv_return_fields
  de  mv_dict_end             rg  mv_range_alpha
  df  mv_dict_fold            rl  mv_range_look
  di  mv_dict_limit           rm  mv_range_min
  dl  mv_dict_look            rn  mv_return_file_name
  do  mv_dict_order           rs  mv_return_spec
  dp  mv_delay_page           rx  mv_range_max
  dr  mv_record_delim         se  mv_searchspec
  em  mv_exact_match          sf  mv_search_field
  er  mv_spelling_errors      sp  mv_search_page
  fi  mv_search_file          sq  mv_sql_query
  fm  mv_first_match          st  mv_searchtype
  fn  mv_field_names          su  mv_substring_match
  hs  mv_head_skip            tc  mv_sort_command
  id  mv_index_delim          tf  mv_sort_field
  lr  mv_search_line_return   to  mv_sort_option
  ml  mv_matchlimit           ty  mv_sort_crippled
  mm  mv_max_matches          un  mv_unique
  mp  mv_profile              va  mv_value
</PRE>
<P>
They can be treated just the same as form variables on the page, except that they can't contain spaces, '/' in a file name, or quote marks. These characters can be used in 
<FONT SIZE=-1>URL</FONT> hex encoding, i.e. <CODE>%20</CODE> is a space, <CODE>%2F</CODE> is a
 <CODE>/</CODE>, etc. --
<CODE>&amp;sp;</CODE> or <CODE>&amp;#32;</CODE> will not be recognized. If you use one of the methods below to escape these
``unsafe'' characters, you won't have to worry about this.

<P>
<STRONG>IMPORTANT NOTE:</STRONG> An incompatibility in earlier MiniVend catalogs is specifying <CODE>[page scan/se=searchstring]</CODE> on a <CODE>[new]</CODE> parsed page. This is interpreted by the new parser as <CODE>[page scan/se=&quot;searchstring&quot;]</CODE> and will cause a bad 
<FONT SIZE=-1>URL.</FONT> Change this to <CODE>[page scan se=searchstring]</CODE> to make those earlier catalogs work with MiniVend 3.10 and higher.

<P>
Beginning in MiniVend 3.08, you may specify a one-click search in three different ways. The first is as used in previous versions, with the scan 
<FONT SIZE=-1>URL</FONT> being specified completely as the page name; this will only work in a
 <CODE>[compat] [/compat]</CODE> region or on an <CODE>[old]</CODE> page. The second two use the ``argument'' parameter to the <CODE>[page ...]</CODE> or <CODE>[area ...]</CODE>
tags to specify the search (an argument to a scan is never valid anyway).

<DL>
<DT><STRONG><A NAME="item_Original">Original</A></STRONG><DD>

If you wish to do an 
<FONT SIZE=-1>OR</FONT> search on the fields category and artist for the
strings ``Surreal'' and ``Gogh'', while matching substrings, you would do:

<P>
<PRE> [page scan se=Surreal/se=Gogh/os=yes/su=yes/sf=artist/sf=category]
    Van Gogh -- compare to surrealists
 [/page]
</PRE>
<P>
In this method of specification, to replace a / (slash) in a file name (for
the sp, bd, or fi parameter) you must use the shorthand of ::, i.e.
sp=results::standard. (This may not work for some browsers, so you should
probably either put the page in the main pages directory or define the page
in a search profile.)

<P><DT><STRONG><A NAME="item_Multi">Multi-line</A></STRONG><DD>

You can specify parameters one to a line, as well. 

<P>
<PRE>    [page scan
        se=&quot;Van Gogh&quot;
        sp=lists/surreal
        os=yes
        su=yes
        sf=artist
        sf=category
    ] Van Gogh -- compare to surrealists [/page]
</PRE>
<P>
Any ``unsafe'' characters will be escaped. If you need to search for
trailing spaces (unlikely) you must quote.

<P><DT><STRONG><A NAME="item_Ampersand">Ampersand</A></STRONG><DD>

You can substitute &amp; for / in the specification and be able to use /
and quotes and spaces in the specification.

<P>
<PRE> [page scan se=&quot;Van Gogh&quot;&amp;sp=lists/surreal&amp;os=yes&amp;su=yes&amp;sf=artist&amp;sf=category]
    Van Gogh -- compare to surrealists
 [/page]
</PRE>
<P>
Any ``unsafe'' characters will be escaped. 

<P></DL>
<P>
New syntax and old syntax handle the tags the same, though if by some odd
chance you wanted to be able to search for a <CODE>]</CODE> (right square bracket) you would need to use new syntax.

<P>
<HR>


code: 11.10
section: THE_SEARCH_ENGINE
type: item
title: Setting display options with mv_value

<A NAME="Setting_display_options_with_mv_">Setting display options with mv_value</A></H2>
<P>
As of MiniVend 3.11, you can specify a value that will be set in the link
with the <A HREF="#item_mv_value">mv_value</A> parameter. It takes an argument of <CODE>var=value</CODE>, just as you would set a normal variable in a MiniVend profile. Actually
<A HREF="#item_mv_value">mv_value</A> is a misnomer, for you would almost never use it in a form, where you can
easily set variable values. You will always specify it in a one-click
search with <CODE>va=var=value</CODE>. Example:

<P>
<PRE>    [page href=scan
          arg=&quot;se=Renaissance
               se=Impressionists
               va=category_name=Renaissance and Impressionist Paintings
               os=yes&quot;]Renaissance and Impressionist Paintings[/page]
</PRE>
<P>
Now you can display the appropriate category on the search results page
with <CODE>[value category_name]</CODE>.

<P>
<HR>


code: 11.11
section: THE_SEARCH_ENGINE
type: item
title: In-page searches

<A NAME="In_page_searches">In-page searches</A></H2>
<P>
<STRONG>NOTE:</STRONG> This section is appropriate for MiniVend 3.09 and above.

<P>
You may specify a search inside a page with the <CODE>[search parameters*]</CODE> or
<CODE>[search_region parameters*]</CODE> tag. The parameters are the same as the the one-click search, and the
output is always a newline-separated list of the return objects -- by
default a series of item codes.

<P>
The <CODE>[loop ...]</CODE> tag directly accepts a search parameter. To search for all products in the
categories ``Americana'' and ``Contemporary'' you can do:

<P>
<PRE>    [loop search=&quot;
        se=Americana
        se=Contemporary
        os=yes
        sf=category9
        &quot;]
    Artist: [loop-field artist]&lt;BR&gt;
    Title: [loop-field title]&lt;P&gt;
    [/loop]
</PRE>
<P>
The advantage of the in-page search is that you can embed searches within searches, and you can have straight unchanging links from static 
<FONT SIZE=-1>HTML</FONT> pages.


<P>
The syntax is a bit tricky because of the 
<FONT SIZE=-1>HTML</FONT> style evaluation and the <CODE>=</CODE> signs in both argument types, so you may want to pre-set the search
arguments with a search profile. Any string passed to the search tag that
doesn't contain an equals (<CODE>=</CODE>) sign is considered a search profile name. Example:

<P>
<PRE>    [set My search]
    mv_searchspec=Americana
    mv_searchspec=Contemporary
    mv_search_field=category
    mv_orsearch=yes
    [/set]
</PRE>
<P>
Now doing a search with <CODE>[search My search]</CODE> or <CODE>[loop search=&quot;My search&quot;]</CODE>
will use the above settings. 

<P>
If you want to use the shorthand ``se=Americana'' notation, you can set the
special scratch variable mv_search_arg:

<P>
<PRE>    [set mv_search_arg]
    se=Americana
    se=Contemporary
    sf=category
    os=yes
    [/set]
</PRE>
<P>

<FONT SIZE=-1>A</FONT> search with empty parameters, as in <A HREF="#item__search_">[search]</A> or <CODE>[loop search=&quot;&quot;]</CODE>, will yield the same results. (You must define an empty string with quote
marks for the second notation -- <CODE>[loop search=]</CODE> will not work.)

<P>
To place an in page search with the full range of display in a normal
results page, use the <CODE>[search-region]</CODE> tag the same as above, except that you can place <CODE>[search-list]</CODE>, <CODE>[more-list]</CODE>, and <CODE>[more]</CODE>
tags within it and use them to display and format the results -- including
paging.

<P>
For example:

<P>
<PRE>    [search-region   se=Americana
                     sf=category
                     ml=2
                     ]
    [more-list][more][/more-list]
    [search-list]
    &lt;A MV=&quot;page [item-code]&quot; HREF=&quot;flypage.html&quot;&gt;
        [item-field title]&lt;A&gt;, by [item-field artist]
    [/search-list]
    [no-match]
        Sorry, no matches for [value mv_searchspec].
    [/no-match]
    [/search-region]
</PRE>
<P>
If you want to use the same page for search paging, make sure you set the <CODE>sp=page</CODE> parameter.

<P>
<HR>


code: 11.12
section: THE_SEARCH_ENGINE
type: item
title: Search Profiles

<A NAME="Search_Profiles">Search Profiles</A></H2>
<P>
You can predefine an unlimited number of search profiles that reside in a
file or files. To use this, make up a series of lines like:

<P>
<PRE> mv_search_field=artist
 mv_search_field=category
 mv_orsearch=yes
</PRE>
<P>
These correspond to the MiniVend search variables that can be set on a
form. You can set it right on the page that contains the search.

<P>
<PRE>    [set artist_profile]
    mv_search_field=artist
    mv_search_field=category
    mv_orsearch=yes
    [/set]
</PRE>
<P>
Then in the search form, set a variable with the name of the profile:

<P>
<PRE>    &lt;INPUT TYPE=hidden NAME=mv_profile VALUE=artist_profile&gt;
</PRE>
<P>
In a one-click search, you use the <CODE>mp</CODE> modifier:

<P>
<PRE>    [page scan se=Leonardo/mp=artist_profile]A left-handed artist[/page]
</PRE>
<P>
You can also place them in a file. Define the file name in the
<EM>SearchProfile</EM> directive. (You must reconfig the catalog for MiniVend to read it.) The profile is named by placing a name following a 
<FONT SIZE=-1>__NAME__</FONT> pragma:


<P>
<PRE>  __NAME__ title_search
</PRE>
<P>
The 
<FONT SIZE=-1>__NAME__</FONT> must begin the line, and be followed by
whitespace and then the name.

<P>
The special variable <CODE>mv_last</CODE> stops interpretation of search variables. The following variables are
always interpreted:

<P>
<PRE>    mv_dict_look
    mv_searchspec
    mv_range_look
    mv_range_min
    mv_range_max
</PRE>
<P>
Other than that, if you set mv_last in a search profile, and there are
other variables on the search form, they will not be interpreted.

<P>
If you want to place multiple search profiles in the same file, separate them with 
<FONT SIZE=-1>__END__,</FONT> which must be on a line by itself.


<P>
<HR>


code: 11.13
section: THE_SEARCH_ENGINE
type: item
title: Search Reference

<A NAME="Search_Reference">Search Reference</A></H2>
<P>
The supplied <CODE>simple/srchform.html</CODE> and <CODE>simple/results.html</CODE> pages show example search forms. You can modify them to present the search
in any way you like -- just be careful to use the proper variable names for
passing to MiniVend. It is also necessary that you copy the hidden
variables as-is -- they are required to interpret the request as a search.

<P>
<STRONG>NOTE:</STRONG> The following definitions frequently refer to <EM>field name</EM>
and <EM>column</EM> and <EM>column number</EM> -- all are the references to the columns of a searched text file as
separated by delimiter characters.

<P>
The field names can be specified in several ways.

<DL>
<DT><STRONG><A NAME="item_products">products.asc</A></STRONG><DD>

If the file to be searched is left empty in the search form or definition
(set with <A HREF="#item_mv_search_file">mv_search_file</A>), then the <EM>products.asc</EM> file will be searched, and field names are already available as named in
the first line of <CODE>products.asc</CODE>.

<P><DT><STRONG><A NAME="item_other">other database files</A></STRONG><DD>

If the file or files to be searched are 
<FONT SIZE=-1>ASCII</FONT> delimited files, and have field names specified
on the first line of the file, MiniVend will read the first line (of the
first file) and determine the field names.

<P><DT><STRONG>other files</STRONG><DD>

If the file or files to be searched are 
<FONT SIZE=-1>ASCII</FONT> delimited files, but
<STRONG>don't</STRONG> have field names specified on the first line of the file, you can set the
variable <A HREF="#item_mv_field_names">mv_field_names</A> to a comma-separated list of field names as they will be referenced.

<P></DL>
<P>
Fields can also always be specified by an integer column number, with 0 as
the first column. This may reduce system processing somewhat, since the
field names don't have to be indexed every time they are referenced, and
won't have to be read from disk.

<DL>
<DT><STRONG><A NAME="item_mv_all_chars">mv_all_chars</A></STRONG><DD>

Scan abbreviation: ac=[1|0]

<P>
Set this if you anticipate searching for lots of punctuation characters
that might be special characters for Perl -- the characters ()[]\$^ are
included.

<P><DT><STRONG><A NAME="item_mv_base_directory">mv_base_directory</A></STRONG><DD>

Scan abbreviation: bd=/directory/name

<P>
In the text search, set to the directory from which to base file searches.
File names without leading / characters will be based from there. In the
Glimpse search, passed to Glimpse with the <CODE>-H</CODE> option, and Glimpse will look for its indices there. Default is ProductDir.

<P>
If you use an absolute path directory, for security you must enable it in
the users session with:

<P>
<PRE>    [set /directory/name]1[/set]
</PRE>
<P>
This prevents users from setting an arbitrary value and viewing arbitrary
files.

<P><DT><STRONG><A NAME="item_mv_begin_string">mv_begin_string</A></STRONG><DD>

If this is set, the string will only match if it is at the beginning of a field. The handling is a bit different for the default 
<FONT SIZE=-1>AND</FONT> search compared to the 
<FONT SIZE=-1>OR</FONT> search. With 
<FONT SIZE=-1>OR</FONT> searches all words are searched for from the beginning of the field, with 
<FONT SIZE=-1>AND</FONT> searches all are.


<P>
This is a multiple parameter. If mv_coordinate is in force, then it should
be set as many times as necessary to match the field/searchstring
combination. If set only once, it applies to all fields. If set more than
once but not as many times as the fields, it will default to off.

<P><DT><STRONG><A NAME="item_mv_case">mv_case</A></STRONG><DD>

If this item is set to <A HREF="#item_no">no</A>, the search will return items without regard to upper or lower case. This
is the default -- set to <A HREF="#item_yes">yes</A> if case should be matched. Implement with a checkbox 
<FONT SIZE=-1>&lt;INPUT</FONT> 
<FONT SIZE=-1>TYPE=CHECKBOX&gt;</FONT> field.


<P>
If stacked to match the mv_search_field and mv_searchspec variables, and <A HREF="#item_mv_coordinate">mv_coordinate</A> is set, it will operate only for the corresponding field.

<P><DT><STRONG><A NAME="item_mv_coordinate">mv_coordinate</A></STRONG><DD>

If this item is set to <EM>yes</EM>, and the number of search fields equals the number of search specs, the
search will return only items that match field to spec. (The search
specifications are set by stacked
<A HREF="#item_mv_searchspec">mv_searchspec</A> and <A HREF="#item_mv_search_field">mv_search_field</A> variables.)

<P>
Case sensitivity, substring matching, and negation all work on a field-by
field basis according to the following:

<P><UL>
<LI>

If only one instance of the option is set, then it will affect all fields.

<P><LI>

If the number of instances of the option is greater than or equal to the
number of search specs, all will be used independently. Trailing instances
will be ignored.

<P><LI>

If more than one instance of the options are set, but fewer than the number
of search specifications, the default setting will be used for the trailing
unset options.

<P>
If a search specification is blank, it will be removed and all
case-sensitivity/negation/substring options will be adjusted accordingly.

<P></UL>
<DT><STRONG><A NAME="item_mv_dict_end">mv_dict_end</A></STRONG><DD>

If the string at the beginning of a line lexically exceeds this value,
matching will stop. Ignored without mv_dict_look.

<P><DT><STRONG><A NAME="item_mv_dict_fold">mv_dict_fold</A></STRONG><DD>

Make dictionary matching case-insensitive. Ignored without mv_dict_look. 
<FONT SIZE=-1>NOTE:</FONT> This is the reverse sense from mv_case.

<P><DT><STRONG><A NAME="item_mv_dict_limit">mv_dict_limit</A></STRONG><DD>

Automatically set the limiting string (mv_dict_end) to be one character greater than the mv_dict_look variable, at the character position specified. 
<FONT SIZE=-1>A</FONT> value of 1, for instance, will set the limiting string to ``fprsythe'' if the value of
 <A HREF="#item_mv_dict_look">mv_dict_look</A> is ``forsythe''. 
<FONT SIZE=-1>A</FONT> useful value is -1, which will increment the last
character (setting the mv_dict_end to ``forsythf'' in our example). This
prevents having to scan the whole file once a unique match is found.

<P>
The order of this and the <A HREF="#item_mv_dict_end">mv_dict_end</A> variable is significant -- each will overwrite the other.

<P>
If this is set to a non-numeric value, an automatic mode is entered which
looks for a dictionary-indexed file that corresponds to the file name plus
<A HREF="#item__field">.field</A>, where <A HREF="#item_field">field</A> is what you have set <A HREF="#item_mv_dict_limit">mv_dict_limit</A> to. The actual value of mv_dict_limit is set to <CODE>-1</CODE>. If the file does not exist, then the original file is silently used (this
might not be what you want!). Also, the value of <A HREF="#item_mv_return_fields">mv_return_fields</A> is set to <CODE>1</CODE> to correspond to the location of the key in the auto-indexed file.

<P>
To illustrate:

<P>
<PRE>    &lt;INPUT TYPE=hidden NAME=mv_dict_limit  VALUE=category&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_file VALUE=&quot;products.asc&quot;&gt;
</PRE>
<P>
is equal to:

<P>
<PRE>    &lt;INPUT TYPE=hidden NAME=mv_dict_limit    VALUE=&quot;-1&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_search_file   VALUE=&quot;products.asc.category&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_return_fields VALUE=&quot;1&quot;&gt;
</PRE>
<P>
The real utility would be in a form construct like

<P>
<PRE>    Search for
    &lt;SELECT NAME=mv_dict_limit&gt;
    &lt;OPTION&gt; author
    &lt;OPTION&gt; title
    &lt;/SELECT&gt; beginning with &lt;INPUT NAME=mv_dictlook&gt;
</PRE>
<P>
which would allow automatic binary search file selection.

<P>
Combined with the <CODE>INDEX</CODE> attribute to the <EM>Database</EM> directive, this allows fast binary search qualification combined with
regular
<A HREF="#item_mv_searchspec">mv_searchspec</A> text searches.

<P><DT><STRONG><A NAME="item_mv_dict_look">mv_dict_look</A></STRONG><DD>

The string at which to begin matching at in a dictionary-based search. If
not set, the mv_dict_end, mv_dict_fold, and mv_dict_case variables will be
ignored. May be set in a search profile based on other form variables.

<P><DT><STRONG><A NAME="item_mv_dict_order">mv_dict_order</A></STRONG><DD>

Make dictionary matching follow dictionary order, where only word
characters and whitespace matter. Ignored without mv_dict_look.

<P><DT><STRONG><A NAME="item_mv_doit">mv_doit</A></STRONG><DD>

This must be set to <A HREF="#item_search">search</A> to make this a search page.

<P><DT><STRONG><A NAME="item_mv_exact_match">mv_exact_match</A></STRONG><DD>

Normally MiniVend searches match words, as opposed to sentences. This
behavior can be overridden with mv_exact_match, which when set will place
quotes around any value in mv_searchspec or mv_dict_look.

<P><DT><STRONG><A NAME="item_mv_field_names">mv_field_names</A></STRONG><DD>

Deprecated in favor of in-list sorting.

<P>
Defines the field names for the file being searched. This guarantees that they will be available, and prevents a disk access if using named fields on a search file (that is not the product database 
<FONT SIZE=-1>ASCII</FONT> source, where field names are already known). This
 <STRONG>must</STRONG> be exactly correct, or it will result in anomalous search operation.
Usually passed in a hidden field or search profile as a comma-separated
list.

<P>

<FONT SIZE=-1>NOTE:</FONT> You should use this on the product database only
if you plan on both pre-sorting with <A HREF="#item_mv_sort_field">mv_sort_field</A> and then post-sorting
<CODE>with [sort]field:opt[/sort]</CODE>.

<P><DT><STRONG><A NAME="item_mv_first_match">mv_first_match</A></STRONG><DD>

Normally MiniVend will return the first page of a search. If you set this
variable it will start the search return at the match specified, even if
there is only one page. If set to a value greater than the number of
matches, it will act as if no matches were found.

<P><DT><STRONG><A NAME="item_mv_head_skip">mv_head_skip</A></STRONG><DD>

Normally MiniVend searches all lines of an index/product file but the
first. Set this to the number of lines to skip at the beginning of the
index. Default is 1 for the text search, which skips the header line in the
product file. Default is 0 for a Glimpse search.

<P><DT><STRONG><A NAME="item_mv_index_delim">mv_index_delim</A></STRONG><DD>

Sets the delimiter for counting fields in a search index. The default is
the same as the <EM>Delimiter</EM> directive.

<P><DT><STRONG><A NAME="item_mv_matchlimit">mv_matchlimit</A></STRONG><DD>

The page size for matches that are returned. If more matches than
<STRONG>mv_matchlimit</STRONG> are found, the search paging mechanism will be employed if the proper <CODE>[more-list]</CODE> is present. Can be implemented as a scrolling list 
<FONT SIZE=-1>(INPUT</FONT> 
<FONT SIZE=-1>TYPE=SELECT)</FONT> or radiobox 
<FONT SIZE=-1>(INPUT</FONT> 
<FONT SIZE=-1>TYPE=RADIO)</FONT> field.


<P><DT><STRONG><A NAME="item_mv_max_matches">mv_max_matches</A></STRONG><DD>

The maximum number of records that will be returned in a search. Default is 2000. This only applies to Glimpse as of 
<FONT SIZE=-1>MV</FONT> 3.12; use mv_matchlimit to set the search page size.


<P><DT><STRONG><A NAME="item_mv_min_string">mv_min_string</A></STRONG><DD>

Sets the minimum size of a search string for a search operation. Default is
4 for the Glimpse search, and 1 for the text search.

<P><DT><STRONG><A NAME="item_mv_negate">mv_negate</A></STRONG><DD>

Specifies that records 
<FONT SIZE=-1>NOT</FONT> matching the search criteria will be returned.
Default is no. It is not operative for the Glimpse search.

<P>
If stacked to match the mv_search_field and mv_searchspec variables, and
mv_coordinate is set, it will operate only for the corresponding field.

<P><DT><STRONG><A NAME="item_mv_orsearch">mv_orsearch</A></STRONG><DD>

If this item is set to <EM>yes</EM>, the search will return items matching any of the words in <EM>searchspec</EM>. The default is <EM>no</EM>.

<P><DT><STRONG><A NAME="item_mv_profile">mv_profile</A></STRONG><DD>

Selects one of the pre-defined search specifications set by the
<EM>SearchProfile</EM> directive. If the special variable within that file,
<CODE>mv_last</CODE>, is defined, it will prevent the scanning of the form input for further
search modifications. The values of <A HREF="#item_mv_searchspec">mv_searchspec</A> and
<A HREF="#item_mv_dict_look">mv_dict_look</A> are always scanned, so you can specify this to do the equivalent of setting
multiple checkboxes or radioboxes with one click, while still reading the
search input text.

<P><DT><STRONG><A NAME="item_mv_range_alpha">mv_range_alpha</A></STRONG><DD>

Sets the type of match, numeric or alphanumeric, for the range search in
its corresponding range field. The search will return true (assuming it is
greater than the mv_range_min specification) if the field searched is less
than or equal to mv_range_max, in an alphanumeric sense.

<P><DT><STRONG><A NAME="item_mv_range_look">mv_range_look</A></STRONG><DD>

This sets a field to scan for a range of numbers. It must be accompanied
with corresponding mv_range_min and mv_range_max variables. It can be
specified with either a field name or a column number.

<P><DT><STRONG><A NAME="item_mv_range_max">mv_range_max</A></STRONG><DD>

Sets the high bound for the range search in its corresponding range field.
The search will return true (assuming it is greater than the mv_range_min
specification) if the field searched is less than or equal to mv_range_max.
To set the bound at infinity, or whatever your integer limit is, set
mv_range_min to 0.

<P><DT><STRONG><A NAME="item_mv_range_min">mv_range_min</A></STRONG><DD>

Sets the low bound for the range search in its corresponding range field.
The search will return true (assuming it is less than the mv_range_max
specification) if the field searched is less than or equal to mv_range_min.

<P><DT><STRONG><A NAME="item_mv_record_delim">mv_record_delim</A></STRONG><DD>

Sets the delimiter for counting records in a search index. The default is
newline, which works for the products and most line-based index files.

<P><DT><STRONG><A NAME="item_mv_return_fields">mv_return_fields</A></STRONG><DD>

The fields that should be returned by the match, specified either by field
name or by column number. You should almost always specify 0 as the first
field to be returned if searching the products database, since that is the
key for accessing database fields.

<P><DT><STRONG><A NAME="item_mv_return_spec">mv_return_spec</A></STRONG><DD>

Returns the string specified as the search (i.e. the value of <A HREF="#item_mv_searchspec">mv_searchspec</A>) as the one and only match. Typically used in a SKU/part number search.

<P><DT><STRONG><A NAME="item_mv_search_field">mv_search_field</A></STRONG><DD>

The <CODE>field(s)</CODE> to be searched, specified either by column name
or by column number.

<P>
If the number of instances matches the number of fields specified in the
<A HREF="#item_mv_searchspec">mv_searchspec</A> variable, and <A HREF="#item_mv_coordinate">mv_coordinate</A> is set to true, each search field (in order specified on the form) will be
matched with each search spec (again in that order).

<P><DT><STRONG><A NAME="item_mv_search_file">mv_search_file</A></STRONG><DD>

In the text search, set this variable to the <CODE>file(s)</CODE> to be
scanned for a match. The default, if not set, is to scan the products.asc
file. If set multiple times in a form (for a text search), will cause a
search all the files. One file name per instance.

<P>
In the Glimpse search, follows the Glimpse wildcard-based file name
matching scheme. Use with caution and a liberal dose of the Glimpse man
page.

<P><DT><STRONG><A NAME="item_mv_search_match_count">mv_search_match_count</A></STRONG><DD>

Set by the search to indicate the total number of matches found.

<P><DT><STRONG><A NAME="item_mv_search_over_msg">mv_search_over_msg</A></STRONG><DD>

The message that should be displayed if there is an overflow condition (<A HREF="#item_mv_matchlimit">mv_matchlimit</A> is exceeded). Overrides the SearchOverMsg directive -- it is cleared by
MiniVend if there is no overflow. Somewhat deprecated by match paging.

<P><DT><STRONG><A NAME="item_mv_search_page">mv_search_page</A></STRONG><DD>

The MiniVend-style name of the page that should display the search results.
Overrides the FrameSearchPage directive, and the default value of <A HREF="#item_search">search</A>.

<P><DT><STRONG><A NAME="item_mv_searchspec">mv_searchspec</A></STRONG><DD>

The actual search string that is typed in by the customer. It is a text 
<FONT SIZE=-1>INPUT</FONT> 
<FONT SIZE=-1>TYPE=TEXT</FONT> field, or can be put in a select (drop-down) list to enable category searches. If multiple instances are found, they will be concatenated just as if multiple words had been placed in a text field.


<P>
The user can place quotes around words to specify that they match as a
string. To enable this by default, use the <A HREF="#item_mv_exact_match">mv_exact_match</A>
variable.

<P>
If <A HREF="#item_mv_dict_look">mv_dict_look</A> has a value, and <A HREF="#item_mv_searchspec">mv_searchspec</A> does <STRONG>not</STRONG>, then mv_searchspec will be set to the value of mv_dict_look.

<P>
If the number of instances matches the number of fields specified in the
<A HREF="#item_mv_search_field">mv_search_field</A> variable, and <A HREF="#item_mv_coordinate">mv_coordinate</A> is set to true, each search field (in order specified on the form) will be
matched with each search spec (again in that order).

<P><DT><STRONG><A NAME="item_mv_searchtype">mv_searchtype</A></STRONG><DD>

If set to <EM>glimpse</EM>, selects the Glimpse search (if Glimpse is defined).

<P>
If set to <EM>sql</EM>, formulates an 
<FONT SIZE=-1>SQL</FONT> select statement to return the search list. 

<P>
If set to <EM>db</EM>, iterates over every row of the database (not the associated text source
file).

<P>
If set to <EM>text</EM>, selects the text-based search.

<P>
Defaults to <EM>text</EM> if <EM>Glimpse</EM> is not defined, to Glimpse if it is. This can allow use of both search
types if that is desirable -- for instance, searching for very common
strings is better done by the text-based search. An example might be
searching for categories of items instead of individual items.

<P><DT><STRONG><A NAME="item_mv_sort_command">mv_sort_command</A></STRONG><DD>

In Minivend 
<FONT SIZE=-1>V3.09</FONT> and higher, the default is to use an internal sort routine which should be better than most 
<FONT SIZE=-1>UNIX</FONT> sorts. But if you wish to use an external sort command, set
 <A HREF="#item_mv_sort_command">mv_sort_command</A> to a path name that will access the standard 
<FONT SIZE=-1>UNIX</FONT> sort command -- in most cases simply
<EM>sort</EM>. If the sort command does not accept field-specific options, as more recent sorts like the 
<FONT SIZE=-1>GNU</FONT> sort command do, set mv_sort_crippled to
 <EM>yes</EM>.

<P><DT><STRONG><A NAME="item_mv_sort_field">mv_sort_field</A></STRONG><DD>

The file <CODE>field(s)</CODE> the search is to be sorted on, specified in
one of two ways. If the <CODE>file(s)</CODE> to be searched have a header
line (the first line) that contains <EM>Delimiter</EM>-separated field names, it can be specified by field name. If can also be
specified by column number (the code or key is specified with a value of 0,
for both types). These can be stacked, if coming from a form, or placed in
a single specification separated by commas.

<P>

<FONT SIZE=-1>NOTE</FONT> 
<FONT SIZE=-1>FOR</FONT> 
<FONT SIZE=-1>ADVANCED</FONT> 
<FONT SIZE=-1>USERS:</FONT> If specifying a sort for the product database,

<A HREF="#item_mv_field_names">mv_field_names</A> must be specified if you will be doing a fieldname-addressed post-sort.

<P><DT><STRONG><A NAME="item_mv_sort_option">mv_sort_option</A></STRONG><DD>

The way that each field should be sorted. The flags are <CODE>r</CODE>, <CODE>n</CODE>, and <A HREF="#item_f">f</A> -- for reverse, numeric, and case-insensitive respectively. These can be
stacked, if coming from a form, or placed in a single specification
separated by commas. The stacked options will be applied to the sort fields
as they are defined, presuming those are stacked.

<P><DT><STRONG><A NAME="item_mv_spelling_errors">mv_spelling_errors</A></STRONG><DD>

The number of spelling errors that will be tolerated. Ignored unless using
Glimpse. If you have a large catalog, you might wish to limit this to two.

<P><DT><STRONG><A NAME="item_mv_substring_match">mv_substring_match</A></STRONG><DD>

If <A HREF="#item_mv_substring_match">mv_substring_match</A> is set to <EM>yes</EM>, matches on substrings as well as whole words. You would typically want to
set this for dictionary-based searches.

<P>
If stacked to match the <A HREF="#item_mv_search_field">mv_search_field</A> and <A HREF="#item_mv_searchspec">mv_searchspec</A> variables, and <A HREF="#item_mv_coordinate">mv_coordinate</A> is set, it will operate only for the corresponding field.

<P><DT><STRONG><A NAME="item_mv_unique">mv_unique</A></STRONG><DD>

If set to a true value, causes the sort to return only unique results. This
operates on whatever the search return is, as defined by
<A HREF="#item_mv_return_fields">mv_return_fields</A>.

<P><DT><STRONG><A NAME="item_mv_value">mv_value</A></STRONG><DD>

This is normally only used in the one-click search (va=var=value). It
allows setting of a session variable based on the clicked link, which makes
for easy definition of headers and other display choices. (If you had
trouble using <A HREF="#item_mv_searchspec">mv_searchspec</A> for this before, this is what you need.)

<P></DL>
<P>
<HR>


code: 11.14
section: THE_SEARCH_ENGINE
type: item
title: The Results Page

<A NAME="The_Results_Page">The Results Page</A></H2>
<P>
Once a search has been done, there needs to be a way of presenting the
output. By default, the <EM>SpecialPage</EM> search is used -- it is set to <CODE>results</CODE> in the distribution demo -- but any number of search pages can be specified
by passing the value in the search form, specified in the variable <A HREF="#item_mv_search_page">mv_search_page</A>.

<P>
On the search page, some special MiniVend tags are used to format the otherwise standard 
<FONT SIZE=-1>HTML.</FONT> Each of the iterative tags is applied to every code returned from the search -- this is normally the product code, but could be a key to any of the arbitrary databases. The value placed by the
 <CODE>[item-code]</CODE> tag is set to the first field returned from the search.

<DL>
<DT><STRONG><A NAME="item__search_list_">[search-list]</A></STRONG><DD>

Starts the representation of a search list. MiniVend tags can be embedded
in the search list, yielding a table or formatted list of items with part
number, description, price, and hyperlinks to order or go to its catalog
page. 

<P>
The set of tags for <CODE>[item-list]</CODE> are available, with the exception of tags like <CODE>[item-modifier]</CODE>, <CODE>[modifier-name]</CODE>, <CODE>[item-accessories]</CODE>, and others that access shopping-cart specific elements. Thse include:

<P>
<PRE>    [if-data table column] [/if-data]
    [if-field column] [/if-field]
    [item-code]
    [item-data table column]
    [item-discount]
    [item-field column]
    [item-price quantity* noformat*]
</PRE>
<P>
In fact, any of the MiniVend database access tags can be used, allowing you
to pull data from any of the fields in any of your predefined databases.
Along with the MiniVend conditional tags, very complex pages can be built
for each individual item returned in the search.

<P><DT><STRONG><A NAME="item__search_list_">[/search-list]</A></STRONG><DD>

Ends the search list. 

<P><DT><STRONG><A NAME="item__no_match_">[no-match]</A></STRONG><DD>

Starts the region of the search results page that should be returned if
there is no match (and no error) for the search. If this is not on the
page, the special page <EM>nomatch</EM> will be displayed instead.

<P><DT><STRONG><A NAME="item__no_match_">[/no-match]</A></STRONG><DD>

Ends the no match region.

<P><DT><STRONG><A NAME="item__sort">[sort database:field:option* database:field:option*]</A></STRONG><DD>

Sorts the search list return based on database fields. If no options are
supplied, sorts according to the return code. See
<EM>SORTING</EM>.

<P><DT><STRONG><A NAME="item__sort_options_sort_">[sort]&lt;options&gt;[/sort]</A></STRONG><DD>

(This form of sort is deprecated, as it is difficult to use. Use the above
method.)

<P>
Placed inside the search list. Causes sorting of the search return based on
the passed options. The fields that are there to sort are set by <A HREF="#item_mv_return_fields">mv_return_fields</A>.

<P>
The field options passed in either numeric or field name form. If they are
field numbers, they are numbered as sent to the search list in the order
specified by <EM>mv_return_fields</EM>, starting from 0 and proceeding upwards. If column names, they are as found in the first record of the searched file (by default the 
<FONT SIZE=-1>ASCII</FONT> source for the product database),
 <EM>except for the key or first field</EM>. followed by a <EM>required</EM> colon (:) and the options, if any.

<P>
Accepts none, any, or combinations of the flags:

<P>
<PRE>  f   case-insensitive sort (folded) (mutually exclusive of n)
  n   numeric order (mutually exclusive of f)
  r   reverse sort
</PRE>
<P>
The &lt;options&gt; are a field number and an optional flag or flags, in a
similar fashion to the Unix sort command, and are interpolated for form
values before being used. As an example, if you set up the following fields
on your search form:

<P>
<PRE>  &lt;INPUT TYPE=&quot;hidden&quot; NAME=&quot;mv_return_fields&quot; VALUE=&quot;0,title,artist,price&quot;&gt;
  &lt;INPUT TYPE=&quot;radio&quot; NAME=&quot;the_sort_field&quot; VALUE=&quot;title&quot;&gt; Sort by Title
  &lt;INPUT TYPE=&quot;radio&quot; NAME=&quot;the_sort_field&quot; VALUE=&quot;artist&quot;&gt; Sort by Artist
  &lt;INPUT TYPE=&quot;radio&quot; NAME=&quot;the_sort_option&quot; VALUE=&quot;&quot;&gt; Forward sort
  &lt;INPUT TYPE=&quot;radio&quot; NAME=&quot;the_sort_option&quot; VALUE=&quot;r&quot;&gt; Reverse sort
  
  NOTE: The 0 refers to the database code/key used for [item-code]
</PRE>
<P>
This would combine with the following search result page fragment to sort
by either title or artist.

<P>
<PRE>    [search-list]
      [sort]
        [value the_sort_field]:[value the_sort_option]
      [/sort]
    &lt;B&gt;[item-field title]&lt;/B&gt;, by [item-field artist]&lt;BR&gt;
    [/search-list]
</PRE>
<P>
The [value...] lines will end up looking like <CODE>artist:r</CODE> or <CODE>title:</CODE>. This could also be specified with <CODE>2r</CODE> or <CODE>1</CODE>.

<P>

<FONT SIZE=-1>PERFORMANCE</FONT> 
<FONT SIZE=-1>TIP:</FONT> on heavily trafficked systems, it will pay to use only column numbers rather than named fields, as it reduces processing and may obviate an access to the searched file to find the field names.


<P><DT><STRONG><A NAME="item__uniq_">[uniq]</A></STRONG><DD>

Placed <STRONG>immediately</STRONG> after the <CODE>[sort]</CODE> tag (after <CODE>[search-list]</CODE>
if doing sorts via mv_sort_field). If specified on a sorted return list,
causes only the first line containing an <CODE>[item-code]</CODE> to be returned -- all subsequent lines will not be interpreted on the list.
Note that
<CODE>[matches]</CODE> and <CODE>[more-list]</CODE> may not operate as you wish in this case.
<STRONG>Note</STRONG> that <CODE>[on-change]</CODE> is more likely useful.

<P><DT><STRONG><A NAME="item__on_change">[on-change marker]</A></STRONG><DD>

Active only within <CODE>[search-list][/search-list]</CODE>.

<P>
Along with the companion <CODE>[/on-change marker]</CODE>, surrounds a region which should only be output when a field (or other
repeating value) changes its value. This allows indented lists similar to
database reports to be easily formatted. The repeating value must be a tag
interpolated in the search process, such as <CODE>[item-field field]</CODE> or <CODE>[item-data database field]</CODE>.

<P>
Of course, this will only work as you expect when the search results are
properly sorted.

<P>
The <CODE>marker</CODE> field is mandatory, and is also arbitrary, meaning that you can select any
marker you wish as long as it matches the marker associated with <CODE>[/on-change marker]</CODE>. The value to be tested is contained within a <CODE>[condition]value[/condition]</CODE> tag pair. The <CODE>[on-change marker]</CODE> tag also processes an <CODE>[else] [/else]</CODE> pair for output when the value does not change. The tags may be nested as
long as the markers are different.

<P>
Here is a simple example for a search list that has a field <A HREF="#item_category">category</A> and
<CODE>subcategory</CODE> associated with each item:

<P>
<PRE> &lt;TABLE&gt;
 &lt;TR&gt;&lt;TH&gt;Category&lt;/TH&gt;&lt;TH&gt;Subcategory&lt;/TH&gt;&lt;TH&gt;Product&lt;/TH&gt;&lt;/TR&gt;
 [search-list]
 &lt;TR&gt;
    &lt;TD&gt;
         [on-change cat]
 
         [condition][item-field category][/condition]
 
                 [item-field category]
         [else]
                 &amp;nbsp;
         [/else]
         [/on-change cat]
    &lt;/TD&gt;
    &lt;TD&gt;
         [on-change subcat]
 
         [condition][item-field subcategory][/condition]
 
                 [item-field subcategory]
         [else]
                 &amp;nbsp;
         [/else]
         [/on-change subcat]
    &lt;/TD&gt;
    &lt;TD&gt; [item-field name] &lt;/TD&gt;
 [/search-list]
 &lt;/TABLE&gt;
</PRE>
<P>
The above should put out a table that only shows the category and
subcategory once, while showing the name for every product. (The <CODE>&amp;nbsp;</CODE>
will prevent blanked table cells if you use a border.)

<P><DT><STRONG><A NAME="item__on_change">[/on-change marker]</A></STRONG><DD>

Companion to <CODE>[on-change marker]</CODE>.

<P><DT><STRONG><A NAME="item__matches_">[matches]</A></STRONG><DD>

Replaced with the range of match numbers displayed by the search page.
Looks something like ``1-50''. Make sure you insert this item between a <CODE>[more-list]</CODE> and <CODE>[/more-list]</CODE>
element pair.

<P><DT><STRONG><A NAME="item__more_list">[more-list next_img* prev_img* page_img* border* border_current*]</A></STRONG><DD>

Starts the section of the search page which is only displayed if there are
more matches than specified in <A HREF="#item_mv_matchlimit">mv_matchlimit</A>. If there are less matches than the number in mv_matchlimit, all text/html
between the <CODE>[more_list]</CODE> and <CODE>[/more_list]</CODE> elements is stripped.

<P>
Use in conjunction with the <CODE>[more]</CODE> element to place pointers to additional pages of matches.

<P>
If the optional arguments <CODE>next_img</CODE>, <CODE>prev_img</CODE>, and/or <CODE>page_img</CODE>
are present, they represent image files that will be inserted instead of
the standard 'Next', 'Previous', and page number. If <CODE>prev_img</CODE>
is <CODE>none</CODE>, then no previous link will be output. If <CODE>page_img</CODE> is
<CODE>none</CODE>, then no links to pages of matches will be output. These are URLs, are
substituted for with <EM>ImageDir</EM> and friends, and will be encased in 
<FONT SIZE=-1>IMG</FONT> tags. Lastly, <CODE>border</CODE> is the border number to put.

<P>
In addition, if <CODE>page_img</CODE> is used, it will be passed an argument of the digit that is to be
represented. This would allow an image generator program to be used,
generating page numbers on the fly. The <CODE>border</CODE>
and <CODE>border_selected</CODE> values are integers indicating the border that should be put around images
in the <CODE>page_img</CODE> selection. The &lt;border_selected&gt; is used for the current page if set.

<P>
As an example, if you use <CODE>[more-list next.gif prev.gif page_num.cgi]</CODE>, the following will be the anchors:

<P>
<PRE>  Previous   &lt;IMG SRC=&quot;prev.gif&quot;&gt;
  Page 1     &lt;IMG SRC=&quot;/cgi-bin/page_num.cgi?1&quot;&gt;
  Page 2     &lt;IMG SRC=&quot;/cgi-bin/page_num.cgi?2&quot;&gt;
  Next       &lt;IMG SRC=&quot;next.gif&quot;&gt;
</PRE>
<P>
If you wish to set custom text for the ``Previous'' and ``Next'' usually
used, then you can define the next_img, prev_img, and page_img with
<CODE>[next-anchor][/next-anchor]</CODE>, <CODE>[prev-anchor][/prev-anchor]</CODE> and
<CODE>[page-anchor][/page-anchor]</CODE>. The string 
<FONT SIZE=-1>$PAGE$</FONT> will be replaced with the page number in the
latter. The same example:

<P>
<PRE>    [more-list 0 0 0]
    [next-anchor] Forward [/next-anchor]
    [prev-anchor] Back [/prev-anchor]
    [page-anchor] Page $PAGE$ [/page-anchor]
    [more]
    [/more-list]
</PRE>
<P>
will display U&lt;Forward Page 1 Page 2 Back&gt; for 2 pages.

<P>
As shown, you must pass a 0 for the arguments of each to tell MiniVend to
look for the assignments.

<P><DT><STRONG><A NAME="item__more_list_">[/more-list]</A></STRONG><DD>

Companion to <CODE>[more-list]</CODE>. 

<P><DT><STRONG><A NAME="item__more_">[more]</A></STRONG><DD>

Inserts a series of hyperlinks that will call up the next matches in a
series. They look like this:

<P>
<PRE>    Previous 1 2 3 4 5 6 Next
</PRE>
<P>
The current page will not be a hyperlink. Every time the new link is
pressed, the list is re-built to correspond to the current page. If there
is no <CODE>Next</CODE> or <CODE>Previous</CODE> page, that link will not be shown.

<P>
See the <CODE>fr_resul.html</CODE> or <CODE>search.html</CODE> files for examples. Make sure you insert this item between a <CODE>[more-list]</CODE> and <CODE>[/more-list]</CODE> element pair.

<P><DT><STRONG><A NAME="item__process_search_">[process-search]</A></STRONG><DD>

Calls the search with the proper 
<FONT SIZE=-1>URL,</FONT> including MiniVend session tags. Used as the 
<FONT SIZE=-1>ACTION</FONT> value for the search form.


<P><DT><STRONG><A NAME="item__process_target">[process-target frame]</A></STRONG><DD>

Calls the search with the proper 
<FONT SIZE=-1>URL,</FONT> including MiniVend session tags. Used as the 
<FONT SIZE=-1>ACTION</FONT> value for the search form if the results are to be targeted to a different window than the one set by SearchFrame (which is ``_self'' by default).


<P></DL>
<P>
<HR>


code: 11.14
section: THE_SEARCH_ENGINE
type: item
title: Using a Search Cache

<A NAME="Using_a_Search_Cache">Using a Search Cache</A></H2>
<P>
Each catalog may maintain a search cache, which is enabled by specifying
<CODE>Yes</CODE> for the <EM>SearchCache</EM> directive in <EM>catalog.cfg</EM>. It operates by developing a 
<FONT SIZE=-1>MD5</FONT> key or 3-byte checksum of the combined parameters
of a search.

<P>
If your catalog frequently specifies category searches in a large catalog,
speed of search return can be increased by a large factor, mostly by
obviating the need for database lookups.

<P>
If you have mostly dynamic session-based content based on user variables,
you should not use SearchCache unless you want to give that up. MiniVend
will not cache pages with dynamic content, and using cache slows down
searches that don't cache.

<P>
If you have the 
<FONT SIZE=-1>MD5</FONT> module installed on Perl, it will be used to generate the cache keys. This will guarantee a unique cache 
<FONT SIZE=-1>ID.</FONT> If you don't have 
<FONT SIZE=-1>MD5</FONT> installed, a 32-bit checksum will be used to create the cache key. It is conceivable, indeed likely in a large catalog, that two separate searches could generate the same 32-bit checksum and return the same cached search.


<P>
The search cache is invalidated when a user hits 
<FONT SIZE=-1>``RELOAD''.</FONT> It can also be invalidated by a <CODE>[set mv_no_cache]1[/set]</CODE> scratch setting, which only takes effect for the next page.

<P>
If you change your product database or any other files you search, you
should reconfigure or the search returns may be wrong. You also may just
remove all files in the tmp/ directory.

<P>
Search caching is disabled on a client-by-client basis if the client
browser does not have cookie capability, for the generated session numbers
would be incorrect otherwise.

<P>
Multiple page returns are also cached. If you <CODE>[set mv_no_count]1[/set]</CODE>
on the calling page, then the user's browser will keep track of the
traveled links.

<P>
The last search can be recalled with <CODE>[page href=&quot;[data session last_search]&quot;]</CODE>.

<P>
<HR>


code: 11.15
section: THE_SEARCH_ENGINE
type: item
title: Updating session variables after a search

<A NAME="Updating_session_variables_after">Updating session variables after a search</A></H2>
<P>
You may notice that if you set a scratch variable or reference a variable
set in a search routine on the results page, the change does not stay in
the user session.

<P>
To change this, set the <STRONG>scratch</STRONG> variable <CODE>mv_put_session</CODE> on the page in question:

<P>
<PRE>    [set mv_put_session]Yes[/set]
</PRE>
<P>
This setting is persistent, so it is recommended that you do it once at the
beginning of the user session if you wish it to be the default. If you
don't want it to be the default, reset it to the empty value (or zero) on
another page:

<P>
<PRE>    [set mv_put_session][/set]
</PRE>
<P>
<HR>


code: 12.00
section: THE_SEARCH_ENGINE
type: overview
title: THE SEARCH ENGINE

<A NAME="THE_SEARCH_ENGINE">THE SEARCH ENGINE</A></H1>
<P>
MiniVend implements a search engine which will search the product database
(or any other file) for items based on customer input. It uses either forms
or link-based searches that are called with the special page name
<CODE>scan</CODE>. The search engine uses many special MiniVend tags and variables.

<P>
If the search is implemented in a link or a form, it will always display
formatted results on <EM>the results page</EM>, a MiniVend page that uses some combination of the <CODE>[search-region]</CODE>, <CODE>[search-list]</CODE>,
<CODE>[more-list]</CODE>, <CODE>[more]</CODE>, and other MiniVend tags to format and display the results. The search
results are usually a series of product codes/SKUs or other database keys,
which are then iterated over similar to the 
<CODE>[item-list]</CODE>.

<P>
Examples of search forms and result pages are included in the supplied
demos.

<P>
Two search engine interfaces are provided, and five types of searching are
available. The default is a text-based search of the
<CODE>products.asc</CODE> file. 
<FONT SIZE=-1>A</FONT> binary search of a dictionary-ordered file can be
specified. An optional Glimpse search is enabled by placing the command
specification for Glimpse in the directive <EM>Glimpse</EM>. There is a range-based search, used in combination with one of the above. And finally, there is an 
<FONT SIZE=-1>SQL</FONT> search which translates the MiniVend search interface to 
<FONT SIZE=-1>SQL</FONT> queries.


<P>
The default, a text based search, sequentially scans the lines in the
target file. By default it returns the first field (delineated by the
standard <EM>Delimiter</EM>), for every line matching the search specification. This corresponds to
the product code, which is then used to key specific accesses to the
database.

<P>
The text-based search is capable of sophisticated field-specific searches with fully-independent case-sensitivity, substring, and negated matching. (There is not yet a full search language except for 
<FONT SIZE=-1>SQL</FONT> queries, so 
<FONT SIZE=-1>AND/OR</FONT> matching is not supported across multiple fields. Stay tuned for this in MiniVend 3.1 or later.)


<P>
<HR>


code: 12.02
section: THE_ORDER_PROCESS
type: item
title: How to set up an order link

<A NAME="How_to_set_up_an_order_link">How to set up an order link</A></H2>
<P>
On a product display page, use:

<P>
<PRE>    [order 00-0011]Order the Mona Lisa[/order]
</PRE>
<P>
If coming from a search results or on-the-fly page, you may use the
generated
<CODE>[item-code]</CODE> thusly:

<P>
<PRE>    [order [item-code]]Order [item-field name][/order]
</PRE>
<P>
Bear in mind that if you have not reached the page via a search or
on-the-fly operation, <CODE>[item-code]</CODE> means nothing and will cause an error.

<P>
<HR>


code: 12.03
section: THE_ORDER_PROCESS
type: item
title: How to set up an order button

<A NAME="How_to_set_up_an_order_button">How to set up an order button</A></H2>
<P>
MiniVend can order via form submission as well. This allows you to order a
product (or group of products) via a form button. In its simplest form, it
is:

<P>
<PRE>    &lt;FORM ACTION=&quot;[process-target]&quot; METHOD=POST&gt;
    &lt;INPUT TYPE=hidden NAME=mv_todo ACTION=refresh&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_item VALUE=&quot;00-0011&quot;&gt;
    &lt;INPUT TYPE=submit VALUE=&quot;Order the Mona Lisa&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
The default quantity is one. An initial quantity may be set by the user by
adding an mv_order_quantity variable:

<P>
<PRE>     Number to order:&lt;INPUT TYPE=text NAME=mv_order_quantity VALUE=&quot;1&quot;&gt;
</PRE>
<P>
You can order multiple items by stacking the variables:

<P>
<PRE>    &lt;FORM ACTION=&quot;[process-target]&quot; METHOD=POST&gt;
    &lt;INPUT TYPE=hidden NAME=mv_todo ACTION=refresh&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_item VALUE=&quot;00-0011&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_item VALUE=&quot;00-0011a&quot;&gt;
    &lt;INPUT TYPE=submit VALUE=&quot;Order the Mona Lisa with frame&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
Initial size or color may be set as well, provided <EM>UseModifier</EM> is set up properly:

<P>
<PRE>    &lt;INPUT TYPE=hidden NAME=mv_order_size VALUE=&quot;L&quot;&gt;
</PRE>
<P>
If the order is coming from a generated flypage, loop list, or search
results page, you can get a canned select box from the 
<CODE>[item-accessories size]</CODE> or <CODE>[item-accessories size]</CODE> tag. See
<EM>Item Attributes</EM>.

<P>
<HR>


code: 12.04
section: THE_ORDER_PROCESS
type: item
title: Order Groups

<A NAME="Order_Groups">Order Groups</A></H2>
<P>
MiniVend 3.06 allows you to group items together, making a master item and
sub-items. This can be used to delete accessories or options when the
master item is deleted. In its simplest form, you order just one master
item and all subsequent items are sub-items.

<P>
<PRE>    &lt;FORM ACTION=&quot;[process-target]&quot; METHOD=POST&gt;
    &lt;INPUT TYPE=hidden NAME=mv_todo ACTION=refresh&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_group VALUE=&quot;1&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_item VALUE=&quot;00-0011&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_item VALUE=&quot;00-0011a&quot;&gt;
    &lt;INPUT TYPE=submit VALUE=&quot;Order the Mona Lisa with frame&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
If you wish to stack more than one master item, then you must define
mv_order_group for <STRONG>all</STRONG> items, with either a 1 value (master) or 0 value (sub-item). 
<FONT SIZE=-1>A</FONT> master owns all subsequent sub-items until the next
master is defined.

<P>
<PRE>    &lt;FORM ACTION=&quot;[process-target]&quot; METHOD=POST&gt;
    &lt;INPUT TYPE=hidden NAME=mv_todo ACTION=refresh&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_group VALUE=&quot;1&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_item VALUE=&quot;00-0011&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_group VALUE=&quot;0&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_item VALUE=&quot;00-0011a&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_group VALUE=&quot;1&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_item VALUE=&quot;19-202&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_group VALUE=&quot;0&quot;&gt;
    &lt;INPUT TYPE=hidden NAME=mv_order_item VALUE=&quot;99-102&quot;&gt;
    &lt;INPUT TYPE=submit VALUE=&quot;Order items&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
When the master item <CODE>00-0011</CODE> is deleted from the basket,
<CODE>00-0011a</CODE> will be deleted as well. And when 19-202 is deleted, then 99-102 will be
deleted from the basket.

<P>

<FONT SIZE=-1>NOTE:</FONT> You cannot use checkboxes for this type of
thing, for they do not pass a value when unchecked. Use radio groups or
select/drop-down buttons.

<P>
The attributes <CODE>mv_mi</CODE> and <CODE>mv_si</CODE> are set to the group and sub-item status of each item. The group, contained
in the attribute <CODE>mv_mi</CODE>, is a meaningless yet unique integer. All items in a group will have the
same value of <CODE>mv_mi</CODE>. The attribute <CODE>mv_si</CODE> is set to 0 if the item is a master item, and 1 if it is a sub-item.

<P>
<HR>


code: 12.05
section: THE_ORDER_PROCESS
type: item
title: Basket display

<A NAME="Basket_display">Basket display</A></H2>
<P>
The basket <CODE>page(s)</CODE> are where the items are tracked and
adjusted by the customer. It is possible to have an unlimited number of
basket pages. It is also possible to have multiple shopping carts, as in
buy or sell. This allows a basket/checkout type of ordering scheme, with
custom order pages for items which have many accessories.

<P>
The name of the page to display can be configured in several ways:

<OL>
<LI>

Set the SpecialPage <A HREF="#item_order">order</A> to the page to display when an item is ordered.

<P><LI>

Set the FrameOrderPage directive to the page to use when frames are
enabled. This overrides option 1.

<P><LI>

Use the <CODE>[order item cart/page] Order it! [/order]</CODE> form of order tag to specify an arbitrary order page for an item.

<P><LI>

If already on an order page, set the mv_checkout, mv_orderpage,
mv_nextpage, mv_successpage, or mv_failpage variables.

<P></OL>
<P>
The variables mentioned above modify the page display in the following
ways:

<DL>
<DT><STRONG><A NAME="item_mv_cartname">mv_cartname</A></STRONG><DD>

The shopping cart (default is main) to be used for this order operation.

<P><DT><STRONG><A NAME="item_mv_checkout">mv_checkout</A></STRONG><DD>

Page to be displayed when checkout is called from the form

<P><DT><STRONG><A NAME="item_mv_failpage">mv_failpage</A></STRONG><DD>

Page to be displayed on a failed order check (see <EM>Advanced Multi-level Order Pages</EM>)

<P><DT><STRONG><A NAME="item_mv_nextpage">mv_nextpage</A></STRONG><DD>

Page to display on a return operation.

<P><DT><STRONG><A NAME="item_mv_orderpage">mv_orderpage</A></STRONG><DD>

Page to be displayed on a refresh.

<P><DT><STRONG><A NAME="item_mv_successpage">mv_successpage</A></STRONG><DD>

Page to be displayed on a successful order check (see <EM>Advanced Multi-level Order Pages</EM>).

<P><DT><STRONG><A NAME="item_mv_order_profile">mv_order_profile</A></STRONG><DD>

Order profile to be used if the form action is <EM>submit</EM>
(see <EM>Advanced Multi-level Order Pages</EM>).

<P></DL>
<P>
<HR>


code: 12.06
section: THE_ORDER_PROCESS
type: item
title: Multiple Shopping Carts

<A NAME="Multiple_Shopping_Carts">Multiple Shopping Carts</A></H2>
<P>
You can maintain multiple shopping carts with MiniVend (2.02 and above). One shopping cart -- main, by name -- is defined when the user session starts. If the user orders item 
<FONT SIZE=-1>M1212</FONT> with the following tag:


<P>
<PRE>    [order M1212 layaway] Order this item! [/order]
</PRE>
<P>
the order will be placed in the cart named <EM>layaway</EM>. However, by default you won't see what you want! That is because the
default shopping basket page won't display the cart you are thinking it
will -- it will show the main cart. So copy the default cart
(pages/ord/basket.html in the demos) to a new file, insert a <CODE>[cart layaway]</CODE> tag, and submit it as a MiniVend page name addendum to the cart name:

<P>
<PRE>    [order M1212 layaway/lay_basket] Order this item! [/order]
</PRE>
<P>
Now the contents of the <EM>layaway</EM> cart will be displayed. If you need to display a different price, you will
have to emulate the <CODE>[subtotal]</CODE>,
<CODE>[item-price]</CODE>, <CODE>[item-subtotal]</CODE>, etc. fields with <CODE>[item-list]</CODE>, <CODE>[calc]</CODE>, and <CODE>[currency]</CODE> tags. This snippet emulates the item-price tag for a different price field <EM>layaway-price</EM>:

<P>
<PRE>    [currency] [item-field layaway-price] [/currency]
</PRE>
<P>
An item subtotal:

<P>
<PRE>    [currency]
        [calc]
            [item-field layaway-price] * [item-quantity]
        [/calc]
    [/currency]
</PRE>
<P>

<FONT SIZE=-1>A</FONT> cart subtotal, using the item-list tag:

<P>
<PRE>    [currency]
        [calc]
            [item-list layaway]
            ([item-field layaway-price] * [item-quantity]) +
            [/item-list]
            0
        [/calc]
    [/currency]
</PRE>
<P>
The zero is needed because of the trailing plus sign left by the iterative <CODE>[item-list]</CODE> tag.

<P>
Shipping and the <CODE>[nitems]</CODE> tag will still work properly with a different price.

<P>
You can also order items from a form, using the <CODE>mv_order_item</CODE>,
<A HREF="#item_mv_cartname">mv_cartname</A>, and optional <CODE>mv_order_quantity</CODE> variables.

<P>
<PRE> &lt;FORM METHOD=POST ACTION=&quot;[process-order]&quot;&gt;
 &lt;input type=checkbox name=&quot;mv_order_item&quot; value=&quot;M3243&quot;&gt; Item M3243
 &lt;input name=&quot;mv_order_quantity&quot; value=&quot;1&quot;&gt; Quantity
 &lt;input type=hidden name=&quot;mv_cartname&quot; value=&quot;layaway&quot;&gt;
 &lt;input type=hidden name=&quot;mv_doit&quot; value=&quot;refresh&quot;&gt;
 &lt;input type=submit name=&quot;mv_junk&quot; value=&quot;Place on Layaway Now!&quot;&gt;
 &lt;/FORM&gt;
</PRE>
<P>
<HR>


code: 12.07
section: THE_ORDER_PROCESS
type: item
title: Advanced Multi-level Order Pages

<A NAME="Advanced_Multi_level_Order_Pages">Advanced Multi-level Order Pages</A></H2>
<P>
An unlimited number of order checking profiles can be defined with the
<EM>OrderProfile</EM> directive, or by defining order profiles in scratch variables. This allows
a multi-level ordering process, with checking for format and validity at
every stage.

<P>
As of MiniVend 3.12, you can place a message after the format check
requirement.

<P>
Specifications take the form of an order page variable (like name or
address), followed by an equals sign and one of five check types:

<DL>
<DT><STRONG><A NAME="item_required">required</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> non-blank value is required

<P><DT><STRONG><A NAME="item_mandatory">mandatory</A></STRONG><DD>

Must be non-blank, and must have been specified on this form, not a saved
value from a previous form

<P><DT><STRONG><A NAME="item_phone">phone</A></STRONG><DD>

The field must look like a phone number, by a very loose specification
allowing numbers from all countries

<P><DT><STRONG><A NAME="item_phone_us">phone_us</A></STRONG><DD>

Must have 
<FONT SIZE=-1>US</FONT> phone number formatting, with area code

<P><DT><STRONG><A NAME="item_state">state</A></STRONG><DD>

Must be a 
<FONT SIZE=-1>US</FONT> state, including 
<FONT SIZE=-1>DC</FONT> and Puerto Rico.


<P><DT><STRONG><A NAME="item_province">province</A></STRONG><DD>

Must be a Canadian province or pre-1997 territory.

<P><DT><STRONG><A NAME="item_state_or_province">state_or_province</A></STRONG><DD>

Must be a 
<FONT SIZE=-1>US</FONT> state or Canadian province.

<P><DT><STRONG><A NAME="item_zip">zip</A></STRONG><DD>

Must have 
<FONT SIZE=-1>US</FONT> postal code formatting, with optional 
<FONT SIZE=-1>ZIP+4.</FONT> Also called by the alias
 <CODE>us_postcode</CODE>.

<P><DT><STRONG><A NAME="item_ca_postcode">ca_postcode</A></STRONG><DD>

Must have Canadian postal code formatting. Checks for a valid first letter.

<P><DT><STRONG><A NAME="item_postcode">postcode</A></STRONG><DD>

Must have Canadian or 
<FONT SIZE=-1>US</FONT> postal code formatting.

<P><DT><STRONG><A NAME="item_true">true</A></STRONG><DD>

Field begins with <STRONG>y</STRONG>, <STRONG>1</STRONG>, or <STRONG>t</STRONG> (Yes, 1, or True) - not case sensitive

<P><DT><STRONG><A NAME="item_false">false</A></STRONG><DD>

Field begins with <STRONG>n</STRONG>, <STRONG>0</STRONG>, or <STRONG>f</STRONG> (No, 0, or False) - not case sensitive

<P><DT><STRONG><A NAME="item_email">email</A></STRONG><DD>

Rudimentary email address check, must have an '@' sign, a name, and a
minimal domain

<P></DL>
<P>
Also, there are four pragmas that can be used to change behavior:

<DL>
<DT><STRONG><A NAME="item__amp_fatal">&amp;amp;fatal</A></STRONG><DD>

Set to '&amp;fatal=yes' if an error should generate the error page.

<P><DT><STRONG><A NAME="item__amp_final">&amp;amp;final</A></STRONG><DD>

Set to '&amp;final=yes' if a successful check should cause the order to be
placed.

<P><DT><STRONG><A NAME="item__amp_set">&amp;amp;set</A></STRONG><DD>

Set a user session variable to a value, i.e. <CODE>&amp;set=mv_email [value email]</CODE>. This is usually placed at the end after a <CODE>&amp;fatal</CODE> pragma
would have caused the process to stop if there was an error -- can also be
used to determine pass/fail based on a derived value, as it will cause
failure if it evaluates to zero or a blank value.

<P><DT><STRONG><A NAME="item__amp_return">&amp;amp;return</A></STRONG><DD>

Causes profile processing to terminate with either a success or failure
depending on what follows. If it is non-blank and non-zero, the profile
succeeds. 

<P>
<PRE>    # Success :)
    &amp;return 1
</PRE>
<P>
<PRE>    # Failure :\
    &amp;return 0
</PRE>
<P>
Will ignore the <CODE>&amp;fatal</CODE> pragma, but <CODE>&amp;final</CODE>
is still in effect if set.

<P></DL>
<P>
As an added measure of control, the specification is evaluated for the
special MiniVend tags to provide conditional setting of order parameters.
With the <CODE>[perl]</CODE>  <CODE>[/perl]</CODE> capability, quite complex checks can be done. Also, the name of the page to
be displayed on an error can be set in the <A HREF="#item_mv_failpage">mv_failpage</A> variable.

<P>
The following file specifies a simple check of formatted parameters:

<P>
<PRE> name=required You must give us your name.
 address=required Oops! No address.
 city=required
 state=required
 zip=required
 email=required
 phone_day=phone_us XXX-XXX-XXXX phone-number for US or Canada
 &amp;fatal=yes
 email=email Email address missing the domain?
 &amp;set=mv_email [value email]
 &amp;set=mv_successpage ord/shipping
</PRE>
<P>
The profile above only performs the <CODE>&amp;set</CODE> directives if all
of the previous checks have passed -- the &amp;fatal=yes will stop
processing after the check of the email address if any of the previous
checks failed.

<P>
If you want to place multiple order profiles in the same file, separate them with 
<FONT SIZE=-1>__END__,</FONT> which must be on a line by itself.


<P>
<HR>


code: 12.08
section: THE_ORDER_PROCESS
type: item
title: Simple Order Report File

<A NAME="Simple_Order_Report_File">Simple Order Report File</A></H2>
<P>
The simple order report file, ``report'', defines the layout of the order
report which gets mailed on the completion of the order. For example,

<P>
<PRE>              Order Date: $date
</PRE>
<P>
<PRE>                    Name: $name
           Email address: $email
</PRE>
<P>
<PRE>        Shipping address: $addr
        Town, State, Zip: $town, $state $zip
                 Country: $country
</PRE>
<P>
Any input field from the order page can be included using the dollar sign
notation.

<P>
To prevent a value from being included in the order report, just add it to
the <STRONG>ReportIgnore</STRONG> configuration directive. 

<P>
MiniVend defines some values for use in the search form -- they begin with <CODE>mv_</CODE> and are automatically ignored.

<P>
<HR>


code: 12.09
section: THE_ORDER_PROCESS
type: item
title: Fully-configurable Order Reports

<A NAME="Fully_configurable_Order_Reports">Fully-configurable Order Reports</A></H2>
<P>
You can specify a fully-configurable order report by setting the hidden
field ``mv_order_report'' to a legal MiniVend page. This page will be
interpolated with all MiniVend tags before sending by email. The order
number as set by backend ordering is in the variable mv_order_number, and
available for your use.

<P>
You could if you wish include 
<FONT SIZE=-1>HTML</FONT> in the file, which will be interpreted by many mailers, but you can choose to use standard 
<FONT SIZE=-1>ASCII</FONT> format. An example report is provided in the demo file &lt;pages/ord/report.html&gt;.


<P>
<HR>


code: 12.10
section: THE_ORDER_PROCESS
type: item
title: Customer Input Fields

<A NAME="Customer_Input_Fields">Customer Input Fields</A></H2>
<P>
On the order (or shopping basket) page, by default order.html, you will
have a number of input fields allowing the customer to enter information
such as their name and address. You can add more fields simply by putting
more input elements on the order.html page, and the information will
automatically be included in the order report. Input elements should be
written in this way:

<P>
<PRE>    &lt;input type=&quot;text&quot; name=&quot;town&quot; value=&quot;[value town]&quot; size=30&gt;
</PRE>
<P>
Choose a name for this input field such as ``email'' for an email address.
Set the name attribute to the name you have chosen.

<P>
The value attribute specifies the default value to give the field when the
page is displayed. Because the customer may enter information on the order
page, return to browsing, and come back to the order page, you want the
default value to be what was entered the first time. This is done with the <CODE>[value var]</CODE> element, which returns the last value of an input field. Thus,

<P>
<PRE>    value=&quot;[value name]&quot;
</PRE>
<P>
will evaluate to the name entered on the previous order screen, such as:

<P>
<PRE>       value=&quot;Jane Smith&quot;
</PRE>
<P>
which will be displayed by the browser.

<P>
The size attributes specifies how many characters wide the input field
should be on the browser. You do not need to set this to fit the longest
possible value since the browser will scroll the field, but you should set
it large enough to be comfortable for the customer.

<P>
<HR>


code: 12.10
section: THE_ORDER_PROCESS
type: item
title: Order Receipts

<A NAME="Order_Receipts">Order Receipts</A></H2>
<P>
If you specify a legal MiniVend page name in the ReceiptPage directive, the
user will be sent this page instead of the default ``confirmation'' file.
The file can of course be configured with all MiniVend tags, and will be
interpolated for the ordered items before they are deleted from the user
record. If you want to have a different receipt for different carts, set
the <CODE>mv_order_receipt</CODE> variable in the form.

<P>
<HR>


code: 12.11
section: THE_ORDER_PROCESS
type: item
title: The Order Counter

<A NAME="The_Order_Counter">The Order Counter</A></H2>
<P>
An order counter can be enabled if the <EM>OrderCounter</EM> directive is set to a file name. An incrementing count of all orders will
be kept and assigned as orders are placed. By default, the number starts at
0, but you can edit the file and change the default starting number at any
time.

<P>
This capability is made possible by the File::CounterFile module, available
(as a part of the fine libwww modules) at the same place you got MiniVend.
It is included with the distribution.

<P>
<HR>


code: 13.00
section: THE_ORDER_PROCESS
type: overview
title: THE ORDER PROCESS

<A NAME="THE_ORDER_PROCESS">THE ORDER PROCESS</A></H1>
<P>
MiniVend has a completely flexible order basket and checkout scheme. The <A HREF="#item_simple">simple</A> demo presents a common use of this process, in the directory pages/ord --
the files are:

<P>
<PRE>    basket.html      The order basket displayed by default
    checkout.html    The form where the customer enters their billing
                     and shipping info
    receipt.html     The receipt displayed to the customer
    report.html      The order report mailed to you
</PRE>
<P>
It is not strictly necessary to display an order basket when an item is
ordered. If you specify a different page to be displayed that is fine, but
most customers will be confused if you don't give them an indication that
the order operation has succeeded.

<P>
Any order basket is an 
<FONT SIZE=-1>HTML</FONT> <CODE>FORM</CODE>. It will have a number of variables on it. At the minimum it must have an <CODE>[item-list]</CODE> to loop through the items, and the <CODE>quantity</CODE> of each item must be set in some place on that form. Any valid MiniVend
tags may be used on the page, and you may use multiple item lists if
necessary.

<P>
<HR>


code: 13.02
section: PRODUCT_PRICING
type: item
title: Simple pricing

<A NAME="Simple_pricing">Simple pricing</A></H2>
<P>
The simplest method is flat pricing based on a fixed value in the <A HREF="#item_products">products</A> database. If you put that price in a field named
<CODE>price</CODE>, you don't need to do more. If you want to change pricing based on
quantity, size, color or other factors read on.

<P>
<HR>


code: 13.03
section: PRODUCT_PRICING
type: item
title: Price Maintenance with CommonAdjust

<A NAME="Price_Maintenance_with_CommonAdj">Price Maintenance with CommonAdjust</A></H2>
<P>
As of MiniVend 3.11, a flexible chained pricing scheme is available when
the <EM>CommonAdjust</EM> directive is set.

<P>

<FONT SIZE=-1>NOTE:</FONT> For compatibility with older carts, if both
PriceAdjustment and CommonAdjust are set, and CommonAdjust contains a valid
database identifier, the CommonAdjust value is used to set pricing
adjustments based on item attributes. This is not discussed further in this
section; all items below assume <EM>PriceAdjustment</EM> is not in use.

<P>
We talk below about a <EM>CommonAdjust string</EM>; it will be defined in due time.

<P>

<FONT SIZE=-1>A</FONT> few rules about CommonAdjust, all assuming the <EM>PriceField</EM> directive is set to <CODE>price</CODE>:

<OL>
<LI>

If <CODE>CommonAdjust</CODE> is set to any value, a valid <EM>CommonAdjust string</EM> or not, extended price adjustments are enabled. It may also hold the
default pricing scheme.

<P><LI>

The <CODE>price</CODE> field may also hold a <EM>CommonAdjust string</EM>. It takes precedence over the default.

<P><LI>

If the value of the <CODE>CommonAdjust</CODE> directive is set to a CommonAdjust string, and the <CODE>price</CODE> field is empty or specifically <EM>0</EM>, then it will be used to set the price of the items.

<P><LI>

If PriceBreaks is in use, it's price will take precedence over the value of <CODE>CommonAdjust</CODE>, though it may also contain a CommonAdjust string.

<P><LI>

If no CommonAdjust strings are found, then the price will be 0, subject to
any later application of discounts.

<P><LI>

If another CommonAdjust string is found as the result of an operation, it
will be re-parsed and the result applied. Chaining is retained; a fallback
may be passed and will take effect.

<P></OL>
<P>
Prices may be adjusted in several ways, and the individual actions are
referred to below as <EM>atoms</EM>. Price atoms they may be <EM>final</EM>,
<EM>chained</EM>, or <EM>fallback</EM>. 
<FONT SIZE=-1>A</FONT> final price atom is always applied if it does not evaluate to zero. 
<FONT SIZE=-1>A</FONT> chained price atom is subject to further adjustment. 
<FONT SIZE=-1>A</FONT> fallback price atom is skipped if a previous chained price was not zero.


<P>
Atoms are separated by whitespace, and may be quoted (although there should not normally be whitespace in a setting). 
<FONT SIZE=-1>A</FONT> chained item ends with a comma. 
<FONT SIZE=-1>A</FONT> fallback item has a leading semi-colon. Final atoms have no comma appended or semi-colon prepended.


<P>

<FONT SIZE=-1>A</FONT> <EM>settor</EM> is the means by which the price is set. There are There are eight different
types of price settors. All settors can then yield another CommonAdjust
string. 

<P>
It is quite possible to create endless loops, so the maximum number of
initial CommonAdjust strings is set to 16, and there may be only 20
iterations before the price will return zero on an error.

<P>
<STRONG>NOTE</STRONG>: Common needs are easily shown but not so easily explained; skip to the
examples if the reference below if your vision starts to blur when reading
the next section. 8-)

<P>

<FONT SIZE=-1>USAGE:</FONT> Optional items below have asterisks appended.
The asterisk should not be used in the actual string. Optional <STRONG>base</STRONG> or <STRONG>table</STRONG> always defaults to the active <A HREF="#item_products">products</A> database table. The optional <STRONG>key</STRONG>
defaults to the item code except in a special case for the attribute-based
lookup. The <STRONG>field</STRONG> name is not optional except in the case of an attribute lookup.

<DL>
<DT><STRONG><A NAME="item_N">N.NN or -N.NN</A></STRONG><DD>

where 
<FONT SIZE=-1>N</FONT> is a digit. 
<FONT SIZE=-1>A</FONT> number which is applied directly; for instance 10 will yield a price of 10. May be a positive or negative number.


<P><DT><STRONG><A NAME="item_N">N.NN%</A></STRONG><DD>

where 
<FONT SIZE=-1>N</FONT> is a digit. 
<FONT SIZE=-1>A</FONT> number which is applied as a percentage of the
 <EM>current</EM> price value. May be a positive or negative number. For example, if the
price is 10 and -8% is applied, the next price value will be 9.20.

<P><DT><STRONG><A NAME="item_table">table*:column:key*</A></STRONG><DD>

Causes a straight lookup in a database table. The optional <STRONG>table</STRONG> 
defaults to the main products database table for the item (subject of
course to multiple product files). The <STRONG>column</STRONG> must always be present. The optional <STRONG>key</STRONG> defaults to the item code except in a special case for the attribute-based
lookup. The return value is then re-parsed as another price settor.

<P><DT><STRONG><A NAME="item_table">table*:col1..col5,col10:key*</A></STRONG><DD>

Causes a quantity lookup in database table <STRONG>table</STRONG> (which defaults to the products database), with a set of comma-separated
fields, looked up by the optional <STRONG>key</STRONG>. (Key defaults to the item code, of course). If ranges are specified with
.., each column in the sequence will be used; Therefore

<P>
<PRE>    pricing:p1,p2,p3,p4,p5,p10:
</PRE>
<P>
is the same as

<P>
<PRE>    pricing:p1..p5,p10:
</PRE>
<P>
Leading non-digits are stripped, and the item quantity is compared with the
numerical portion of the column name. The price is set to the value of the
database column (numeric portion) that is at least equal to it but doesn't
yet reach the next break.

<P>

<FONT SIZE=-1>WARNING:</FONT> If the field at the appropriate quantity
level is blank, a zero cost will be returned from the atom. It is important
to have all columns populated.

<P><DT><STRONG><A NAME="item__attribute_table_column_key_">==attribute:table*:column*:key*</A></STRONG><DD>

Does an attribute-based adjustment. The attribute is looked up in the
database <STRONG>table</STRONG>, with the optional <STRONG>column</STRONG> defaulting to the same name as the <EM>value</EM> of the <STRONG>attribute</STRONG>. If the column is not left blank, the <EM>key</EM> is set to the <EM>value</EM> of the <STRONG>attribute</STRONG> if blank.

<P><DT><STRONG><A NAME="item__amp_">&amp;amp; CODE</A></STRONG><DD>

The leading <CODE>&amp;</CODE> sign is stripped and the code is passed to the equivalent of a <CODE>[calc]</CODE> tag. No MiniVend tags can be used, but the <CODE>&amp;tag_data</CODE>
routine is available, the current value of the price and quantity are
available as <A HREF="#item__s">$s</A>, and the current item (code, quantity, price, and any attributes) are
available as <CODE>$item</CODE>, all forced to the package Vend::Interpolate. That means that in a
UserTag:

<P>
<PRE>  $Vend::Interpolate::item          is the current item
  $Vend::Interpolate::item-&gt;{code}  gives key for current item
  $Vend::Interpolate::item-&gt;{size}  gives size for current item (if there)
  $Vend::Interpolate::item-&gt;{mv_ib} gives database ordered from
</PRE>
<P><DT><STRONG><A NAME="item__valid">[valid minivend tags]</A></STRONG><DD>

If the settor begins with a square bracket (<CODE>[</CODE>) or underscore, it is parsed for MiniVend tags with variable substitution
(but no Locale substitution). You may define a price in a <EM>Variable</EM> in this fashion. The string is re-submitted as an atom, so it may yield yet
another settor.

<P><DT><STRONG><A NAME="item__">$</A></STRONG><DD>

Tells MiniVend to look in the <CODE>mv_price</CODE> attribute of the shopping cart, and apply that price as the final price, if
it exists. The attribute must be a numerical value.

<P><DT><STRONG><A NAME="item__word">&gt;&gt;word</A></STRONG><DD>

Tells the routine to return <A HREF="#item_word">word</A> directly as the result. This is not useful in pricing, as it will evaluate
to zero. But when CommonAdjust is used for shipping, it is a way of
re-directing shipping modes.

<P><DT><STRONG><A NAME="item_word">word</A></STRONG><DD>

The value of <A HREF="#item_word">word</A>, which must not match any of the other settors, is available as a key for
the next lookup (only). If the next settor is a database lookup, and it
contains a dollar sign (<CODE>$</CODE>) the <A HREF="#item_word">word</A>
will be substituted; i.e. <CODE>table:column:$</CODE> becomes <CODE>table:column:word</CODE>.

<P><DT><STRONG><A NAME="item__">( settor )</A></STRONG><DD>

The value returned by <CODE>settor</CODE> will be used as a key for the next lookup, as above.

<P></DL>
<P>
<HR>


code: 13.04
section: PRODUCT_PRICING
type: item
title: CommonAdjust Examples

<A NAME="CommonAdjust_Examples">CommonAdjust Examples</A></H2>
<P>
Most examples below use an outboard database table named <STRONG>pricing</STRONG>, but any valid table including the <STRONG>products</STRONG> table can be used. We will refer to this <STRONG>pricing</STRONG> table:

<P>
<PRE>  code    common  q1     q5     q10    XL    S      red
  99-102          10     9      8      1     -0.50  0.75
  00-343                               2
  red      0.75
</PRE>
<P>
The simplest case is a straight lookup on an attribute; <EM>size</EM> in this case. 

<P>
<PRE>  10.00, ==size:pricing
</PRE>
<P>
With this value in the <CODE>price</CODE> field, a base price of 10.00 will be adjusted with the value of the <EM>size</EM> attribute. If size for the item 99-102 is set to <CODE>XL</CODE> then 1.00 will be added for a total price of 11.00; if it is <CODE>S</CODE> then .50 will be subtracted for a total price of 9.50; for any other value
of <EM>size</EM> no further adjustment would be made. 00-343 would be adjusted up 2.00 only
for <EM>XL</EM>.

<P>
<PRE>  10.00, ==size:pricing, ==color:pricing
</PRE>
<P>
This is the same as above, except both size and color are adjusted for. 
<FONT SIZE=-1>A</FONT> color value of red for item code 99-102 would add
0.75 to the price. For 00-343 it would have no effect.

<P>
<PRE>  10.00, ==size:pricing, ==color:pricing:common
</PRE>
<P>
Here price is set based on a common column, keyed by the value of the color
attribute. Any item with a color value of red would have 0.75 added to the
base price.

<P>
<PRE>  pricing:q1,q5,q10:, ;10.00, ==size:pricing, ==color:pricing:common
</PRE>
<P>
Here is a quantity price lookup, with a fallback price setting. If there is
a valid price found at the quantity of 1, 5, or 10, depending on item
quantity, then it will be used. The fallback of 10.00 only applies if no
non-zero/non-blank price was found at the quantity lookup. In either case,
size/color adjustment is applied.

<P>
<PRE>  pricing:q1,q5,q10:, ;10.00 ==size:pricing, ==color:pricing:common
</PRE>
<P>
Removing the comma from the end of the fallback string stops color/size
lookup if it reaches that point. If a quantity price was found, then size
and color are chained.

<P>
<PRE>  pricing:q1,q5,q10:, ;products:list_price, ==size:pricing, ==color:pricing
</PRE>
<P>
The value of the database column <CODE>list_price</CODE> is used as a fallback instead of the fixed 10.00 value. The above value
might be a nice one to use as the default for a typical retail catalog that
has items with colors and sizes.
 

<P>
<HR>


code: 13.05
section: PRODUCT_PRICING
type: item
title: PriceBreaks, discounts, and PriceAdjustment

<A NAME="PriceBreaks_discounts_and_Pric">PriceBreaks, discounts, and PriceAdjustment</A></H2>
<P>
There are several ways that MiniVend can modify the price of a product
during normal catalog operation. Several of them require that the <EM>pricing.asc</EM>
file be present, and that you define a pricing database. You do that by
placing the following directive in <EM>catalog.cfg</EM>:

<P>
<PRE>  Database  pricing pricing.asc 1
</PRE>
<P>

<FONT SIZE=-1>NOTE:</FONT> PriceAdjustment is slightly deprecated by
CommonAdjust, but will remain in use at least through the end of Version 3
of MiniVend.

<P>
Configurable directives and tags with regard to pricing:

<UL>
<LI>

Quantity price breaks are configured by means of the <EM>PriceBreaks</EM> and
<EM>MixMatch</EM> directives. They require a field named specifically <CODE>price</CODE>
in the pricing database. The <STRONG>price</STRONG> field contains a space-separated list of prices that correspond to the
quantity levels defined in the
<EM>PriceBreaks</EM> directive. If quantity is to be applied to all items in the shopping cart
(as opposed to quantity of just that item) then the
<EM>MixMatch</EM> directive should be set to <STRONG>Yes</STRONG>.

<P><LI>

Individual line-item prices can be adjusted according to the value of their
attributes. See <EM>PriceAdjustment</EM> and <EM>CommonAdjust</EM>. The pricing database <STRONG>must</STRONG> be defined unless you define the <EM>CommonAdjust</EM>
behavior.

<P><LI>

Product discounts for individual products, specific product codes, all
products, or the entire order can be configured with the <A HREF="#item__discount_">[discount ...]</A>
tag. Discounts are applied on a per-user basis -- you can gate the discount
based on membership in a club or other arbitrary means. See
<EM>Product Discounts</EM>.

<P></UL>
<P>
For example, if you decided to adjust the price of T-shirt part number
99-102 up 1.00 when the size is extra large and down 1.00 when the size is
small, you would have the following directives defined in
&lt;catalog.cfg&gt;:

<P>
<PRE>  Database          pricing pricing.asc 1
  UseModifier       size
  PriceAdjustment   size
</PRE>
<P>
To enable the automatic modifier handling of MiniVend 3.0, you would define
a size field in products.asc:

<P>
<PRE>  code    description   price    size
  99-102  T-Shirt       10.00    S=Small, M=Medium, L=Large*, XL=Extra Large
</PRE>
<P>
You would place the proper tag within your <CODE>[item-list]</CODE> on the shopping-basket or order page:

<P>
<PRE>    [item-accessories size]
</PRE>
<P>
In the pricing.asc database source, you would need:

<P>
<PRE>  code      S       XL
  99-102    -1.00   1.00
</PRE>
<P>
As of MiniVend 3.06, if you want to assign a price based on the option,
precede the number with an equals sign:

<P>
<PRE>  code    S       M       L       XL
  99-102  =9.00   =10     =10     =11
</PRE>
<P>

<FONT SIZE=-1>IMPORTANT</FONT> 
<FONT SIZE=-1>NOTE:</FONT> Price adjustments occur 
<FONT SIZE=-1>AFTER</FONT> quantity price breaks, so the above would negate anything set with the
 <EM>PriceBreaks</EM> directive/option.

<P>
Numbers that begin with an equals sign (<CODE>=</CODE>) are used as absolute prices and are <EM>interpolated for MiniVend tags first</EM>, so you can use subroutines to set the price. To facilite coordination
with the subroutine, the session variables <CODE>item_code</CODE> and <CODE>item_quantity</CODE> are set to the code and quantity of the item being evaluated. They would be
accessed in a global subroutine with <CODE>$Vend::Session-</CODE>&gt;<CODE>{item_code}</CODE>
and <CODE>$Vend::Session-</CODE>&gt;<CODE>{item_quantity}</CODE>.

<P>
The pricing information must always come from a database because of
security.

<P>
<HR>


code: 13.06
section: PRODUCT_PRICING
type: item
title: Item Attributes

<A NAME="Item_Attributes">Item Attributes</A></H2>
<P>
MiniVend allows item attributes to be set for each ordered item. This
allows a size, color, or other modifier to be attached to a common part
number. If multiple attributes are set, then they should be separated by
commas. Previous attribute values can be saved by means of a hidden field
on a form, and multiple attributes for each item can be <EM>stacked</EM> on top of each other.

<P>
The configuration file directive <EM>UseModifier</EM> is used to set the name of the modifier or modifiers. For example

<P>
<PRE>    UseModifier        size,color
</PRE>
<P>
will attach both a size and color attribute to each item code that is
ordered.

<P>
<STRONG>IMPORTANT NOTE:</STRONG> You may not use the following names for attributes:

<P>
<PRE>    item  group  quantity  code  mv_ib  mv_mi  mv_si
</PRE>
<P>
You can also set it in scratch with the mv_UseModifier scratch variable -- <CODE>[set mv_UseModifier]size color[/set]</CODE> has the same effect as above. This allows multiple options to be set for
products. Whichever one is in effect at order time will be used. Be
careful, you cannot set it more than once on the same page. Setting the <CODE>mv_separate_items</CODE> or global directive <EM>SeparateItems</EM>
places each ordered item on a separate line, simplifying attribute
handling. The scratch setting for <CODE>mv_separate_items</CODE> has the same effect.

<P>
The modifier value is accessed in the <CODE>[item-list]</CODE> loop with the
<CODE>[item-modifier attribute]</CODE> tag, and form input fields are placed with the
<CODE>[modifier-name attribute]</CODE> tag. This is similar to the way that quantity is handled, except that
attributes can be ``stacked'' by setting multiple values in an input form.

<P>
You cannot define a modifier name of <EM>code</EM> or <EM>quantity</EM>, as they are already used. You must be sure that no fields in your forms
have digits appended to their names if the variable is the same name as the
attribute name you select, as the <CODE>[modifier-name size]</CODE> variables will be placed in the user session as the form variables size0,
size1, size2, etc. 

<P>
You can use the <CODE>[loop arg=&quot;item item item&quot;]</CODE> list to reference multiple display or selection fields for modifiers (in
MiniVend 3.0, you can have it automatically generated --see below). The
modifier value can then be used to select data from an arbitrary database
for attribute selection and display.

<P>
Below is a fragment from a shopping basket display form which shows a
selectable size with ``sticky'' setting. Note that this would always be
contained within the <CODE>[item_list]</CODE>  <CODE>[/item-list]</CODE>
pair.

<P>
<PRE>    &lt;SELECT NAME=&quot;[modifier-name size]&quot;&gt;
    &lt;OPTION  [selected [modifier-name size] S]&gt; S
    &lt;OPTION  [selected [modifier-name size] M]&gt; M
    &lt;OPTION  [selected [modifier-name size] L]&gt; L
    &lt;OPTION [selected [modifier-name size] XL]&gt; XL
    &lt;/SELECT&gt;
</PRE>
<P>
It could just as easily be done with a radio button group combined with the <CODE>[checked ...]</CODE> tag.

<P>
MiniVend 3.0 will automatically generate the above select box when the <CODE>[accessories &lt;code</CODE> size]&gt; or <CODE>[item-accessories size]</CODE>
tags are called. They have the syntax:

<P>
<PRE>   [item_accessories attribute*, type*, field*, database*, name*, outboard*]
  
   [accessories code attribute*, type*, field*, database*, name*, outboard*]
</PRE>
<DL>
<DT><STRONG><A NAME="item_code">code</A></STRONG><DD>

Not needed for item-accessories, this is the product code of the item to
reference. =item attribute

<P>
The item attribute as specified in the UseModifier configuration directive.
Typical are <A HREF="#item_size">size</A> or <CODE>color</CODE>.

<P><DT><STRONG><A NAME="item_type">type</A></STRONG><DD>

The action to be taken. One of:

<P>
<PRE>  select          Builds a dropdown &lt;SELECT&gt; menu for the attribute.
                  NOTE: This is the default.
 
  multiple        Builds a multiple dropdown &lt;SELECT&gt; menu for the
                  attribute.  The size is equal to the number of
                  option choices.
                   
  display         Shows the label text for *only the selected option*.
   
  show            Shows the option choices (no labels) for the option.
   
  radio           Builds a radio box group for the item, with spaces
                  separating the elements.
                   
  radio nbsp      Builds a radio box group for the item, with &amp;nbsp;
                  separating the elements.
                   
  radio left n    Builds a radio box group for the item, inside a
                  table, with the checkbox on the left side. If &quot;n&quot;
                  is present and is a digit from 2 to 9, it will align
                  the options in that many columns.
                   
  radio right n   Builds a radio box group for the item, inside a
                  table, with the checkbox on the right side. If &quot;n&quot;
                  is present and is a digit from 2 to 9, it will align
                  the options in that many columns.
</PRE>
<P>
<PRE>   
  check           Builds a checkbox group for the item, with spaces
                  separating the elements.
                   
  check nbsp      Builds a checkbox group for the item, with &amp;nbsp;
                  separating the elements.
                   
  check left n    Builds a checkbox group for the item, inside a
                  table, with the checkbox on the left side. If &quot;n&quot;
                  is present and is a digit from 2 to 9, it will align
                  the options in that many columns.
                   
  check right n   Builds a checkbox group for the item, inside a
                  table, with the checkbox on the right side. If &quot;n&quot;
                  is present and is a digit from 2 to 9, it will align
                  the options in that many columns.
</PRE>
<P>
The default is 'select', which builds an 
<FONT SIZE=-1>HTML</FONT> select form entry for the attribute. Also
recognized is 'multiple', which generates a multiple-selection drop down
list, 'show', which shows the list of possible attributes, and 'display',
which shows the label text for the selected option only.

<P><DT><STRONG><A NAME="item_field">field</A></STRONG><DD>

The database field name to be used to build the entry (usually a field in
the products database). Defaults to a field named the same as the
attribute.

<P><DT><STRONG><A NAME="item_database">database</A></STRONG><DD>

The database to find <STRONG>field</STRONG> in, defaults to the first products file where the item code is found.

<P><DT><STRONG>name</STRONG><DD>

Name of the form variable to use if a form is being built. Defaults to
mv_order_<STRONG>attribute</STRONG> -- i.e. if the attribute is <STRONG>size</STRONG>, the form variable will be named <STRONG>mv_order_size</STRONG>.

<P><DT><STRONG><A NAME="item_outboard">outboard</A></STRONG><DD>

If calling the item-accessories tag, and you wish to select from an
outboard database, you can pass the key to use to find the accessory data.

<P></DL>
<P>
When called with an attribute, the database is consulted and looks for a
comma-separated list of attribute options. They take the form:

<P>
<PRE>    name=Label Text, name=Label Text*
</PRE>
<P>
The label text is optional -- if none is given, the <STRONG>name</STRONG> will be used.

<P>
If an asterisk is the last character of the label text, the item is the
default selection. If no default is specified, the first will be the
default. An example:

<P>
<PRE>    [item_accessories color]
</PRE>
<P>
This will search the product database for a field named ``color''. If an
entry ``beige=Almond, gold=Harvest Gold, White*, green=Avocado'' is found,
a select box like this will be built:

<P>
<PRE>    &lt;SELECT NAME=&quot;mv_order_color&quot;&gt;
    &lt;OPTION VALUE=&quot;beige&quot;&gt;Almond
    &lt;OPTION VALUE=&quot;gold&quot;&gt;Harvest Gold
    &lt;OPTION SELECTED&gt;White
    &lt;OPTION VALUE=&quot;green&quot;&gt;Avocado
    &lt;/SELECT&gt;
</PRE>
<P>
In combination with the <CODE>mv_order_item</CODE> and <CODE>mv_order_quantity</CODE> variables this can be used to allow entry of an attribute at time of order.

<P>
If used in an item list, and the user has changed the value, the generated
select box will automatically retain the current value the user has
selected.

<P>
The value can then be displayed with <CODE>[item-modifier size]</CODE> on the order report, order receipt, or any other page containing an
<CODE>[item-list]</CODE>. 

<P>
<HR>


code: 13.07
section: PRODUCT_PRICING
type: item
title: Product Discounts

<A NAME="Product_Discounts">Product Discounts</A></H2>
<P>
Product discounts can be set upon display of any page. The discounts apply
only to the customer receiving them, and are of one of three types:

<P>
<PRE>    1. A discount for one particular item code (key is the item-code)
    2. A discount applying to all item codes (key is ALL_ITEMS)
    3. A discount for an individual line item (set the mv_disount attribute
       with embedded Perl)
    4. A discount applied after all items are totaled
       (key is ENTIRE_ORDER)
</PRE>
<P>
The discounts are specified via a formula. The formula is scanned for the
variables <CODE>$q</CODE> and $s, which are substituted for with the item
<EM>quantity</EM> and <EM>subtotal</EM> respectively. The variable <A HREF="#item__s">$s</A> is saved between
iterations, so the discounts are cumulative. In the case of the item and
all items discount, the formula must evaluate to a new subtotal for all
items <EM>of that code</EM> that are ordered. The discount for the entire order is applied to the
entire order, and would normally be a monetary amount to subtract or a flat
percentage discount.

<P>
Discounts are applied to the effective price of the product, including any
quantity discounts or price adjustments.

<P>
To apply a straight 20% discount to all items:

<P>
<PRE>    [discount ALL_ITEMS] $s * .8 [/discount]
</PRE>
<P>
or with named attributes:

<P>
<PRE>    [discount code=ALL_ITEMS] $s * .8 [/discount]
</PRE>
<P>
To take 25% off of only item 00-342:

<P>
<PRE>    [discount 00-342] $s * .75 [/discount]
</PRE>
<P>
To subtract $5.00 from the customer's order:

<P>
<PRE>    [discount ENTIRE_ORDER] $s - 5 [/discount]
</PRE>
<P>
To reset a discount, set it to the empty string: 

<P>
<PRE>    [discount ALL_ITEMS][/discount]
</PRE>
<P>
Perl code can be used to apply the discounts, and variables are saved
between items and are shared with the <CODE>[calc]</CODE> tag. This example gives 10% off if two items are ordered, with 5% more for
each additional up to a maximum of 30% discount:

<P>
<PRE>    [calc] 
        [item-list]
            $totalq{&quot;[item-code]&quot;} += [item-quantity];
        [/item-list]
            return '';
    [/calc]
    
    [item-list]
        [discount code=&quot;[item-code]&quot;]
            return ($s)       if $totalq{&quot;[item-code]&quot;} == 1;
            return ($s * .70) if $totalq{&quot;[item-code]&quot;} &gt; 6;
            return ($s * ( 1 - 0.05 * $totalq{&quot;[item-code]&quot;} ));
        [/discount]
    [/item-list]
</PRE>
<P>
Here is an example of a special discount for item code 00-343 which prices
the <EM>second</EM> one ordered at 1 cent:

<P>
<PRE>    [discount 00-343]
    return $s if $q == 1;
    my $p = $s/$q;
    my $t = ($q - 1) * $p;
    $t .= 0.01;
    return $t;
    [/discount]
</PRE>
<P>
If you want to display the discount amount, use the <CODE>[item-discount]</CODE> tag.

<P>
<PRE>    [item-list]
    Discount for [item-code]: [item-discount]
    [/item-list]
</PRE>
<P>
Finally, if you want to display the discounted subtotal, you need to use
the <CODE>[calc]</CODE> capability:

<P>
<PRE>    [item-list]
    Discounted subtotal for [item-code]: [currency][calc]
                                            [item-price] * [item-quantity]
                                            [/calc][/currency]
    [/item-list]
</PRE>
<P>
<HR>


code: 13.08
section: PRODUCT_PRICING
type: item
title: CyberCash 3.2

<A NAME="CyberCash_3_2">CyberCash 3.2</A></H2>
<P>
MiniVend 3.11 supports CyberCash 3 with the CCMckDirectLib3_2.pm
CCMckLib3_2.pm modules. If those modules are in place in your Perl include
path (you can use VendRoot/lib as a home if you wish), using CyberCash 3.2
is the same as with CyberCash 2 server except:

<OL>
<LI>

CyberCash 3 maintains a configuration file (merchant.conf) for each merchant. This needs to be set in the variable 
<FONT SIZE=-1>CYBER_CONFIGFILE</FONT> as in:


<P>
<PRE>  Variable CYBER_CONFIGFILE  /home/you/mck-lib/conf/merchant.conf
</PRE>
<P>
In all likelihood, this will make the values of 
<FONT SIZE=-1>CYBER_HOST,</FONT> 
<FONT SIZE=-1>CYBER_PORT,</FONT> and 
<FONT SIZE=-1>CYBER_SECRET</FONT> moot. It will not hurt anything if they remain set.


<P><LI>

The variables 
<FONT SIZE=-1>CYBER_VERSION</FONT> needs to be set to a numeric value of 3
or greater:

<P>
<PRE>  Variable CYBER_VERSION  3.2
</PRE>
<P>
This allows CyberCash 2 and 3 implementations to coexist on the same
machine.

<P></OL>
<P>
<HR>


code: 13.08
section: PRODUCT_PRICING
type: item
title: Sales Tax

<A NAME="Sales_Tax">Sales Tax</A></H2>
<P>
MiniVend allows calculation of sales tax on a straight percentage basis,
with certain items allowed to be tax-exempt. To enable this feature, the
directive <EM>SalesTax</EM> is initialized with the name of a field (or fields) on the order form.
Commonly, this is zipcode and/or state:

<P>
<PRE>    SalesTax    zip,state
</PRE>
<P>
This being done, MiniVend assumes the presence of a file <EM>salestax.asc</EM>, which contains a database with the percentages. Each line of 
<EM>salestax.asc</EM> should be a code (again, usually a five-digit zip or a two letter state)
followed by a tab, then a percentage. Example:

<P>
<PRE>    45056   .0525
    61821   .0725
    61801   .075
    IL      .0625
    OH      .0525
    VAT     .15
    WA      .08
</PRE>
<P>
Based on the user's entry of information in the order form, MiniVend will look up (for our example SalesTax directive) first the zip, then the state, and apply the percentage to the 
<FONT SIZE=-1>SUBTOTAL</FONT> of the order. The subtotal will include any taxable items, and will also include the shipping cost if the state/zip is included in the
 <EM>TaxShipping</EM> directive. It will add the percentage, then make that available with the <A HREF="#item__salestax_">[salestax]</A>
tag for display on the order form. If no match is found, the entry
'default' is applied -- that is normally 0, but can be anything.

<P>
If business is being done on a national basis, it is now common to have to collect sales tax for multiple states. If you are doing so, it is possible to subscribe to a service which issues regular updates of the sales tax percentages -- usually by quarterly or monthly subscription. Such a database should be easily converted to MiniVend format -- but some systems are rather convoluted, and it will be well to check and see if the program can export to a flat 
<FONT SIZE=-1>ASCII</FONT> file format based on zip code.


<P>
If some items are not taxable, then you must set up a field in your
database which indicates that. You then place the <STRONG>name</STRONG> of that field in the <EM>NonTaxableField</EM> directive. If the field for that item evaluates true on a yes-no basis
(i.e. is set to <A HREF="#item_yes">yes</A>, <CODE>y</CODE>, 1, or the like), sales tax will not be applied to the item. If it
evaluates false, it will be taxed.

<P>
If your state taxes shipping, use the <EM>TaxShipping</EM> directive. Utah and Nevada are known to tax shipping -- there may be
others.

<P>
If you want to set a fixed tax for all orders, as might occur for 
<FONT SIZE=-1>VAT</FONT> in some countries, just set the <EM>SalesTax</EM> directive to a value like
<CODE>tax_code</CODE>, and define a variable in the user session to reflect the proper entry in
the <CODE>salestax.asc</CODE> file. To set it to 15% with the above <CODE>salestax.asc</CODE> file, you would put in a form:

<P>
<PRE>    &lt;INPUT TYPE=hidden NAME=tax_code VALUE=&quot;VAT&quot;&gt;
</PRE>
<P>
or to do it without submitting a form:

<P>
<PRE>    [perl values] $Safe{'values'}{tax_code} = 'VAT'; return ''[/perl]
</PRE>
<P>
<HR>


code: 13.09
section: PRODUCT_PRICING
type: item
title: Using CyberCash

<A NAME="Using_CyberCash">Using CyberCash</A></H2>
<P>
MiniVend will directly interface with Perl libraries provided by CyberCash,
Inc. This allows direct card billing at the time the order is placed. If
using CyberCash 2, the module is called CCLib.pm and its version should be
1.3 or greater. If the library is found at startup, the message ``CyberCash
2 module found'' will be displayed.

<P>
MiniVend 3.11 and above support CyberCash 3; see the section below for
differences when using CyberCash 3.

<P>
To use CyberCash 2, you must first have a CyberCash Secure Merchant Payment Server 
<FONT SIZE=-1>(SMPS)</FONT> running on your system. It must be fully enabled, and should be tested 
<FONT SIZE=-1>OK</FONT> with the CyberCash test suite. This capability has been tested to work with SMPS-2.1.x in
 <CODE>mauthcapture</CODE> and <CODE>mauthonly</CODE>
modes. Any modes supported by CyberCash should work.

<P>
The special mode <CODE>minivend_test</CODE> will cause the transaction to complete successfully and the information
that would have been sent to the CyberCash server to be logged in the
catalog <CODE>error.log</CODE> file.

<P>
The CyberCash Perl library module must be available to MiniVend -- if you
cannot install it in the main Perl library then the Minivend software
directory <EM>lib/</EM> will suffice. If it is found at MiniVend startup, a message will be
displayed.

<P>
MiniVend only will charge CyberCash in the final phase of the order
process, i.e. at the time the receipt and order report are generated. The
full amount as shown by the <CODE>[total-cost]</CODE> tag will be billed -- if you need to do partial charges you will have to
manage multiple shopping carts.

<P>
The process of enabling CyberCash processing is something like this:

<OL>
<LI>

Turn off CreditCardAuto by setting the catalog directive to No. This would
normally be done right in catalog.cfg, but it also can be done in a
mv_click subroutine if you wish to mix transaction types:

<P>
<PRE>    &lt;INPUT TYPE=checkbox NAME=mv_click VALUE=CyberCash&gt; Use CyberCash
    [set CyberCash]
        [perl config]
            $Safe{config}-&gt;{CreditCardAuto} = 0;
            $Safe{config}-&gt;{CyberCash} = 1;
            return '';
        [/perl]
    mv_cyber_mode=mauthcapture
    [/set]
</PRE>
<P><LI>

Enable the CyberCash directive in catalog.cfg (or with the technique
above). Also set the catalog <EM>Variable</EM> value <STRONG>CYBER_SECRET</STRONG> to the ``secret'' for your payment server. If you are not using the default
values of <STRONG>localhost</STRONG> and <STRONG>8000</STRONG> for your server and port, set the Variables <STRONG>CYBER_HOST</STRONG> and <STRONG>CYBER_PORT</STRONG> as well. In the catalog.cfg file it would look like:

<P>
<PRE>    CreditCardAuto   No
    CyberCash        Yes
    Variable         CYBER_SECRET  first-natl
    Variable         CYBER_PORT    8000
    Variable         CYBER_HOST    localhost
</PRE>
<P><LI>

Set your final order screen to accept the user form fields
<A HREF="#item_mv_credit_card_number">mv_credit_card_number</A> (contains the actual card number),
<A HREF="#item_mv_credit_card_exp_month">mv_credit_card_exp_month</A> and <A HREF="#item_mv_credit_card_exp_year">mv_credit_card_exp_year</A> (the expiration date month and year), and the fields containing name,
address, city, state, and country. And <STRONG>you must</STRONG> define the form field <CODE>mv_cyber_mode</CODE>  <STRONG>on the submitting form</STRONG> to enable the processing.

<P>
The order mode must be final, either by omitting an order profile entirely
or by defining an order profile that contains &amp;final=yes.

<P></OL>
<P>
The fields containing name and address information should be the same as on
the standard MiniVend demo order pages:

<P>
<PRE>    b_name       Billing name      takes priority
    name         Shipping name     used if b_name empty
    b_address    Billing address   takes priority
    address      Shipping address  used if b_address empty
    b_city       Billing city      takes priority
    city         Shipping city     used if b_city empty
    b_state      Billing state     takes priority
    state        Shipping state    used if b_state empty
    b_country    Billing country   takes priority
    country      Shipping country  used if b_country empty
</PRE>
<P>
If you must use other values, they can be redefined in catalog.cfg with the <EM>Variable</EM>  <STRONG>CYBER_REMAP</STRONG> like so:

<P>
<PRE>    Variable CYBER_REMAP  name=my_name address=my_address
</PRE>
<P>
or like so:

<P>
<PRE>    Variable &lt;&lt;EOF
    CYBER_REMAP
    b_name   my_bname
    name     my_name
    address  processed_address
    city     parsed_city
    EOF
</PRE>
<P>
<STRONG>NOTE:</STRONG> As always when using the 
<FONT SIZE=-1>&lt;&lt;EOF</FONT> (here document) capability, the 
<FONT SIZE=-1>EOF</FONT> must be on a line by itself, with no leading or trailing white space. That includes carriage returns, Windows devotees. Upload in 
<FONT SIZE=-1>ASCII</FONT> mode!


<P>
If you have defined the directive <EM>EncryptProgram</EM> to be something containing the value <EM>pgp</EM>, then the <EM>CreditCardAuto</EM> method will be used to encrypt the mv_credit_card_number value before it is
wiped from memory. (Errors in that process will be silently ignored.) It
will never be written to the user session, at least by MiniVend itself, so
attempts to recall it on future forms will be in vain.

<P>
If the authorization fails, the special page <EM>failed</EM> will be displayed, and passed the CyberCash error message for display with
the <CODE>[subject]</CODE> tag. The order will not complete, i.e. the cart will still be intact and no
receipt or order report will be generated. The error itself is always
available as <CODE>[data session cybercash_error]</CODE>.

<P>
If successful, the receipt page will be displayed, the order report
emailed, and the cart will be emptied. If you wish to display the order-id
returned from CyberCash on the receipt, it is available in
<CODE>[data session cybercash_id]</CODE>. If the order is successful, but is detected as a ``success-duplicate'', <CODE>[data session cybercash_error]</CODE>
will contain the message returned from CyberCash.

<P>
<HR>


code: 14.00
section: PRODUCT_PRICING
type: overview
title: PRODUCT PRICING

<A NAME="PRODUCT_PRICING">PRODUCT PRICING</A></H1>
<P>
MiniVend maintains a price in its database for every product. The price
field is the one required field in the product database -- it is necessary
to build the price routines.

<P>
For speed, MiniVend builds the code that is used to determine a product's
price at catalog configuration time. If you choose to change a directive
that affects product pricing you must reconfigure the catalog.

<P>
<HR>


code: 15.00
section: SORTING
type: overview
title: SORTING

<A NAME="SORTING">SORTING</A></H1>
<P>
MiniVend has standard sorting options for sorting the search lists, loop
lists, and item lists based on the contents of database fields. In
addition, adds list slices for limiting the displayed entries based on a
start value and chunk size (or start and end value, from which a chunk size
is determined). All accept a standard format sort tag which must be
directly after the list call:

<P>
<PRE>    [loop 4 3 2 1]
    [sort -2 +2]
        [loop-code]
    [/loop]
 
    [search-list]
    [sort products:category:f]
        [item-price] [item-description]&lt;BR&gt;
    [/search-list]
 
    [item-list]
    [sort products:price:rn]
        [item-price] [item-code]&lt;BR&gt;
    [/item-list]
 
    [tag each products]
    [sort products:category products:title]
    [loop-field category] [loop-field title] &lt;BR&gt;
    [/tag]
</PRE>
<P>
All sort situations -- <CODE>[search list]</CODE> , <CODE>[loop list]</CODE> , <CODE>[tag each table]</CODE>, and
<CODE>[item-list]</CODE>, take options of the form:

<P>
<PRE>  [sort database:field:option* -n +n =n-n ... ]
</PRE>
<DL>
<DT><STRONG>database</STRONG><DD>

The MiniVend database identifier. This must be supplied, and should
normally be 'products' if you are using the default name for the database.

<P><DT><STRONG>field</STRONG><DD>

The field (column) of the database to be sorted on.

<P><DT><STRONG><A NAME="item_option">option</A></STRONG><DD>

None, any, or combinations of the options:

<P>
<PRE>  f   case-insensitive sort (folded) (mutually exclusive of n)
  n   numeric order (mutually exclusive of f)
  r   reverse sort
</PRE>
<P><DT><STRONG><A NAME="item__n">-n</A></STRONG><DD>

The starting point of the list to be displayed, beginning at 1 for the
first entry.

<P><DT><STRONG><A NAME="item__n">+n</A></STRONG><DD>

The number of entries to display in this list segment.

<P><DT><STRONG><A NAME="item__n_n">=n-n</A></STRONG><DD>

The starting and ending point of the list display -- this is an alternative
to -n and +n. You should specify in only one form -- if both are specified
the last one will take effect.

<P><DT><STRONG><A NAME="item__">...</A></STRONG><DD>

Don't really put <CODE>...</CODE> in. This just means that you may specify as many sort levels as you wish.
Lots of sort levels with large databases will be quite slow.

<P></DL>
<P>
Multiple levels of sort are supported, and you can cross database
boundaries on different sort levels. Cross-database sorts on the same level
are not supported, so if you use multiple product databases you will have
to sort with embedded Perl. This is actually a feature in some cases, since
you can then display all items in a <CODE>used</CODE> database before or after your new ones in <A HREF="#item_products">products</A>.

<P>
Examples, all based on the <A HREF="#item_simple">simple</A> demo:

<DL>
<DT><STRONG><A NAME="item_Loop">Loop list</A></STRONG><DD>

<PRE>    [loop 00-0011 19-202 34-101 99-102]
    [sort products:title]
        [loop-code] [loop-field title]&lt;BR&gt;
    [/loop]
 
Will display:
</PRE>
<P>
<PRE>    34-101 Family Portrait
    00-0011 Mona Lisa
    19-202 Radioactive Cats
    99-102 The Art Store T-Shirt
</PRE>
<P>
If you instead do:

<P>
<PRE>    [loop 00-0011 19-202 34-101 99-102]
    [sort products:title -3 +2]
        [loop-code] [loop-field title]&lt;BR&gt;
    [/loop]
 
you will see:
</PRE>
<P>
<PRE>    19-202 Radioactive Cats
    99-102 The Art Store T-Shirt
</PRE>
<P>
The tag <CODE>[sort products:title =3-4]</CODE> is equivalent to the above.

<P><DT><STRONG><A NAME="item_Search">Search list</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> search of all products (i.e. <A
HREF="http://yoursystem.com/cgi-bin/simple/scan/ra=yes):">http://yoursystem.com/cgi-bin/simple/scan/ra=yes):</A>


<P>
<PRE>    [search-list]
    [sort products:artist products:title:rf]
        [item-field artist] [item-field title]&lt;BR&gt;
    [/search-list]
 
will display:
</PRE>
<P>
<PRE>    Gilded Frame
    Grant Wood American Gothic
    Jean Langan Family Portrait
    Leonardo Da Vinci Mona Lisa
    Salvador Dali Persistence of Memory
    Sandy Skoglund Radioactive Cats
    The Art Store The Art Store T-Shirt
    Vincent Van Gogh The Starry Night
    Vincent Van Gogh Sunflowers
</PRE>
<P>
Note the reversed order of the title for <EM>Van Gogh</EM>, and the presence of the accessory item <EM>Gilded Frame</EM> at the front of the list (it has no artist field, and as such sorts first).

<P>
Adding a slice option:

<P>
<PRE>    [search-list]
    [sort products:artist products:title:rf =6-10]
        [item-field artist] [item-field title]&lt;BR&gt;
    [/search-list]
 
will display:
</PRE>
<P>
<PRE>    Sandy Skoglund Radioactive Cats
    The Art Store The Art Store T-Shirt
    Vincent Van Gogh The Starry Night
    Vincent Van Gogh Sunflowers
</PRE>
<P>
If the end value/chunk size exceeds the size of the list, only the elements
that exist will be displayed, starting from the start value.

<P><DT><STRONG><A NAME="item_Shopping">Shopping cart</A></STRONG><DD>

<PRE>    [item-list]
    [sort products:price:rn]
        [item-price] [item-code]&lt;BR&gt;
    [/item-list]
 
will display the items in your shopping cart sorted on their price, with
the most expensive shown first. (Note that this is based on the database field,
and doesn't take quantity price breaks or discounts into effect.) B&lt;NOTE:&gt; You 
cannot sort on modifier values or quantities.
</PRE>
<P><DT><STRONG><A NAME="item_Complete">Complete database contents</A></STRONG><DD>

<PRE>    [tag each products]
    [sort products:category products:title]
    [loop-field category] [loop-field title] &lt;BR&gt;
    [/tag]
</PRE>
<P>

<FONT SIZE=-1>A</FONT> two level sort, that will sort products based first
on their category then on their title within the category.

<P></DL>
<P>
Note that large lists may take some time to sort -- if you have a product
database with many thousands of items, it is not recommended that you use
the <CODE>[tag each products]</CODE> sort unless you are planning on caching or statically building your pages.

<P>
<HR>


code: 15.02
section: SHIPPING
type: item
title: Default Shipping Mode

<A NAME="Default_Shipping_Mode">Default Shipping Mode</A></H2>
<P>
If a default shipping mode other than <CODE>default</CODE> is desired, enter it into the <EM>DefaultShipping</EM> directive:

<P>
<PRE>    DefaultShipping     upsg
</PRE>
<P>
This will make the entry on the order form checked by default when the user
starts the order process, if it is put in the form:

<P>
<PRE>  &lt;INPUT TYPE=RADIO NAME=mv_shipmode VALUE=upsg [checked mv_shipmode upsg]&gt; 
</PRE>
<P>
To force a choice by the user, you can make mv_shipmode a required form
variable (with <EM>RequiredFields</EM> or in an order profile) and set <EM>DefaultShipping</EM>
to zero.

<P>
<HR>


code: 15.03
section: SHIPPING
type: item
title: Shipping Cost Database

<A NAME="Shipping_Cost_Database">Shipping Cost Database</A></H2>
<P>
The shipping cost database (located in ProductDir/shipping.asc) is a tab-separated 
<FONT SIZE=-1>ASCII</FONT> file with six fields -- code, text description, criteria (quantity or weight, for example), minimum number, maximum number, and cost. None of the fields are case-sensitive. It always needs to be present if
 <EM>CustomShipping</EM> is to be used.

<DL>
<DT><STRONG>code</STRONG><DD>

The unique identifier for that shipping method and criteria range. 

<P><DT><STRONG><A NAME="item_description">description</A></STRONG><DD>

Text to describe the method (can be accessed on a page with the <CODE>[shipping-description]</CODE> element).

<P><DT><STRONG><A NAME="item_criteria">criteria</A></STRONG><DD>

Whether shipping is based on weight, quantity, price, etc. Valid MiniVend
tags can be placed in the field to do a dynamic lookup -- if a number is
returned, that is used as the <EM>accumulated criteria</EM> -- that is, the total of weight, quantity, or price as applied to all items
in the shopping cart.

<P>
The criteria field varies according to whether it is the first field in the
shipping file exactly matching the mode identifier. In that case, it is
called the <STRONG>main criterion</STRONG>. If it is in subsidiary shipping lines matching the mode (with optional
appended digits) then it is called a
<STRONG>qualifying criterion</STRONG>. The difference is that the main criterion returns the basis for the
calculation (i.e. weight or quantity) while the qualifying criterion
determines whether the individual line may match the conditions.

<P>
The return must be one of:

<P><DL>
<DT><STRONG><A NAME="item_o">o quantity</A></STRONG><DD>

quantity -- The literal value <STRONG>quantity</STRONG> as the main criterion will simply count the number of items in the shopping
cart and return it as the <EM>accumulated criteria</EM>.

<P><DT><STRONG>o &lt;field name&gt;</STRONG><DD>


<FONT SIZE=-1>A</FONT> valid product database field (column) name as main
criterion will cause the number of items in the shopping cart to be
multiplied by the
<EM>value of the field for each item</EM> to obtain the <EM>accumulated criteria</EM>.

<P><DT><STRONG>o n.nn</STRONG><DD>

where <STRONG>n.nn</STRONG> is any number. It will be directly used as the
<EM>accumulated criteria</EM>. This can be effectively returned from a Perl subroutine or MiniVend <CODE>[calc][item-list] ... [/item-list][/calc]</CODE>
to create custom shipping routines.

<P></DL>

<STRONG>IMPORTANT NOTE:</STRONG> The above only applies to the <STRONG>first</STRONG> field that matches the shipping mode exactly. Following <STRONG>criteria</STRONG> fields contain qualifier matching strings.

<P><DT><STRONG><A NAME="item_minimum">minimum</A></STRONG><DD>

The low bound of quantity/weight/criteria this entry applies to.

<P><DT><STRONG><A NAME="item_maximum">maximum</A></STRONG><DD>

The high bound of quantity/weight/criteria this entry applies to. The first
found entry is used in case of ties.

<P><DT><STRONG><A NAME="item_cost">cost</A></STRONG><DD>

The total cost, determined by formula if it begins with <A HREF="#item_f">f</A>, by multiplier if it begins with <A HREF="#item_x">x</A>, by UPS-style lookup if it begins with <A HREF="#item_u">u</A> or <CODE>[A-Z]</CODE>, by named subroutine if it begins with an <A HREF="#item_s">s</A>, by a MiniVend chained cost calculation if <A HREF="#item_m">m</A> or <A HREF="#item_i">i</A>, and a straight cost otherwise. If it begins with an <A HREF="#item_e">e</A>, a zero cost is returned with the following string as the error message.

<P></DL>
<P>
<HR>


code: 15.04
section: SHIPPING
type: item
title: Shipping Calculation modes

<A NAME="Shipping_Calculation_modes">Shipping Calculation modes</A></H2>
<P>
There are 8 ways that shipping cost may be calculated. The method used
depends on the <EM>first character</EM> of the <A HREF="#item_cost">cost</A> field in the shipping database.

<DL>
<DT><STRONG>N.NN (digits)</STRONG><DD>

If the first character is a digit, then a number is assumed and read
directly as the shipping cost.

<P><DT><STRONG><A NAME="item_c">c</A></STRONG><DD>

If the first character is a <A HREF="#item_c">c</A>, no cost is present but a mode-specific configuration option is applied.
This most often would be definition of an alternate UPS-style lookup zone.

<P><DT><STRONG><A NAME="item_e">e</A></STRONG><DD>

If the first character is an <A HREF="#item_e">e</A>, a cost of zero is returned and an error message is placed in the session
value <CODE>ship_message</CODE>
(<CODE>[data session ship_message]</CODE>).

<P><DT><STRONG><A NAME="item_f">f</A></STRONG><DD>

If the character <A HREF="#item_f">f</A> is the first, MiniVend will first interpret the text for any MiniVend tags
and then interpret the result as a formula (really as Perl code).

<P><DT><STRONG><A NAME="item_g">g</A></STRONG><DD>

If the first character is a <A HREF="#item_g">g</A>, no cost is present but a global configuration option is applied, such as
applicability of <EM>PriceDivide</EM>.

<P><DT><STRONG><A NAME="item_i">i</A></STRONG><DD>

Specifies a chained shipping lookup which will be applied to each item in
the shopping cart.

<P><DT><STRONG><A NAME="item_m">m</A></STRONG><DD>

Specifies a chained shipping lookup which will be applied to the entire
shopping cart.

<P><DT><STRONG><A NAME="item_s">s</A></STRONG><DD>

Specifies a named subroutine; this is largely deprecated in favor of
chained shipping modes.

<P><DT><STRONG><A NAME="item_u">u</A></STRONG><DD>

Calls the default UPS-style lookup.

<P><DT><STRONG><A NAME="item_x">x</A></STRONG><DD>

If an <A HREF="#item_x">x</A> is first, a number is expected and is applied as a fixed multiplier for the accumulated criterion 
<FONT SIZE=-1>(@@TOTAL@@).</FONT>


<P><DT><STRONG><A NAME="item_A">A-Z</A></STRONG><DD>

If the first character is a capital letter, calls one of the 26 secondary
UPS-style lookup zones.

<P></DL>
<P>
<HR>


code: 15.05
section: SHIPPING
type: item
title: How shipping is calculated

<A NAME="How_shipping_is_calculated">How shipping is calculated</A></H2>
<OL>
<LI>

The base code is selected by reading the value of mv_shipmode in the user
session. If it has not been explicitly set, either by means of the <EM>DefaultShipping</EM> directive or by setting the variable on a form (or in an order profile), it
will be <CODE>default</CODE>.

<P><LI>

The criterion field is found -- if it is quantity, then it is the total
quantity of items on the order form. If it is any other name, then the
criterion is calculated by multiplying the return value from the product
database field for each item in the shopping cart, multiplied by its
quantity. (If the lookup fails due to the column or row not existing, a
zero cost will be returned, and an error is sent to the catalog error log.)
If a number is returned from a MiniVend tag, then that number is used
directly.

<P><LI>

Entries in the shipping database that begin with the same string as the
shipping mode are examined. If none is found, a zero cost is returned and
an error is sent to the catalog error log.

<P>
<STRONG>NOTE:</STRONG> You may use the same mode name for all lines in the same group, but the <EM>first</EM> one will contain the main criteria.

<P><LI>

The value of the accumulated criteria is examined, and if it falls with in
the minimum and maximum, the cost is then applied.

<P><LI>

If the cost is fixed, it is simply added.

<P><LI>

If the cost field begins with an <A HREF="#item_x">x</A>, the cost is multiplied by the accumulated criterion -- price, weight,
etc.

<P><LI>

If the cost field begins with <A HREF="#item_f">f</A>, the formula following is applied. Use 
<FONT SIZE=-1>@@TOTAL@@</FONT> as the value of the accumulated criterion.

<P><LI>

If the cost field begins with <A HREF="#item_u">u</A> or a single letter from 
<FONT SIZE=-1>A-Z,</FONT> a UPS-style lookup is done.

<P><LI>

If the cost field begins with <A HREF="#item_s">s</A>, a Perl subroutine call is made.

<P><LI>

If the cost field begins with <A HREF="#item_e">e</A>, zero cost is returned and an error placed in the session <STRONG>ship_message</STRONG> field, available as
<CODE>[data session ship_message]</CODE>. (If using the standard tag syntax, you should surround it with <CODE>[post] [/post]</CODE> to ensure you get the messages from the current page.)

<P></OL>
<P>
Here is an example shipping file using all of the methods of determining
shipping cost.

<P>

<FONT SIZE=-1>NOTE:</FONT> The columns are lined up for your reading convenience, the actual entries should have 
<FONT SIZE=-1>ONE</FONT> tab between fields.


<P>
<PRE> global Option   n/a                 0   0      g PriceDivide
 
 rpsg   RPS      quantity            0   0      R RPS products/rps.csv
 rpsg   RPS      quantity            0   5      7.00
 rpsg   RPS      quantity            6   10     10.00
 rpsg   RPS      quantity            11  150    x .95
  
 usps   US Post  price               0   0      0
 usps   US Post  price               0   50     f 7 + (1 * @@TOTAL@@ / 10)
 usps   US Post  price               50  100    f 12 + (.90 * @@TOTAL@@ / 10)
 usps   US Post  price               100 99999  f @@TOTAL@@ * .05
 
 upsg   UPS      weight [value state]  0   0      e Nothing to ship.
 upsg   UPS      AK HI               0   150    u upsg [default zip 980] 12.00 round
 upsg   UPS                          0   150    u upsg [default zip 980] 2.00 round
 upsg   UPS                          150 9999   e @@TOTAL@@ lb too heavy for UPS
</PRE>
<P>
<PRE> upsca  UPS/CA   weight              0   0      c C UPS_Canada products/can.csv
 upsca  UPS/CA   weight              -1   -1    o PriceDivide=0
 upsca  UPS/CA   weight              0   150    C upsca [default zip A7G] 5.00
 upsca  UPS/CA   weight              150 99999  e @@TOTAL@@ lb too heavy for UPS
 
 fedex  FedEx    quantity            1   9999   s fedex_cost ;[value country]
</PRE>
<DL>
<DT><STRONG><A NAME="item_global">global</A></STRONG><DD>

This is a global option setting, called out by the <A HREF="#item_g">g</A> at the beginning. PriceDivide tells the shipping routines to multiply all
shipping settings by the PriceDivide factor -- except those explicitly set
differently with the <A HREF="#item_o">o</A> individual modifier. This allows currency conversion. (Currently the only
option is PriceDivide.)

<P><DT><STRONG><A NAME="item_rpsg">rpsg</A></STRONG><DD>

If the user selected 
<FONT SIZE=-1>RPS,</FONT> (code rpsg), and the quantity on the order was 3,
the cost of 7.00 from the second <EM>rpsg</EM> line would be applied. If the quantity were 7, the next entry from the
third <EM>rpsg</EM> line would be selected, for a cost of 10.00. If the quantity were 15, the
last <EM>rpsg</EM> would be selected, and the quantity of 15 multiplied by 0.95, for a total
cost of 14.25.

<P><DT><STRONG><A NAME="item_usps">usps</A></STRONG><DD>

The next mode, <A HREF="#item_usps">usps</A>, is a more complicated formula -- using price as the criteria. If the
total price of all items in the shopping cart (same as <CODE>[subtotal]</CODE> without quantity price breaks in place) is from 1 to 50, the cost will be
7.00 plus 10% of the order. If the total is from 50.01 to 100, the cost
will be 12.00 plus 9% of the order total. If the cost is 100.01 or greater,
then 5% of the order total will be used as the shipping cost.

<P><DT><STRONG><A NAME="item_upsg">upsg</A></STRONG><DD>

The next, <A HREF="#item_upsg">upsg</A>, is a special case. It specifies a 
<FONT SIZE=-1>UPS</FONT> lookup based on your 
<FONT SIZE=-1>UPS</FONT> zone and two required values (and two optional arguments):


<P>
<PRE>    1. Weight (careful, always use weight for this one!)
    2. The zip/postal code of the recipient, of which only
       the first three digits are used.
    3. A fixed amount to add to the cost found in the UPS
       tables (use 0 as a placeholder if specifying roundup)
    4. If set to 'round', will round the cost up to the next
       integer monetary unit.
</PRE>
<P>
If the cost returned is zero, the reason will be placed as an error message
in the session variable ship_message (available as
<CODE>[data session ship_message]</CODE>).

<P>

<FONT SIZE=-1>UPS</FONT> weights are always rounded up if any fraction is
present. 

<P>
The routines use standard 
<FONT SIZE=-1>UPS</FONT> lookup tables. First, the 
<FONT SIZE=-1>UPS</FONT> Zone file must be present. That is a standard 
<FONT SIZE=-1>UPS</FONT> document,

<EM>specific to your area</EM>, that you must obtain from 
<FONT SIZE=-1>UPS</FONT> and enter into and make available to MiniVend in TAB-delimited format. (As of March 1997, you can use the standard .csv file distributed by 
<FONT SIZE=-1>UPS</FONT> on their web site at www.ups.com.) You specify it with the
 <EM>UpsZoneFile</EM> directive -- it is usually named something like <CODE>NNN.csv</CODE>, where 
<FONT SIZE=-1>NNN</FONT> is the first three digits of the originating zip
code. If you place it in your products directory, then the directive would
look like:

<P>
<PRE>    UPSZoneFile  products/450.csv
</PRE>
<P>
Second, you must obtain the cost tables from 
<FONT SIZE=-1>UPS</FONT> (again, you can get them from www.ups.com) and place them into a MiniVend database. That database, its identifier specified with the first argument (upsg in the example) of the cost specification, is consulted to determine the 
<FONT SIZE=-1>UPS</FONT> cost for that weight and rate schedule.


<P>
In the example below, you would want a database specification like:

<P>
<PRE>    Database  upsg  upsg.csv  CSV
</PRE>
<P>
You can append a simple shipping cost qualification to a 
<FONT SIZE=-1>UPS</FONT> lookup. If any additional parameters are present after the five usual ones used for 
<FONT SIZE=-1>UPS</FONT> lookup, they will be interpreted as a Perl subroutine call. The syntax is the same as if it was encased in the tag
 <CODE>[perl sub] [/perl]</CODE>, but the following substitutions are made prior to the call:

<P>
<PRE>    @@COST@@  is replaced with whatever the UPS lookup returned
    @@GEO@@   is replaced with the zip (or other geo code)
    @@ADDER@@ is replaced with the defined adder
    @@TYPE@@  is replaced with the UPS shipping type
    @@TOTAL@@ is replaced with the total weight
</PRE>
<P>
The example above also illustrates geographic qualification. If the value
of the form variable <STRONG>state</STRONG> on the checkout form is 
<FONT SIZE=-1>AK</FONT> or 
<FONT SIZE=-1>HI,</FONT> the 
<FONT SIZE=-1>U.S.</FONT> states Alaska and Hawaii, a $10.00 additional charge (over and above the normal 2.00 handling charge) is made. This can also be used to select on country, product type, or any other qualification that can be encoded in the file.


<P><DT><STRONG><A NAME="item_upsca">upsca</A></STRONG><DD>

The next entry is just like the 
<FONT SIZE=-1>UPS</FONT> definition except it defines a different lookup
zone file (<CODE>products/can.csv</CODE>) and uses a different database, <A HREF="#item_upsca">upsca</A>. It also disables the global PriceDivide option for itself only, not
allowing currency conversion. Otherwise, the process is the same.

<P>
You can define up to 27 different lookup zones in the same fashion. If one
of the cost lines (the last field) in the <CODE>shipping.asc</CODE> file begins with a ``c'', it configures another lookup zone, which must be
lettered from <A HREF="#item_A">A</A> to <CODE>Z</CODE>. It takes the format:

<P>
<PRE>    c X name file* length* multiplier*
</PRE>
<P>
where 
<FONT SIZE=-1>X</FONT> is the letter from <CODE>A-Z</CODE>. The name is used internally as an identifier and must be present. The
optional <A HREF="#item_file">file</A> is relative to the catalog root (like <EM>UpsZoneFile</EM> is) -- if it is not present the file equal to <A HREF="#item_name">name</A> in the products directory (<EM>ProductDir</EM>) will be used as the zone file. If the optional digit <CODE>length</CODE> is present, that determines the number of signficant digits in the passed
postal/geo code. When the optional <CODE>multiplier</CODE> is present, the weight is multiplied by it before doing the table lookup.
This allows shipping weights in pounds or kilograms to be adapted to a
table using the opposite as the key. Remember, the match on weight must be
exact, and MiniVend rounds the weight up to the next even unit.

<P>
To define the exact equivalent of the 
<FONT SIZE=-1>UPS</FONT> lookup zone, you would do:

<P>
<PRE>    c U UPS products/450.csv 3 1
</PRE>
<P>
The only difference is that the beginning code to call the lookup is
upper-case
<CODE>U</CODE> instead of lower-case <A HREF="#item_u">u</A>.

<P><DT><STRONG><A NAME="item_fedex">fedex</A></STRONG><DD>

The last entry, <A HREF="#item_fedex">fedex</A>, uses a named subroutine. The example is designed to work with this
subroutine defined in catalog.cfg:

<P>
<PRE>    Sub &lt;&lt;EOF
    sub fedex_cost {
        my($country) = @_;
        my $cost;
        if($country =~ /^usa?$/i) {
            $cost = 20;
        }
        else {
            $cost = 50;
        }
        return $cost;
    }
    EOF
</PRE>
<P>
<STRONG>NOTE:</STRONG> The text above appears indented, but in the <EM>catalog.cfg</EM> file it must begin at the beginning of the line. Also, make sure you upload in 
<FONT SIZE=-1>ASCII</FONT> mode -- carriage returns are not tolerated.


<P>
It will simply return a cost of 20 if the country the user has entered is 
<FONT SIZE=-1>US</FONT> or 
<FONT SIZE=-1>USA</FONT> -- and return 50 otherwise. Obviously much more complicated routines can be defined. Read the following only if you know Perl well and/or are not of faint heart.


<P>
You can call named subroutines with any of the methods, defined with
<CODE>[set name] your_perl_code_here [/set]</CODE>, <EM>Sub</EM>, or <EM>GlobalSub</EM>.

<P>
If parameters are specified, separated by commas, they will be taken as
either fixed values or as database fields to be sent to the subroutine in
an anonymous hash keyed on the item code (for each item in the *current*
shopping cart).

<P>
If a database other than the products database is to be used, the database
name should be prepended with a colon (<CODE>:</CODE>) separator. If a key other than the item code is to be used, it should be
appended with a semi-colon separator.

<P>
To send fixed value to the subroutine (appended to the call reference as an
array of fixed scalar parameters), begin the parameter with a semicolon. <STRONG>They will be appended globally after the hash reference</STRONG>.

<P>
Examples

<P>
<PRE>  # Sends the weight of each item from the products database
  
  weight 
  
  
  # Sends the value of the handling field from the
  # special database for each item
  
  special:handling 
  
   
  # Sends the value of the 'adder' field from the special
  # database, for the value the user has entered for 'country'
  # The spaces around the separators are OK
 
  special : adder ; [value country] 
  
 
  # Sends a fixed parameter of 20 to the subroutine
  
  ;20
</PRE>
<P>
The parameters are interpreted for MiniVend tags before being parsed. Here
is a complete example:

<P>
<PRE>   s item_cost weight,modes:[value mv_shipmode];[value country], ;20, ;25
  
  items in the shopping cart:  00-0011 19=202
  
  ------- product database  ----
  
  code    weight   description      price
  00-0011   8      The Mona Lisa    1000
  19-202    12     American Gothic  800
  
  
  ------- modes database  ----
  
  code    upsg  upsb  upsr  postal_air postal_surface
  UK        0    0     0       1            1 
</PRE>
<P>
will call the subroutine <CODE>item_cost</CODE>, and will send the weight of each item, along with the value of the modes
database column corresponding to the shipping mode the user has selected,
keyed with the value of <CODE>country</CODE>
on their order form. If the user has selected mode postal_air, and is in
the country coded as <CODE>UK</CODE>, the subroutine will be called as if it was:

<P>
<PRE>      item_cost( {
                    '00-0011' =&gt; {postal_air =&gt; '1', weight =&gt; '8'}, 
                    '19-202' =&gt; {postal_air =&gt; '1', weight =&gt; '12'},
                 }, 20, 25 )
</PRE>
<P>
If the undefined value is returned by the routine, the next shipping mode
will be tried. If a non-numeric string value is returned, its value will be
placed as an error message in the session variable ship_message (available
as <CODE>[data session ship_message]</CODE>) and a zero cost will be returned. If any number or the empty string is
returned, it will be used as the shipping cost (even 0).

<P></DL>
<P>
<HR>


code: 15.06
section: SHIPPING
type: item
title: Handling charges

<A NAME="Handling_charges">Handling charges</A></H2>
<P>
Additional handling charges can be defined in the shipping file by setting
the form variable <CODE>mv_handling</CODE> to a space, comma, or null-separated set of valid shipping modes. The
lookup and charges are done in the same fashion, and the additional charges
are added to the order. (The user is responsible for displaying the charge
on the order report or receipt with a <CODE>[shipping handling]</CODE>
tag or the like.) All of the shipping modes found in mv_handling will be
applied -- if multiple instances are found on a form, the accordingly
null-separated values will all be applied. Careful! This should not be done
in an item-list unless you take care to account for multiple setting of the
variables.

<P>
If you wished only to process a handling charge once, you could do safely:

<P>
<PRE>    [item-list]
    [if-field very_heavy]
    [perl values]
        return '' if $Safe-&gt;{'values'}-&gt;{mv_handling} =~ /very_heavy/;
        return &quot;&lt;INPUT TYPE=hidden NAME=mv_handling VALUE=very_heavy&gt;&quot;;
    [/perl]
    [/if-field]
    [/item-list]
</PRE>
<P>

<FONT SIZE=-1>A</FONT> non-blank/non-zero value in the database field <STRONG>very_heavy</STRONG> will then trigger Perl code which will only set mv_handling once.

<P>
<HR>


code: 15.06
section: SHIPPING
type: item
title: More on UPS-style lookup

<A NAME="More_on_UPS_style_lookup">More on UPS-style lookup</A></H2>
<P>
The UPS-style lookup uses two files for its purposes, both of which need to be in a format like 
<FONT SIZE=-1>UPS</FONT> distributes for 
<FONT SIZE=-1>US</FONT> shippers.


<P>
The <EM>zone file</EM> is a file that is usually specific to the originating location. For 
<FONT SIZE=-1>US</FONT> shippers shipping to 
<FONT SIZE=-1>US</FONT> locations, it is named for the first three digits of the originating zip code with a 
<FONT SIZE=-1>CSV</FONT> extenstion -- for example,
 <CODE>450.csv</CODE>.

<P>
It has a format similar to:

<P>
<PRE>    low - high, zone,zone,zone,zone
</PRE>
<P>
The <CODE>low</CODE> entry is the low bound of the geographic location -- <CODE>high</CODE>
is the high bound. (By <EM>geographic location</EM> we mean zip code.) If the first digits of the zip code, compared
alphanumerically, fall between the low and high values, that zone is used
as the column name for a lookup in the <EM>rate database</EM>. The weight is used as the row key.

<P>
The first operative row of the zone file (one without leading quotes) is used to determine the zone column name. In the 
<FONT SIZE=-1>US,</FONT> it looks something like
 

<P>
Dest. ZIP,Ground,3 Day Select,2nd Day Air,2nd Day Air A.M.,Next Day Air
Saver,Next Day Air

<P>
MiniVend strips all non-alpha characters and comes up with:

<P>
DestZIP,Ground,3DaySelect,2ndDayAir,2ndDayAirAM,NextDayAirSaver,NextDayAir

<P>
Therefore, the zone column (shipping type) that you would use use for 
<FONT SIZE=-1>UPS</FONT> ground would be ``Ground'', and that is what the
database should be named. To support the above, you would want a <CODE>shipping.asc</CODE> line that reads:

<P>
<PRE>    upsg  UPS Ground  weight  0  150  u Ground [default zip 983]
</PRE>
<P>
and a <CODE>catalog.cfg</CODE> database callout of:

<P>
<PRE>    Database  Ground  Ground.csv  CSV
</PRE>
<P>
You can change these column names as long as they correspond to the <A HREF="#item_identifier">identifier</A> of your rate database.

<P>
The <EM>rate database</EM> is a standard MiniVend database. For 
<FONT SIZE=-1>US</FONT> shippers, 
<FONT SIZE=-1>UPS</FONT> distributes their rates in a fairly standard comma-separated value format, with weight being the first (or key) column and the remainder of the columns corresponding to the zone -- which you obtain from the lookup in the zone file.


<P>
To adapt other shipper zone files to MiniVend's lookup, you will need to make it fit the 
<FONT SIZE=-1>UPS</FONT> 
<FONT SIZE=-1>US</FONT> format. (Most of the 
<FONT SIZE=-1>UPS</FONT> international files don't follow the 
<FONT SIZE=-1>US</FONT> format). For example, the 1998 Ohio-US to Canada file begins:


<P>
<PRE>    Canada Standard Zone Charts from Ohio
    Locate the zone by cross-refrencing the first three
    characters of the destination Postal Code in the Postal
    Range column.
 
    Postal Range  Zone
    A0A  A9Z      54
    B0A  B9Z      54
    C0A  C9Z      54
    E0A  E9Z      54
    G0A  G0A      51
    G0B  G0L      54
    G0M  G0S      51
    G0T  G0W      54
</PRE>
<P>
You need to change it to

<P>
<PRE> 
    Destination,canstnd
    A0A-A9Z, 54
    B0A-B9Z, 54
    C0A-C9Z, 54
    E0A-E9Z, 54
    G0A-G0A, 51
    G0B-G0L, 54
    G0M-G0S, 51
    G0T-G0W, 54
</PRE>
<P>
and match it with a <CODE>canstnd</CODE> 
<FONT SIZE=-1>CSV</FONT> database that looks like

<P>
<PRE>    Weight,51,52,53,54,55,56
    1,7.00,7.05,7.10,11.40,11.45,11.50
    2,7.55,7.65,7.75,11.95,12.05,12.10
    3,8.10,8.15,8.40,12.60,12.70,12.85
    4,8.65,8.70,9.00,13.20,13.30,13.55
    5,9.20,9.25,9.75,13.85,13.85,14.20
    6,9.70,9.85,10.35,14.45,14.50,14.90
    7,10.25,10.40,11.10,15.15,15.15,15.70
    8,10.80,10.95,11.70,15.70,15.75,16.35
    9,11.35,11.55,12.30,16.40,16.45,17.20
</PRE>
<P>
and is called out in catalog.cfg with:

<P>
<PRE>    Database canstnd canstnd.csv CSV
</PRE>
<P>
With the above, a 4-pound shipment to postal code 
<FONT SIZE=-1>E5C</FONT> 
<FONT SIZE=-1>4TL</FONT> would yield a cost of 13.20.


<P>
<HR>


code: 15.07
section: SHIPPING
type: item
title: Geographic qualification

<A NAME="Geographic_qualification">Geographic qualification</A></H2>
<P>
If the return value in the main criterion includes whitespace, the
remaining information in the field is used as a qualifier for the
subsidiary shipping modes. This can be used to create geographic
qualifications for shipping, as in:

<P>
<PRE> upsg   UPS Ground   weight [value state]   0     0     e No items selected
 upsg   UPS Ground   AK HI                  0     150   u Ground [value zip] 12.00
 upsg   UPS Ground                          0     150   u Ground [value zip] 3.00
</PRE>
<P>
If <A HREF="#item_upsg">upsg</A> is the mode selected, the value of the user session variable
<A HREF="#item_state">state</A> is examined to see if it matches the geographic qualification on a
whole-word boundary. If it is <CODE>AK</CODE> or <CODE>HI</CODE>, then 
<FONT SIZE=-1>UPS</FONT> Ground with an adder of 12 will be selected; if it ``falls through'', then 
<FONT SIZE=-1>UPS</FONT> Ground with an adder of 3 will be selected.


<P>
<HR>


code: 16.00
section: SHIPPING
type: overview
title: SHIPPING

<A NAME="SHIPPING">SHIPPING</A></H1>
<P>
MiniVend allows the addition of a flat shipping charge with the <EM>Shipping</EM> directive. Most catalogs have more elaborate requirements, requiring use of
the <EM>SHIPPING</EM> capability of MiniVend.

<P>
To enable custom shipping, enter the default field to use in the
<EM>CustomShipping</EM> directive:

<P>
<PRE>    CustomShipping  weight
</PRE>
<P>
<STRONG>IMPORTANT NOTE:</STRONG> Before MiniVend 2.0, there could only be one field used to set the
criteria. As of MiniVend 2.0, the entry in the shipping file which is <EM>exactly the same</EM> as the value of the mv_shipmode variable will be used to determine the
field criteria for the shipping method. This allows <EM>weight</EM> to be used for one mode, while <EM>price</EM> or
<EM>quantity</EM> is used for another. The CustomShipping directive only sets the <STRONG>default</STRONG> field to be used if none is present in the mode specification.

<P>
<HR>


code: 16.02
section: USER_DATABASE
type: item
title: The [userdb ...] tag

<A NAME="The_userdb_tag">The [userdb ...] tag</A></H2>
<P>
MiniVend provides a <CODE>[userdb ...]</CODE> tag to access the UserDB functions.

<P>
<PRE> [userdb
        function=function_name
        username=&quot;username&quot;*
        assign_username=1
        username_mask=REGEX*
        password=&quot;password&quot;*
        verify=&quot;password&quot;*
        oldpass=&quot;old password&quot;*
        crypt=&quot;1|0&quot;*
        shipping=&quot;fields for shipping save&quot;
        billing=&quot;fields for billing save&quot;
        preferences=&quot;fields for preferences save&quot;
                ignore_case=&quot;1|0&quot;*
        force_lower=1
        param1=value*
        param2=value*
        ...
        ]
</PRE>
<P>
* Optional

<P>
It is normally called in an <CODE>mv_click</CODE> or <CODE>mv_check</CODE> setting, as in:

<P>
<PRE>    [set Login]
    mv_todo=return
    mv_nextpage=welcome
    [userdb function=login]
    [/set]
</PRE>
<P>
<PRE>    &lt;FORM ACTION=&quot;[process-target]&quot; METHOD=POST&gt;
    &lt;INPUT TYPE=hidden NAME=mv_click VALUE=Login&gt;
    Username &lt;INPUT NAME=mv_username SIZE=10&gt;
    Password &lt;INPUT NAME=mv_password SIZE=10&gt;
    &lt;/FORM&gt;
</PRE>
<P>
There are several global parameters that apply to any use of the <CODE>userdb</CODE> functions. Most importantly, by default the database table is set to be <EM>userdb</EM>. If you must use another table name, then you should include a <CODE>database=table</CODE> parameter with any call to <CODE>userdb</CODE>. The global parameters (default in parens):

<P>
<PRE>    database     Sets user database table (userdb)
    show         Show the return value of certain functions
                 or the error message, if any (0)
    force_lower  Force possibly upper-case database fields
                 to lower case session variable names (0)
    billing      Set the billing fields (see Accounts)
    shipping     Set the shipping fields (see Address Book)
    preferences  Set the preferences fields (see Preferences)
    bill_field   Set field name for accounts (accounts)
    addr_field   Set field name for address book (address_book)
    pref_field   Set field name for preferences (preferences)
    cart_field   Set field name for cart storage (carts)
    pass_field   Set field name for password (password)
    time_field   Set field for storing last login time (time)
    expire_field Set field for expiration date (expire_date)
    acl          Set field for simple access control storage (acl)
    file_acl     Set field for file access control storage (file_acl)
    db_acl       Set field for database access control storage (db_acl)
</PRE>
<P>
By default the system <CODE>crypt()</CODE> call will be used to compare the
password. This is best for security, but the passwords in the user database
will not be human readable.

<P>
If you don't keep critical information and don't do MiniVend administration
via the <CODE>UserDB</CODE> capability, then you may wish to use the &lt;UserDB&gt; directive
(described below) to set encryption off by default:

<P>
<PRE>    UserDB   default   crypt   0
</PRE>
<P>
That will set encryption off by default. You can still set encryption on by
passing <CODE>crypt=1</CODE> with any call to a <A HREF="#item_new_account">new_account</A>, <A HREF="#item_change_pass">change_pass</A>, or <A HREF="#item_login">login</A> call.

<P>
<HR>


code: 16.03
section: USER_DATABASE
type: item
title: Setting defaults with the UserDB directive

<A NAME="Setting_defaults_with_the_UserDB">Setting defaults with the UserDB directive</A></H2>
<P>
The <EM>UserDB</EM> directive provides a way to set defaults for the user database. For
example, if you always wanted to save and recall the scratch variable <CODE>tickets</CODE> in the user database instead of the form variable <CODE>tickets</CODE>, you could set:

<P>
<PRE>    UserDB   default   scratch  tickets
</PRE>
<P>
That makes every call to <CODE>[userdb function=login]</CODE> be equivalent to <CODE>[userdb function=login scratch=tickets]</CODE>.

<P>
If you wish to override that default for one call only, you can use <CODE>[userdb function=login scratch=&quot;passes&quot;]</CODE>.

<P>
The <EM>UserDB</EM> directive uses the same key-value pair settings as the <EM>Locale</EM> and <EM>Route</EM> directives, and you may have more than one set of defaults. You can set
them in a hash structure:

<P>
<PRE>        UserDB  crypt_case  &lt;&lt;EOF
        {
                'scratch'                =&gt; 'tickets',
                'crypt'                  =&gt; '1',
                'ignore_case'    =&gt; '0',
        }
        EOF
</PRE>
<P>
<PRE>        UserDB  default  &lt;&lt;EOF
        {
                'scratch'                =&gt; 'tickets',
                'crypt'                  =&gt; '1',
                'ignore_case'    =&gt; '1',
        }
        EOF
</PRE>
<P>

<FONT SIZE=-1>NOTE:</FONT> The usual here-document caveats apply -- the 
<FONT SIZE=-1>EOF</FONT> must be on a line by itself with no leading/trailing whitespace.


<P>
The last one to be set becomes the default.

<P>
The option <A HREF="#item_profile">profile</A> selects the set to use. So if you wanted usernames and passwords to be case
sensitive with no encryption, you could pass this call:

<P>
<PRE>        [userdb function=new_account profile=case_crypt]
</PRE>
<P>
The username and password will be stored as typed in, and the password will
be encrypted in the database.

<P>
<HR>


code: 16.04
section: USER_DATABASE
type: item
title: User Database functions

<A NAME="User_Database_functions">User Database functions</A></H2>
<P>
The user database features are implemented as a series of functions
attached to the <CODE>userdb</CODE> tag. The functions are:

<DL>
<DT><STRONG><A NAME="item_login">login</A></STRONG><DD>

Active parameters: username, password, crypt, pass_field, ignore_case

<P>
Log in to Minivend. By default, the username is contained in the form
variable <CODE>mv_username</CODE> and the password in <CODE>mv_password</CODE>. If the login is successful, the session value <CODE>username</CODE>
(<CODE>[data session username]</CODE>) will be set to the user name.

<P>
This will recall the values of all non-special fields in the user database
and place them in their corresponding user form variables.

<P>
The <EM>CookieLogin</EM> directive (catalog.cfg) allows users to save their username/password in a
cookie. Expiration time is set by
<EM>SaveExpire</EM>, renewed every time they log in. To cause the cookie to be generated
originally, the form variable <CODE>mv_cookie_password</CODE> or
<CODE>mv_cookie_username</CODE> must be set in the login form. The former causes both username and password
to be saved, the latter just the username.

<P><DT><STRONG><A NAME="item_logout">logout</A></STRONG><DD>

Log out of Minivend. No additional parameters are needed.

<P><DT><STRONG><A NAME="item_new_account">new_account</A></STRONG><DD>

Active parameters: username, password, verify, assign_username,
username_mask, ignore_case

<P>
Create a new account. It requires the <CODE>username</CODE>, <CODE>password</CODE>, and
<CODE>verify</CODE> parameters, which are by default contained in the form variables <CODE>mv_username</CODE>, <CODE>mv_password</CODE>, <CODE>mv_verify</CODE> respectively.

<P>
If you set the <CODE>assign_username</CODE> parameter, then UserDB will assign a sequential username. The <A HREF="#item_counter">counter</A> parameter can be used to set the filename (must be absolute), or you can accept the default of CATALOG_DIR/etc/username.counter. The first username will be 
<FONT SIZE=-1>``U0001''</FONT> if the counter doesn't exist already.


<P>
The <CODE>ignore_case</CODE> parameter forces the username and password to lower case in the database,
in effect rendering the username and password case-insensitive.

<P>
If you set <CODE>username_mask</CODE> to a valid Perl regular expression (without the surrounding / /) then any
username containing a matching string will not be allowed for use. For
example, to screen out order numbers from being used by a random user:

<P>
<PRE>    [userdb function=new_account
            username_mask=&quot;^[A-Z]*[0-9]&quot;
            ]
</PRE>
<P>
The <EM>CookieLogin</EM> directive (catalog.cfg) allows users to save their username/password in a
cookie. Expiration time is set by
<EM>SaveExpire</EM>, renewed every time they log in. To cause the cookie to be generated
originally, the form variable <CODE>mv_cookie_password</CODE> or
<CODE>mv_cookie_username</CODE> must be set in the login form. The former causes both username and password
to be saved, the latter just the username.

<P>
If you want to automatically create an account for every order, you can do
in the <EM>OrderReport</EM> file:

<P>
<PRE>    [userdb function=new_account
            username=&quot;[value mv_order_number]&quot;
            password=&quot;[value zip]&quot;
            verify=&quot;[value zip]&quot;
            database=&quot;orders&quot;
            ]
</PRE>
<P>
This would be coupled with a login form that asked for order number and zip
code; thereupon allowing you to display the contents of a transaction
database with (presumably updated) order status information or a shipping
company tracking number.

<P><DT><STRONG><A NAME="item_change_pass">change_pass</A></STRONG><DD>

Active parameters: username, password, verify, oldpass

<P>
Change the password on the currently logged-in account. It requires the <CODE>username</CODE>, <CODE>password</CODE>, <CODE>verify</CODE>, and <CODE>oldpass</CODE> parameters, which are by default contained in the form variables <CODE>mv_username</CODE>,
<CODE>mv_password</CODE>, <CODE>mv_verify</CODE>, <CODE>mv_oldpass</CODE> respectively.

<P><DT><STRONG><A NAME="item_set_shipping">set_shipping</A></STRONG><DD>

Active parameters: nickname, shipping, ship_field

<P>
Place an entry in the shipping Address book. Example:

<P>
<PRE>    [userdb function=set_shipping nickname=Dad]
</PRE>
<P>
See <EM>Address Book</EM> below.

<P><DT><STRONG><A NAME="item_get_shipping">get_shipping</A></STRONG><DD>

Active parameters: nickname, shipping, ship_field

<P>
Recall an entry from the shipping Address book. Example:

<P>
<PRE>    [userdb function=get_shipping nickname=Dad]
</PRE>
<P>
See <EM>Address Book</EM> below.

<P><DT><STRONG><A NAME="item_get_shipping_names">get_shipping_names</A></STRONG><DD>

Active parameters: ship_field

<P>
Gets the names of shipping address book entries and places them in the
variable <CODE>address_book</CODE>. By default, it does not return the values; if you wish them to be
returned you can set the parameter <CODE>show</CODE> to 1, as in:

<P>
<PRE>    [set name=shipping_nicknames
         interpolate=1]
      [userdb function=get_shipping_names show=1]
    [/set]
</PRE>
<P><DT><STRONG><A NAME="item_set_billing">set_billing</A></STRONG><DD>

Active parameters: nickname, billing, bill_field

<P>
Place an entry in the billing accounts book. Example:

<P>
<PRE>    [userdb function=set_billing nickname=discover]
</PRE>
<P>
See <EM>Accounts Book</EM> below.

<P><DT><STRONG><A NAME="item_get_billing">get_billing</A></STRONG><DD>

Active parameters: nickname, billing, bill_field

<P>
Recall an entry from the billing accounts book. Example:

<P>
<PRE>    [userdb function=get_billing nickname=visa]
</PRE>
<P>
See <EM>Accounts Book</EM> below.

<P><DT><STRONG><A NAME="item_save">save</A></STRONG><DD>

Saves all non-special form values that have columns in the user database.

<P><DT><STRONG><A NAME="item_set_cart">set_cart</A></STRONG><DD>

Save the contents of a shopping cart.

<P>
<PRE>    [userdb function=set_cart nickname=christmas]
</PRE>
<P>
See <EM>Carts</EM> below.

<P><DT><STRONG><A NAME="item_get_cart">get_cart</A></STRONG><DD>

Active parameters: nickname, carts_field, target

<P>
Recall a saved shopping cart. 

<P>
<PRE>    [userdb function=get_cart nickname=mom_birthday]
</PRE>
<P>
Setting <CODE>target</CODE> saves to a different shopping cart than the default main cart. The <CODE>carts_field</CODE> controls the database field used for storage.

<P><DT><STRONG><A NAME="item_set_acl">set_acl</A></STRONG><DD>

Active parameters: location, acl_field, delete

<P>
Set a simple acl. Example:

<P>
<PRE>    [userdb function=set_acl location=cartcfg/editcart]
</PRE>
<P>
This allows the current user to access the page ``cartcfg/editcart'' if it
is access-protected.

<P>
To delete access, do:

<P>
<PRE>    [userdb function=set_acl location=cartcfg/editcart delete=1]
</PRE>
<P>
To display the setting at the same time as setting use the
<CODE>show</CODE> attribute:

<P>
<PRE>    [userdb function=set_acl location=cartcf/editcart show=1]
</PRE>
<P><DT><STRONG><A NAME="item_check_acl">check_acl</A></STRONG><DD>

Active parameters: location, acl_field

<P>
Checks the simple access control listing for a location, returning 1 if
allowed and the empty string if not allowed.

<P>
<PRE>    [if type=explicit
        compare=&quot;[userdb
                    function=check_acl
                    location=cartcfg/editcart]&quot;
    ]
    [page cartcfg/editcart]Edit your cart configuration[/page]
    [/if]
</PRE>
<P><DT><STRONG><A NAME="item_set_file_acl">set_file_acl, set_db_acl</A></STRONG><DD>

Active parameters: location, mode, db_acl_field, file_acl_field, delete

<P>
Sets a complex access control value. Takes the form:

<P>
<PRE>    [userdb function=set_file_acl
            mode=rw
            location=products/inventory.txt]
</PRE>
<P>
where mode is any value you wish to check for with check_file_acl. As with the simple 
<FONT SIZE=-1>ACL,</FONT> you can use delete=1 to delete the location entirely.


<P><DT><STRONG><A NAME="item_check_file_acl">check_file_acl, check_db_acl</A></STRONG><DD>

Active parameters: location, mode, db_acl_field, file_acl_field

<P>
Checks a complex access control value and returns a true/false (1/0) value.
Takes the form:

<P>
<PRE>    [userdb function=check_db_acl
            mode=w
            location=inventory]
</PRE>
<P>
where mode is any value you wish to check for with check_file_acl. It will
return true if the mode string is contained within the entry for that
location. Example:

<P>
<PRE>    [if type=explicit
        compare=&quot;[userdb
                    function=check_db_acl
                    mode=w
                    location=inventory]&quot;
    ]
    [userdb function=set_acl location=cartcfg/edit_inventory]
    [page cartcfg/edit_inventory]You may edit the inventory database[/page]
    [else]
    [userdb function=set_acl location=cartcfg/edit_inventory delete=1]
    Sorry, you can't edit inventory.
    [/if]
</PRE>
<P></DL>
<P>
<HR>


code: 16.05
section: USER_DATABASE
type: item
title: Address Book

<A NAME="Address_Book">Address Book</A></H2>
<P>
<EM>address_book</EM> is a shipping address book. The shipping address book saves information
relevant to shipping the order. In its simplest form, this can be the only
address book needed. By default these form values are included:

<P>
<PRE>   s_nickname
   name
   address
   city
   state
   zip
   country
   phone_day
   mv_shipmode
</PRE>
<P>
The first field is always the name of the form variable that contains the
key for the entry.

<P>
The values are saved with the <CODE>[userdb function=set_shipping]</CODE> tag call, and are recalled with <CODE>[userdb function=get_shipping]</CODE>. 
<FONT SIZE=-1>A</FONT> list of the keys available is kept in the form value <CODE>address_book</CODE>, suitable for iteration in an 
<FONT SIZE=-1>HTML</FONT> select box or in a set of links.

<P>
You can get the names of a the addresses with the get_shipping_names
function:

<P>
<PRE>    [userdb function=get_shipping_names]
</PRE>
<P>
By default, they are placed in the variable <CODE>address_book</CODE>. Here is a little snippet that builds a select box:

<P>
<PRE>    &lt;FORM ACTION=&quot;[process-target]&quot; METHOD=POST&gt;
    [userdb function=get_shipping_names]
    [if value address_book]
    &lt;SELECT NAME=&quot;s_nickname&quot;&gt;
    [loop arg=&quot;[value address_book]&quot;] &lt;OPTION&gt; [loop-code] [/loop]
    &lt;/SELECT&gt;
    &lt;INPUT TYPE=submit NAME=mv_check VALUE=&quot;Recall Shipping&quot;&gt;
    &lt;/FORM&gt;
</PRE>
<P>
The same principle works with accounts , carts, and preferences.

<P>
To restore a cart based on the above, you can place in an <CODE>mv_check</CODE>
routine:

<P>
<PRE>    [set Recall Shipping]
    mv_todo=return
    mv_nextpage=ord/basket
    [userdb function=get_shipping nickname=&quot;[value s_nickname]&quot;]
    [/set]
</PRE>
<P>
When the mv_check variable is encountered, the contents of the scratch
variable <CODE>Recall Shipping</CODE> are processed and the shipping address information inserted into the user
form values. This is destructive of any current values of those user
session variables, of course.

<P>
If you want to change the fields that are recalled or saved, you can use
the <A HREF="#item_shipping">shipping</A> parameter:

<P>
<PRE>    [userdb function=get_shipping
            nickname=city_and_state
            shipping=&quot;city state&quot;]
</PRE>
<P>
Only the values of the <CODE>city</CODE> and <A HREF="#item_state">state</A> variables will be replaced.

<P>
<HR>


code: 16.06
section: USER_DATABASE
type: item
title: Accounts Book

<A NAME="Accounts_Book">Accounts Book</A></H2>
<P>
The accounts book saves information relevant to billing the order. By
default these form values are included:

<P>
<PRE>   b_nickname
   b_name
   b_address
   b_city
   b_state
   b_zip
   b_country
   b_phone
   mv_credit_card_type
   mv_credit_card_exp_month
   mv_credit_card_exp_year
   mv_credit_card_info
</PRE>
<P>
The values are saved with the <CODE>[userdb function=set_billing]</CODE> tag call, and are recalled with <CODE>[userdb function=get_billing]</CODE>. 
<FONT SIZE=-1>A</FONT> list of the keys available is kept in the form value <CODE>accounts</CODE>, suitable for iteration in an 
<FONT SIZE=-1>HTML</FONT> select box or in a set of links.

<P>
<HR>


code: 16.07
section: USER_DATABASE
type: item
title: Controlling page access with UserDB

<A NAME="Controlling_page_access_with_Use">Controlling page access with UserDB</A></H2>
<P>
You can implement a simple access control scheme with the MiniVend user
database. Controlled pages must reside in a directory which has a file
named <CODE>.access</CODE> that is zero bytes in length. (If it is more than 0 bytes, then only the <EM>RemoteUser</EM> or <EM>MasterHost</EM> may access files in that directory.)

<P>
Set the following variables in <CODE>catalog.cfg</CODE>:

<P>
<PRE>    Variable   MV_USERDB_ACL_TABLE  userdb
    Variable   MV_USERDB_ACL_COLUMN acl
</PRE>
<P>
The <CODE>MV_USERDB_ACL_TABLE</CODE> is the table which controls access, and likewise the <CODE>MV_USERDB_ACL_TABLE</CODE> names the column in that database which will be checked for authorization.

<P>
The database entry should contain the complete MiniVend-style page name of
the page to be allowed. It will not match substrings.

<P>
For example, if the user <CODE>flycat</CODE> followed this link:

<P>
<PRE>    &lt;A HREF=&quot;[area cartcfg/master_edit]&quot;&gt;Edit&lt;/A&gt;
</PRE>
<P>
Access would be allowed if the contents of the userdb were:

<P>
<PRE>    code    acl
    flycat  cartcfg/master_edit
</PRE>
<P>
and disallowed if it were:

<P>
<PRE>    code    acl
    flycat  cartcfg/master_editor
</PRE>
<P>
You can enable access with:

<P>
<PRE>    [userdb function=set_acl location=&quot;cartcfg/master_edit&quot;]
</PRE>
<P>
and disallow access with:

<P>
<PRE>    [userdb function=set_acl
            delete=1
            location=&quot;cartcfg/master_edit&quot;]
</PRE>
<P>
Of course a pre-existing database with the 
<FONT SIZE=-1>ACL</FONT> values will work as well; it need not be in the
UserDB setup.

<P>
<HR>


code: 16.07
section: USER_DATABASE
type: item
title: Preferences

<A NAME="Preferences">Preferences</A></H2>
<P>
Preferences are miscellaneous session information. They include by default
the fields:

<P>
<PRE>    email
    fax
    phone_night
    fax_order
</PRE>
<P>
The field p_nickname acts as a key to select the preference set. You can
change the values that are included with the <CODE>preferences</CODE> parameter: [userdb function=set_preferences preferences=``email_copy email
fax_order fax'']

<P>
<HR>


code: 16.08
section: USER_DATABASE
type: item
title: Carts

<A NAME="Carts">Carts</A></H2>
<P>
You may save or recall the contents of shopping carts in much the same
fashion. See the <STRONG>simple</STRONG> demo application <CODE>ord/basket.html</CODE> page for an example.

<P>
<HR>


code: 17.00
section: USER_DATABASE
type: overview
title: USER DATABASE

<A NAME="USER_DATABASE">USER DATABASE</A></H1>
<P>
MiniVend has a user database function which allows customers to save any
pertinent values from their session. It also allows the setting of database
or file access control lists for use in controlling access to pages and
databases on a user-by-user basis.

<P>
The database field names in the user database correspond with the form
variable names in the user session. If you have a column named <CODE>address</CODE>, then when the user logs in the contents of that field will be placed in
the form variable <CODE>address</CODE>, and will then be availabe for display with <CODE>[value address]</CODE>. Similarly, the database value is available with
<CODE>[data table=userdb column=address key=username]</CODE>.

<P>
The 
<FONT SIZE=-1>ASCII</FONT> file for the database will not reflect changes
unless you export the file with <CODE>[tag export userdb][/tag]</CODE>. It is not advisable to edit the 
<FONT SIZE=-1>ASCII</FONT> file, as it will overwrite the real data that is in the 
<FONT SIZE=-1>DBM</FONT> table; user logins and changes would be lost. (This would not happen with 
<FONT SIZE=-1>SQL,</FONT> but editing the 
<FONT SIZE=-1>ASCII</FONT> file would have no effect.) You should probably set the
 <EM>NoImport</EM> configuration directive accordingly.

<P>
This section describes the user database in MiniVend 3.12. Prior to 3.12,
the user database was a demonstration add-on module with a global
subroutine interface. Some of the concepts were the same; the module
interface is much the same; and page code based on the previous version
should work if the <CODE>userdb.cfg</CODE> file is still there.

<P>
The field names to be used are not set in concrete; they may be changed
with options, and fields may be added or subtracted at any time. Most users
will choose to keep the default demo fields for simplicity sake, as they
cover most common needs. As distributed in the demo, the fields are:

<P>
<PRE>    code
    accounts
    acl
    address
    address_book
    b_address
    b_city
    b_country
    b_name
    b_nickname
    b_phone
    b_state
    b_zip
    carts
    city
    country
    db_acl
    email
    email_copy
    fax
    fax_order
    file_acl
    mv_credit_card_exp_month
    mv_credit_card_exp_year
    mv_credit_card_info
    mv_credit_card_type
    mv_shipmode
    name
    order_numbers
    p_nickname
    password
    phone_day
    phone_night
    preferences
    s_nickname
    state
    time
    zip
</PRE>
<P>

<FONT SIZE=-1>A</FONT> few of those fields are special in naming, though all can be changed via an option. 
<FONT SIZE=-1>A</FONT> couple of the fields are reserved for Minivend's use.


<P>
<STRONG>IMPORTANT NOTE:</STRONG> If you are not running with 
<FONT SIZE=-1>PGP</FONT> or other encryption for your credit card numbers, which should 
<FONT SIZE=-1>NEVER</FONT> be done anyway, then it is important that you remove the mv_credit_card_info field from the database.
 

<P>
The special database fields are:

<P>
<PRE>    accounts         Storage for billing accounts book
    address_book     Storage for shipping address book
    b_nickname       Nickname of current billing account
    carts            Storage for shopping carts
    p_nickname       Nickname for current preferences
    preferences      Storage for preferences
    s_nickname       Nickname for current shipping address
    db_acl           Storage for database access control lists
    file_acl         Storage for file access control lists
    acl              Storage for simple integrated access control
</PRE>
<P>
If not defined, the corresponding capability is not available.

<P>

<FONT SIZE=-1>NOTE:</FONT> The fields <CODE>accounts</CODE>, <CODE>address_book</CODE>, <A HREF="#item_carts">carts</A>, and <CODE>preferences</CODE> should be defined as a 
<FONT SIZE=-1>BLOB</FONT> type if you are using 
<FONT SIZE=-1>SQL.</FONT> This is also suggested for the acl fields if those lists could be large.


<P>
Reserved fields include:

<P>
<PRE>    code        The username (key for the database)
    password    Password storage
    time        Last time of login
</PRE>
<P>
<HR>


code: 17.02
section: TRACKING_AND_BACKEND_ORDER_ENTRY
type: item
title: Custom Order Routing

<A NAME="Custom_Order_Routing">Custom Order Routing</A></H2>
<P>
MiniVend can send order emails and perform custom credit card charges
and/or logging for each individual item. The <EM>Route</EM> directive is used to control this behavior, along with the <CODE>mv_order_route</CODE> item attribute and <CODE>mv_order_route</CODE> form variable.

<P>
Routes are established with the Route directive, which is similar to the
Locale directive. Each route is like a locale, in that you can set
key-value pairs. Here is an example setting:

<P>
<PRE>    Route  VEN  pgp_key         0x67798115
    Route  VEN  email           orders@minivend.com
    Route  VEN  reply           service@minivend.com
    Route  VEN  encrypt         1
    Route  VEN  encrypt_program &quot;/usr/bin/pgpe -fat -q -r %s&quot;
    Route  VEN  report          etc/report_mail
</PRE>
<P>
This route would be used whenever the value <CODE>VEN</CODE> was contained in the form variable <CODE>mv_order_route</CODE>.

<P>
The last route that is defined provides the defaults for all other routes.
For example, if <A HREF="#item_encrypt_program">encrypt_program</A> is set there then the same value will be the default for all routes.

<P>
The attributes that can be set are:

<DL>
<DT><STRONG><A NAME="item_attach">attach</A></STRONG><DD>

Determines whether the order report should be attached to the main order report email. This is useful if you must print certain items separately from others, perhaps for 
<FONT SIZE=-1>FAX</FONT> to a fulfilment house.


<P><DT><STRONG><A NAME="item_counter">counter</A></STRONG><DD>

The location of a counter file which should be used instead of <CODE>OrderCounter</CODE> for this route. It will generate a different value for <CODE>mv_order_number</CODE> for the route.

<P><DT><STRONG><A NAME="item_credit_card">credit_card</A></STRONG><DD>

Determines whether credit card encryption should be done for this order.
Either this or <A HREF="#item_encrypt">encrypt</A> should always be set.

<P><DT><STRONG><A NAME="item_cybermode">cybermode</A></STRONG><DD>

If this is set, enables <EM>CyberCash</EM> for the route. You can also set the variables 
<FONT SIZE=-1>CYBER_CONFIGFILE,</FONT> 
<FONT SIZE=-1>CYBER_SECRET,</FONT> and all other normal 
<FONT SIZE=-1>CYBERCASH</FONT> variables. For example:


<P>
<PRE>    Route VEN cybermode         mauthonly
    Route VEN CYBER_CONFIGFILE  config/vendor1_cfg
    Route VEN CYBER_VERSION     3.2
</PRE>
<P><DT><STRONG>email</STRONG><DD>

The email <CODE>address(es)</CODE> where the order should be sent. Set just
like the <EM>MailOrderTo</EM> directive, which is also the default.

<P><DT><STRONG><A NAME="item_encrypt">encrypt</A></STRONG><DD>

Whether the <STRONG>entire order</STRONG> should be encrypted with the <STRONG>encrypt_program</STRONG>. If <A HREF="#item_credit_card">credit_card</A> is set, then the credit card will first be encrypted, then the entire order
encrypted.

<P><DT><STRONG><A NAME="item_encrypt_program">encrypt_program</A></STRONG><DD>

The encryption program incantaton which should be used. Set identically to
the <EM>EncryptProgram</EM> directive, except that <A HREF="#item__s">%s</A> will be replaced with the <A HREF="#item_pgp_key">pgp_key</A>. Default is <CODE>pgpe -fat -r %s</CODE>.

<P><DT><STRONG><A NAME="item_errors_to">errors_to</A></STRONG><DD>

Sets the <CODE>Errors-To:</CODE> email header so that bounced orders will go to the proper address. Default
is the same as <EM>MailOrderTo</EM>.

<P><DT><STRONG><A NAME="item_increment">increment</A></STRONG><DD>

Whether the order number should be incremented as a result of this result.
Default is not to increment, as the order number should usually be the same
for different routes within the same customer order.

<P><DT><STRONG><A NAME="item_individual_track">individual_track</A></STRONG><DD>


<FONT SIZE=-1>A</FONT> <EM>directory</EM> where individual order tracking files will be placed. The file name will
correspond to the value of <CODE>mv_order_number</CODE>. This can be useful for batching orders via download.

<P><DT><STRONG><A NAME="item_pgp_cc_key">pgp_cc_key</A></STRONG><DD>

The 
<FONT SIZE=-1>PGP</FONT> key <EM>selector</EM> that is used to determine which public key is used for encryption of credit cards only. With 
<FONT SIZE=-1>PGP</FONT> 5 and 6, you can see appropriate values by using the command
 <CODE>pgpk -l</CODE>.

<P><DT><STRONG><A NAME="item_pgp_key">pgp_key</A></STRONG><DD>

The 
<FONT SIZE=-1>PGP</FONT> key <EM>selector</EM> that is used to determine which public key is used for encryption. If <A HREF="#item_pgp_cc_key">pgp_cc_key</A> is set, that key will be used for credit card encryption instead of <A HREF="#item_pgp_key">pgp_key</A>. With 
<FONT SIZE=-1>PGP</FONT> 5 and 6, you can see appropriate values by using
the command <CODE>pgpk -l</CODE>.

<P><DT><STRONG><A NAME="item_profile">profile</A></STRONG><DD>

The custom order profile which should be performed to check the order. If
it fails, then the route will not be performed. See <EM>OrderProfile</EM> and <EM>mv_order_profile</EM>.

<P><DT><STRONG><A NAME="item_receipt">receipt</A></STRONG><DD>

The receipt page that should be used for this routing. This only makes
sense if <STRONG>supplant</STRONG> is set for the route.

<P><DT><STRONG><A NAME="item_report">report</A></STRONG><DD>

The report page that should be used for this routing. If <A HREF="#item_attach">attach</A> is defined, then the contents of the report will be placed in a 
<FONT SIZE=-1>MIME</FONT> attachment in the main order report.

<P><DT><STRONG><A NAME="item_reply">reply</A></STRONG><DD>

The <CODE>Reply-To</CODE> header that should be set. Default is the same as <A HREF="#item_email">email</A>.

<P>
If there are only word characters (A-Za-z0-9 and underscore) then it
describes a MiniVend variable name where the address can be found.

<P><DT><STRONG><A NAME="item_supplant">supplant</A></STRONG><DD>

Whether this route should supplant the main order report. If set, the <EM>AsciiTrack</EM> operation will use this route and the normal MiniVend order email sequence
will not be performed.

<P><DT><STRONG><A NAME="item_track">track</A></STRONG><DD>

The name of a file which should be used for tracking. If the
<A HREF="#item_supplant">supplant</A> attribute is set, then the normal order tracking will be used as well.

<P><DT><STRONG>track</STRONG><DD>


<FONT SIZE=-1>A</FONT> number representing the mode to change either <A HREF="#item_track">track</A> or
<A HREF="#item_individual_track">individual_track</A> files to.

<P></DL>
<P>
An individual item routing causes all items labeld with that route to be
placed in a special sub-cart which will be used for the order report. This
means that the <CODE>[item-list] LIST [/item-list]</CODE> will only contain those items, allowing operations to be performed on
subsets of the complete order.

<P>
Here is an example of an order routing:

<P>
<PRE>    Route  HARD  pgp_key          0x67798115
    Route  HARD  email            hardgoods@minivend.com
    Route  HARD  reply            service@minivend.com
    Route  HARD  encrypt          1
    Route  HARD  encrypt_program  &quot;/usr/bin/pgpe -fat -q -r %s&quot;
    Route  HARD  report           etc/report_mail
                                 
    Route  SOFT  email            &quot;&quot;
    Route  SOFT  profile          create_download_link
    Route  SOFT  empty            1
</PRE>
<P>
<PRE>    Route  main  cybermode        mauthonly
    Route  main  CYBER_VERSION    3.2
    Route  main  CYBER_CONFIGFILE etc/cybercash.cfg
    Route  main  pgp_key          0x67798115
    Route  main  email            orders@minivend.com
    Route  main  reply            service@minivend.com
    Route  main  encrypt          1
    Route  main  encrypt_program  &quot;/usr/bin/pgpe -fat -q -r %s&quot;
    Route  main  report           etc/report_all
 
To tell MiniVend that order routing is in effect, the variable
mv_order_route is set on the B&lt;final&gt; order submission form:
</PRE>
<P>
<PRE>    &lt;INPUT TYPE=&quot;hidden&quot; NAME=&quot;mv_order_route&quot; VALUE=&quot;main&quot;&gt;
</PRE>
<P>
To set the order routing for individual items, some method of determining
their status must be made and the <CODE>mv_order_route</CODE>
attribute must be set. This could be set at the time of the item being
placed in the basket, or you can have a database field called <CODE>goods_type</CODE> set to the appropriate value. We will use this Perl routine on the final
order form:

<P>
<PRE> [perl arg=carts interpolate=1]
    my $string = &lt;&lt;'EOF';
 [item-list][item-code]  [item-field goods_type]
 [/item-list]
 EOF
    my @items;
    my %route;
    @items = grep /\S/, split /\n+/, $string;
    for(@items) {
        my ($code, $keycode) = split /\t/, $_;
       $route{$code} = $keycode;
    }
    my $cart = $Safe{'carts'}{'main'};
    my $item;
    foreach $item ( @{ $Safe{'carts'}{'main'} } ) {
        $item-&gt;{mv_order_route} = $route{$item-&gt;{'code'}} || undef;
    }
    return '';
 [/perl]
</PRE>
<P>
Now the individual items are labeled with a <CODE>mv_order_route</CODE> value which will cause their inclusion in the appropriate order routing.

<P>
Upon submission of the order form, any item labeled <CODE>HARD</CODE> will be accumulated and sent to the email address <CODE>hardgoods@minivend.com</CODE>, where presumably the item will be pulled from inventory and shipped.

<P>
Any item labeled <CODE>SOFT</CODE> will be passed to the order profile
<CODE>create_download_link</CODE>, which will place it in a staging area for customer download. (This would
be supported by a link on the receipt, perhaps by reading a value set in
the profile).

<P>
The <CODE>main</CODE> order routing will use CyberCash to charge the order, and will be
completely encrypted for emailing.

<P>
<HR>


code: 17.02
section: TRACKING_AND_BACKEND_ORDER_ENTRY
type: item
title: Easy ASCII Tracking

<A NAME="Easy_ASCII_Tracking">Easy ASCII Tracking</A></H2>
<P>
If you set AsciiTrack to a legal file name (based in VendRoot unless it has
a leading ``/''), a copy of the order will be saved there as well as being
emailed.

<P>
If you set AsciiBackend to a legal file name (based in VendRoot unless it
has a leading ``/''), it will save the backend fields defined in 
<EM>BackendOrder</EM> along with the item-code and quantity of items being ordered. The fields are separated by 
<FONT SIZE=-1>TAB</FONT> characters.
 

<P>
For either directive, if the file name string begins with a pipe ``|'', a
program will be run and the output ``piped'' to that program. This allows
easy backend entry of orders with an external program.

<P>
<HR>


code: 17.03
section: TRACKING_AND_BACKEND_ORDER_ENTRY
type: item
title: Database Tracking

<A NAME="Database_Tracking">Database Tracking</A></H2>
<P>
Once the order report is processed, you can be sure the order will
complete. Therefore it is the perfect place to put MiniVend tags that make
order entries in database tables.

<P>

<FONT SIZE=-1>A</FONT> good model is to place a single record in a database
summarizing the order, and a series of lines that correspond to each line
item in the order. This can be in the same database table; if the order
number itself is the key for the summary, you can append a line number to
the order number to show each line of the order.

<P>
The following would summarize a sample order number 
<FONT SIZE=-1>S00001</FONT> for part number 00-0011 and 99-102:

<P>
<PRE>    code     order_number part_number  quantity   price    shipping  tax
    S00001   S00001                    3          2010     12.72     100.50
    S00001-1 S00001       00-0011      2          1000     UPS       yes
    S00001-2 S00001       99-102       1          10       UPS       yes
</PRE>
<P>
You can add fields as appropriate, perhaps with order status, shipping
tracking number, address, customer number, or other information.

<P>
The above can be easily done with MiniVend's <CODE>[import ....]</CODE> tag using the convenient <CODE>NOTES</CODE> format:

<P>
<PRE>    [set import_status]
    [import table=orders type=LINE continue=NOTES]
</PRE>
<P>
<PRE>    code: [value mv_order_number]
    order_number: [value mv_order_number]
    quantity: [nitems]
    price: [subtotal noformat=1]
    shipping: [shipping noformat=1]
    tax: [salestax noformat=1]
</PRE>
<P>
<PRE>    [/import]
  
    [item-list]
    [import table=orders type=LINE continue=NOTES]
</PRE>
<P>
<PRE>    code: [value mv_order_number]-[item-increment]
    order_number: [value mv_order_number]
    quantity: [item-quantity]
    price: [item-price noformat=1]
    shipping: [shipping-description]
    tax: [if-field nontaxable]No[else]Yes[/else][/if]
</PRE>
<P>
<PRE>    [/import][/item-list]
</PRE>
<P>
<HR>


code: 18.00
section: TRACKING_AND_BACKEND_ORDER_ENTRY
type: overview
title: TRACKING AND BACKEND ORDER ENTRY

<A NAME="TRACKING_AND_BACKEND_ORDER_ENTRY">TRACKING AND BACKEND ORDER ENTRY</A></H1>
<P>
MiniVend allows the entry of orders into a system via one of several
methods. The <EM>AsciiBackend</EM> capability allows submittal of parameters to an external order entry script. Support for 
<FONT SIZE=-1>SQL</FONT> allows entry of orders directly into an 
<FONT SIZE=-1>SQL</FONT> database. Orders can be written to an 
<FONT SIZE=-1>ASCII</FONT> file. They can be formatted precisely for email-based systems. The orders can be placed in a 
<FONT SIZE=-1>DBM</FONT> file. Finally, embedded Perl allows completely flexible order entry, including real-time credit-card verification and settlement.


<P>
<HR>


code: 18.02
section: MINIVEND_SECURITY
type: item
title: Controlling access to certain pages

<A NAME="Controlling_access_to_certain_pa">Controlling access to certain pages</A></H2>
<P>
If the directory containing the page has a file <CODE>.access</CODE>
and that file is zero bytes long, then access can be gated in one of
several ways.

<OL>
<LI>

If the file <CODE>.access_gate</CODE> is present, it will be read and scanned for page-based access. The file has
the form:

<P>
<PRE>   page: condition
   *: condition
</PRE>
<P>
The <CODE>page</CODE> is the file name of the file to be controlled (the .html extension is
optional); the <CODE>condition</CODE> is either a literal <CODE>Yes/No</CODE>
or MiniVend tags which would produce a <CODE>Yes</CODE> or <CODE>No</CODE> (1/0 work just fine, as do true/false).

<P>
The entry for <CODE>*</CODE> sets the default action if the page name is not found. If you want pages to
be allowed by default, set it to <CODE>1</CODE>
or <CODE>Yes</CODE>. If you want pages to be denied by default in this directory, leave blank
or set to <CODE>No</CODE>. Here is an example, for the directory <CODE>controlled</CODE>, having the following files:

<P>
<PRE>  -rw-rw-r--   1 mike     mike            0 Jan  8 14:19 .access
  -rw-rw-r--   1 mike     mike          185 Jan  8 16:00 .access_gate
  -rw-rw-r--   1 mike     mike          121 Jan  8 14:59 any.html
  -rw-rw-r--   1 mike     mike          104 Jan  8 14:19 bar.html
  -rw-rw-r--   1 mike     mike          104 Jan  8 14:19 baz.html
  -rw-rw-r--   1 mike     mike          104 Jan  8 14:19 foo.html
</PRE>
<P>
The contents of <CODE>.access_gate</CODE>:

<P>
<PRE>    foo.html: [if session username eq 'flycat']
                Yes
              [/if]
    bar:      [if session username eq 'flycat']
              [or scratch allow_bar]
                Yes
              [/if]
    baz:      yes
    *:        [data session logged_in]
</PRE>
<P>
The page <CODE>controlled/foo</CODE> is only allowed for the logged-in user
<STRONG>flycat</STRONG>.

<P>
The page <CODE>controlled/bar</CODE> is allowed for the logged-in user
<STRONG>flycat</STRONG>, or if the scratch variable <CODE>allow_bar</CODE> is set to a non-blank, non-zero value.

<P>
The page <CODE>controlled/baz</CODE> is always allowed for display.

<P>
The page <CODE>controlled/any</CODE> (or any other page in the directory not named in <CODE>.access_gate</CODE>) will be allowed for any user logged in via <EM>UserDB</EM>.

<P>

<FONT SIZE=-1>NOTE:</FONT> The <CODE>.access_gate</CODE> scheme is available for database access checking if the database is defined
as an <EM>AdminDatabase</EM>. The <CODE>.access_gate</CODE>
file is located in <EM>ProductDir</EM>.

<P><LI>

If the <EM>Variable</EM>  <CODE>MV_USERDB_REMOTE_USER</CODE> is set (non-zero and non-blank) then any user logged in via the UserDB
feature will receive access to all pages in the directory.

<P>

<FONT SIZE=-1>NOTE:</FONT> If there is a <CODE>.access_gate</CODE> file, it overrides this.

<P><LI>

If the variables <CODE>MV_USERDB_ACL_TABLE</CODE> is set to a valid database identifier, the <EM>UserDB</EM> module can control access with simple 
<FONT SIZE=-1>ACL</FONT> logic. See <EM>USER DATABASE</EM>.

<P>

<FONT SIZE=-1>NOTE:</FONT> If there is a <CODE>.access_gate</CODE> file, it overrides this. Also, if 
<FONT SIZE=-1>MV_USERDB_REMOTE_USER</FONT> is set, then this capability is
not available.

<P></OL>
<P>
<HR>


code: 18.02
section: MINIVEND_SECURITY
type: item
title: SSL support

<A NAME="SSL_support">SSL support</A></H2>
<P>
MiniVend has several features that enable secure ordering via 
<FONT SIZE=-1>SSL</FONT> (Secure Sockets Layer). Despite their mystique, 
<FONT SIZE=-1>SSL</FONT> servers are actually quite easy to operate. The difference between the standard 
<FONT SIZE=-1>HTTP</FONT> server and the 
<FONT SIZE=-1>SSL</FONT> 
<FONT SIZE=-1>HTTPS</FONT> server, from the standpoint of the user, is only in the encryption and the specification of the 
<FONT SIZE=-1>URL</FONT> -- https: is used for the 
<FONT SIZE=-1>URL</FONT> protocol specification instead of the usual http: designation.


<P>
<STRONG>IMPORTANT NOTE:</STRONG>  MiniVend attempts to perform operations securely, but no guarantees or warranties of any kind are made! Since MiniVend comes with Perl source, it is possible to modify the program to create bad security problems. One way to minimize this possibility is to record digital signatures, using 
<FONT SIZE=-1>MD5</FONT> or 
<FONT SIZE=-1>PGP,</FONT> of
 <CODE>minivend</CODE>, <CODE>minivend.cfg</CODE>, and all modules included in minivend. Check them on a regular basis to
ensure they have not been changed.

<P>
MiniVend uses the <EM>SecureURL</EM> directive to set the base 
<FONT SIZE=-1>URL</FONT> for secure transactions, and the <EM>VendURL</EM> directive for normal non-secure transactions. Secure URLs can be enabled
for forms through a form action of 
<CODE>[process-target secure=1]</CODE>. An individual page can be displayed via 
<FONT SIZE=-1>SSL</FONT> with <CODE>[page href=mvstyle_pagename secure=1]</CODE>. 
<FONT SIZE=-1>A</FONT> certain page can be set to be always secure with the <CODE>AlwaysSecure</CODE> catalog.cfg directive.

<P>
MiniVend incorporates additional security for credit card numbers. The
field <STRONG>mv_credit_card_number</STRONG> will not ever be written to disk.

<P>
To enable automated encryption of the credit card information, you need to
define the directive <EM>CreditCardAuto</EM> to <EM>yes</EM>. <EM>EncryptProgram</EM>
also needs to be defined with some value, one which will, with hope, encrypt the number. 
<FONT SIZE=-1>PGP</FONT> is now recommended above all other encryption program. The entries should look something like:


<P>
<PRE>  CreditCardAuto   Yes
  EncryptProgram   /usr/bin/pgpe -fat -r sales@company.com
</PRE>
<P>
See <EM>CreditCardAuto</EM> for more information on how to set the form variables.

<P>
<HR>


code: 18.03
section: MINIVEND_SECURITY
type: item
title: Administrative Pages

<A NAME="Administrative_Pages">Administrative Pages</A></H2>
<P>
With MiniVend's <EM>GlobalSub</EM> capability, very complex add-on schemes can be implemented with Perl
subroutines. And with the new writable database, pages that modify the
catalog data can be made. If you mark a page as an <EM>AdminPage</EM>, only the catalog administrator may use it. See <EM>MasterHost</EM>, <EM>RemoteUser</EM>, and
<EM>Password</EM>.

<P>
In addition, you can create a file in any MiniVend page subdirectory called
.access. If that file is present and non-zero in size, any pages in that
directory are only available to the catalog administrator.

<P>
<HR>


code: 19.00
section: MINIVEND_SECURITY
type: overview
title: MINIVEND SECURITY

<A NAME="MINIVEND_SECURITY">MINIVEND SECURITY</A></H1>
<P>
<HR>


code: 19.02
section: CONTROLLING_PAGE_APPEARANCE
type: item
title: Body and Buttonbar Control

<A NAME="Body_and_Buttonbar_Control">Body and Buttonbar Control</A></H2>
<P>
MiniVend provides centralized page color and imagemap control through use
of the <CODE>[body n]</CODE> and <CODE>[buttonbar n]</CODE> elements. It also can place a random message from a series of messages with
the <CODE>[random]</CODE> element, and embed help messages with the <CODE>[help item]</CODE> element.

<P>
The <CODE>[body n]</CODE> element selects a color scheme -- numbered from 1 to 15 -- that is set by the Mv_Background, Mv_TextColor, Mv_BgColor, Mv_LinkColor, and Mv_VlinkColor directives. Each can contain up to 15 parameters, after an opening 
<FONT SIZE=-1>BEGIN.</FONT> Here is an example:


<P>
<PRE>    Mv_Background  BEGIN /images/blue_pap.gif
    Mv_BgColor     BEGIN none steelblue white
    Mv_LinkColor   BEGIN none white black
    Mv_TextColor   BEGIN none ltgreen blue
    Mv_VlinkColor  BEGIN none orange purple
</PRE>
<P>
The above sequence set in the catalog.cfg file, defines three color
schemes, accessed with <CODE>[body 1]</CODE>, <CODE>[body 2]</CODE>, and <CODE>[body 3]</CODE> elements in MiniVend pages. The first scheme uses the file <CODE>/images/blue_pap.gif</CODE>
as the background pattern, and keeps the user's default colors for
everything else. It is called by a <CODE>[body 1]</CODE> element, which when expanded becomes 
<FONT SIZE=-1>&lt;BODY</FONT> BACKGROUND=``/images/blue_pap.gif&gt;.

<P>

<FONT SIZE=-1>NOTE:</FONT> To be compatible with 
<FONT SIZE=-1>HTML</FONT> editors, it is recommended you use the 
<FONT SIZE=-1>HTML</FONT> syntax for this tag:


<P>
<PRE>        &lt;BODY MV=&quot;body 1&quot;&gt;
</PRE>
<P>
All references to <CODE>[body N]</CODE> can be assumed to mean this call.

<P>
If an extra bit of text is included after the scheme number, then it will
be appended to the body tag. This allows JavaScript and other things to be
inserted. It is appended, and for most browsers this means that previous
definitions made by the numbered scheme will be overridden.

<P>
The second scheme defines no background pattern (there is only one file in
the Mv_Background directive), but defines a background color of <CODE>steelblue</CODE>, with a text color of white, a link color of light green, and a visited
link color of orange. It is accessed by the <CODE>[body 2]</CODE> element, which when expanded becomes 
<FONT SIZE=-1>&lt;BODY</FONT> BGCOLOR=``steelblue'' TEXT=``white''
LINK=``ltgreen'' VLINK=``orange''&gt;.

<P>
The third color scheme is similar to the second, except defines
white-black-blue-purple for the four colors. It is accessed with a <CODE>[body 3]</CODE> element.

<P>
If there is no defined scheme for a body element (as there wouldn't be if
you put <CODE>[body 4]</CODE> in a page with the above schemes defined) MiniVend simply outputs a standard 
<FONT SIZE=-1>&lt;BODY&gt;</FONT> tag.


<P>

<FONT SIZE=-1>NOTE:</FONT> [buttonbar] is deprecated in favor of <EM>Variable</EM>.

<P>
Image maps can be supplied and similarly controlled with the <CODE>[buttonbar n]</CODE>
series of tags. They are defined with the ButtonBars directive in catalog.cfg, and take the form of a series of file names in MiniVend format -- i.e., relative to the PageDir and without a .html extension. To use the buttonbars, create a file with an 
<FONT SIZE=-1>IMG</FONT> directive set with the 
<FONT SIZE=-1>USEMAP</FONT> element and an associated client-side image map (defined with &lt;

<FONT SIZE=-1>MAP&gt;</FONT> &lt;
<FONT SIZE=-1>/MAP&gt;.</FONT> The <CODE>[areatarget page frame]</CODE>
or <CODE>[area page]</CODE> tags are used to set the URLs. An example:

<P>
<PRE>    &lt;IMG SRC=&quot;/sample/images/artbar0.gif&quot; USEMAP=&quot;#ARTBAR0&quot;&gt;
    &lt;MAP NAME=ARTBAR0&gt;
    &lt;AREA COORDS=&quot;198,0,278,20&quot; HREF=&quot;[areatarget fr_sel search]&quot;&gt;
    &lt;AREA COORDS=&quot;303,0,363,20&quot; HREF=&quot;[areatarget fr_search search]&quot;&gt;
    &lt;AREA COORDS=&quot;388,0,442,20&quot; HREF=&quot;[areatarget fr_greet main]&quot;&gt;
    &lt;AREA COORDS=&quot;473,0,537,20&quot; HREF=&quot;[areatarget control main]&quot;&gt;
    &lt;AREA COORDS=&quot;0,0,560,20&quot; NOHREF&gt;
    &lt;/MAP&gt;
</PRE>
<P>
If the above were saved in the file PageDir/bars/artbar0.html (where
PageDir is your MiniVend pages directory), you would be able to access this
imagemap in your pages with a <CODE>[buttonbar 0]</CODE> tag, at least after MiniVend read this line in the configuration file:

<P>
<PRE>    ButtonBars  bars/artbar0 bars/artbar1 bars/artbar2
</PRE>
<P>
The above entry allows you to define three imagemaps and access them in
your pages simply as <CODE>[buttonbar 0]</CODE>, <CODE>[buttonbar 1]</CODE>, and <CODE>[buttonbar 2]</CODE>. The advantage of this scheme is central definition of a series of button
bars with only a few tags -- if you change your page colors or mapping, you
need only change one file and the change will roll over to all of your
catalog pages. Since some installations can number in the thousands of
catalog pages, using the pre-defined buttonbars can save a lot of editing.
(Server-side includes cannot be used to achieve the same thing with
MiniVend, since they wouldn't have the proper URLs.)

<P>
<HR>


code: 19.03
section: CONTROLLING_PAGE_APPEARANCE
type: item
title: In-line Help

<A NAME="In_line_Help">In-line Help</A></H2>
<P>

<FONT SIZE=-1>NOTE:</FONT> This feature is deprecated and should not be
used in new installations.

<P>
The <CODE>[help tag]</CODE> element, in conjunction with the Help directive in the minivend.cfg file,
is similar to the buttonbar tag, except it displays help messages or
images, and is keyed by item name. The help can be contained in any of a
series of files defined in the Help directive. It can contain most MiniVend
elements. The user can turn off help through a form -- see the <CODE>control.html</CODE> file for an example.

<P>
<HR>


code: 19.03
section: CONTROLLING_PAGE_APPEARANCE
type: item
title: Random Banners

<A NAME="Random_Banners">Random Banners</A></H2>
<P>
The <CODE>[random]</CODE> element, in conjunction with the <EM>Random</EM> directive in the catalog.cfg file, is similar to the buttonbar tag, except it displays random messages or images. It can be used to place a random tip, hint, ad, or message, and can be any legal 
<FONT SIZE=-1>HTML</FONT> construct.
 

<P>
<HR>


code: 19.04
section: CONTROLLING_PAGE_APPEARANCE
type: item
title: Rotating Banners

<A NAME="Rotating_Banners">Rotating Banners</A></H2>
<P>
The <CODE>[rotate]</CODE> element, in conjunction with the <EM>Rotate</EM> directive in the minivend.cfg file, is similar to the random tag, except it displays messages or images guaranteed to be presented to the user in a specific order. It can be used to place a tip, hint, ad, or message, and can be any legal 
<FONT SIZE=-1>HTML</FONT> construct.


<P>
<HR>


code: 20.00
section: CONTROLLING_PAGE_APPEARANCE
type: overview
title: CONTROLLING PAGE APPEARANCE

<A NAME="CONTROLLING_PAGE_APPEARANCE">CONTROLLING PAGE APPEARANCE</A></H1>
<P>
MiniVend has several features which help control page appearance.

<P>
<HR>


code: 21.00
section: STATIC_PAGE_BUILDING
type: overview
title: STATIC PAGE BUILDING

<A NAME="STATIC_PAGE_BUILDING">STATIC PAGE BUILDING</A></H1>
<P>
MiniVend now has a complete implementation of a static page building
facility. It allows you to build a parallel page tree <EM>completely in HTML</EM>, and most importantly, keeps track of all of the URLs for you. It means
that MiniVend, whether the page on the browser was called dynamically or
statically, will call the appropriate page for you. This can mean huge
performance gains in catalogs with lots of pages in the browsing structure,
for any statically built pages never have to call MiniVend. This improves
performance and decreases server load.

<P>
You can also use it to build page trees that are scannable by a search
engine spider.

<P>
As of MiniVend 3.03, to make static page building active, you must set the <EM>Static</EM> directive to <CODE>Yes</CODE>. This allows you to turn it on or off with a single directive, and is a
change from MiniVend 3.02 and below.

<P>
It is invoked when starting the MiniVend server by passing the extra
parameters
<CODE>-build shop</CODE> to the minivend program. MiniVend will scan the entire page structure,
testing each page to see if it has any
<EM>dynamic elements</EM>. Dynamic elements are those MiniVend tags which depend on user session
status, like the contents of the shopping cart, conditional tests on user
variables, or databases marked as dynamic with the <EM>DynamicData</EM> directive. If a page has dynamic elements, it will not be built statically.

<P>
Some tags which cause static building to fail are:

<P>
<PRE>  [cart ...]           [if session ...]       [perl]
  [checked ...]        [if validcc ...]       [salestax]
  [data ...]*          [if value ...]         [scratch ...]
  [default ...]        [item_list]            [selected ...]
  [discount]           [last_page]            [shipping]
  [finish-order]       [lookup ..]            [shipping_desc]
  [frames_on|off]      [loop-data ...]*       [sql set]
  [if data ...]*       [loop-field ...]*      [subtotal]
  [if discount ...]    [sql set]              [total_cost]
  [if items ...]       [nitems]               [value ...]
  [if scratch ...]     [perl]
</PRE>
<P>
<PRE>  * Only if database referenced is dynamic
</PRE>
<P>
In addition, if a <CODE>[search-list]</CODE> references dynamic items, it will also prevent a search from being cached
or built statically.

<P>
Pages are also searched for static <CODE>[page scan se=...]</CODE> searches, and those searches are built statically if appropriate. They are
placed in the pages scan1.html on up, so don't name any of your pages scan
and then digits if you want to avoid clashing. Search builds recurse one
level down, meaning that if you have a category search that yields more
category searches, they will also be built. You can set the recursion with <EM>StaticDepth</EM> -- the default is two.

<P>

<FONT SIZE=-1>A</FONT> page marked as an <EM>AdminPage</EM> or <EM>NoCache</EM> will not be statically built or cached.

<P>
If you wish a page to build statically anyway, despite the presence of
dynamic elements, you can insert <CODE>[tag flag build][/tag]</CODE> at the top of the page. This tells the builder to ignore dynamic elements
and build the page anyway -- it will not override NoCache or AdminPage.

<P>
Additionally if you pass a name with <CODE>[tag flag build]</CODE><STRONG>name</STRONG><CODE>[/tag]</CODE>, a symbolic link to <STRONG>name</STRONG> will be made in <EM>StaticDir</EM>. This allows named pages to be reliably found -- otherwise the name of the
page varies with the order the search is found. Commonly you would use
<CODE>[tag flag build][value mv_searchspec][/tag]</CODE> to build a link based on the search string.

<P>
Pages are marked for static build in one of three ways:

<UL>
<LI>

If you want all pages to be statically built when possible, set the
<EM>catalog.cfg</EM> directive <EM>StaticAll</EM> to yes. MiniVend will scan all pages and see if they can be built. If you
have pages and/or directories which you don't want scanned, use the <EM>NoCache</EM> directive to disable it.

<P><LI>

If you want only certain pages to be statically built, you can either
individually mark each one with the <EM>StaticPage</EM> directive, or you may set a <EM>StaticPattern</EM> which encompasses pages to be built statically.

<P><LI>

You can place a list of pages in the file <CODE>.build</CODE> in the root of the pages directory. MiniVend will use that as the list of
pages to be built on this run.

<P></UL>
<P>
In addition, you can build all possible on-the-fly pages out of the
database if the <EM>StaticFly</EM> directive is set. This <STRONG>is</STRONG> subject to the <EM>StaticPattern</EM> as well, so you could build only a portion of the database if you wished.
Obviously catalogs that have many thousands of items should be careful
about use of <EM>StaticFly</EM>.

<P>
The names of pages that are statically built are maintained in the file
<CODE>.static</CODE>, located in the MiniVend <EM>PageDir</EM>. This is how MiniVend knows which pages should be referenced with static
URLs.

<P>
Any pages included in the <CODE>list(s)</CODE> that fail due to dynamic
elements have their names placed in the file <CODE>.unbuilt</CODE> after the build process.

<P>
The <EM>StaticDir</EM> directive defines the <STRONG>file path</STRONG> to the root of the page structure that will be built. If blank, it will use
the directory <CODE>static</CODE> in the catalog root, which can then be copied to the appropriate place in 
<FONT SIZE=-1>HTML</FONT> document space.

<P>
<STRONG>WARNING:</STRONG> Any existing files that are present may be removed from this directory! Do
not place normal pages there!

<P>
The <EM>StaticPath</EM> directive defines the <STRONG>URL path</STRONG> to the root of the page structure that will be built. It is relative to 
<FONT SIZE=-1>HTTP</FONT> document root, and must obviously be the 
<FONT SIZE=-1>URL</FONT> path to
 <EM>StaticDir</EM>. Default is /, or DocumentRoot.

<P>
The <EM>StaticSuffix</EM> directive defines the suffix of the files that will be built. The default
is <CODE>.html</CODE>. DOSites might want to make it <CODE>.htm</CODE>, and if you wished to have the files parsed for server side includes you
might use <CODE>.shtml</CODE>.

<P>
If you wish to build the catalog pages offline (recommended on servers that
are used by multiple catalogs), you can use the command:

<P>
<PRE>   start -test -build shop
</PRE>
<P>
where <CODE>shop</CODE> is the name of the catalog to be built. (Multiple <CODE>-build name</CODE>
directives can be used to build more than one catalog.)

<P>
<HR>


code: 21.02
section: INTERNATIONALIZATION
type: item
title: Setting the locale

<A NAME="Setting_the_locale">Setting the locale</A></H2>
<P>
The locale could be set to <CODE>fr_FR</CODE> (French for France) in one of two ways:

<DL>
<DT><STRONG><A NAME="item__setlocale">[setlocale locale=locale* currency=locale* persist=1*]</A></STRONG><DD>

This tag is for new-style tags only and will not work for <CODE>[old]</CODE>.

<P>
Immediately sets the locale to <CODE>locale</CODE>, and will cause it to persist in future user pages if the <CODE>persist</CODE> is set to a non-zero, non-blank value. If the <CODE>currency</CODE> attribute is set, modifies the pricing and currency-specific locale keys
and MiniVend configuration directives to that locale. If there are no
arguments, sets it back to the user's default locale as defined in the
scratch variables <CODE>mv_locale</CODE> and
<CODE>mv_currency</CODE>.

<P>
This allows:

<P>
<PRE>    Dollar Pricing:
</PRE>
<P>
<PRE>    [setlocale en_US]
    [item-list]
    [item-code]: [item-price]&lt;BR&gt;
    [/item-list]
</PRE>
<P>
<PRE>    Franc Pricing:
</PRE>
<P>
<PRE>    [setlocale fr_FR]
    [item-list]
    [item-code]: [item-price]&lt;BR&gt;
    [/item-list]
</PRE>
<P>
<PRE>    [comment] Return to the user's default locale [/comment]
    [setlocale]
</PRE>
<P>
This tag is only available in new mode (``NewTags Yes'' or <CODE>[new]</CODE>).

<P><DT><STRONG>[page process/locale/fr_FR/page/catalog]</STRONG><DD>

This is the same as <CODE>[page catalog]</CODE>, except when the link is followed it will set the locale to <CODE>fr_FR</CODE> before displaying the page. This is persistent.

<P><DT><STRONG>[page process/locale/fr_FR/currency/en_US/page/catalog]</STRONG><DD>

This is the same as <CODE>[page catalog]</CODE>, except when the link is followed it will set the locale to <CODE>fr_FR</CODE> and the pricing/number display to the locale <CODE>en_US</CODE> before displaying the page. This is persistent.

<P></DL>
<P>
Once the locale is persistently set for a user, it is in effect for the
duration of their session.

<P>
<HR>


code: 21.03
section: INTERNATIONALIZATION
type: item
title: MiniVend Locale Settings

<A NAME="MiniVend_Locale_Settings">MiniVend Locale Settings</A></H2>
<P>
The <CODE>Locale</CODE> directive has many possible settings, allowing complete
internationalization of page sets and currencies. The
<CODE>Locale</CODE> directive is defined in a series of key/value pairs, with a key (which
contains word characters only) followed by a value. The value should be
surrounded with double quotes if it contains whitespace. In this example,
the key is <CODE>Value setting</CODE>.

<P>
<PRE>    Locale fr_FR &quot;Value setting&quot; &quot;Configuration de valeur&quot;
    Locale de_DE &quot;Value setting&quot; Werteinstellung
</PRE>
<P>
When accessed via the special tag <CODE>[L]Value setting[/L]</CODE>, the value <CODE>Configuration de valeur</CODE> will be displayed <STRONG>only</STRONG> if the locale is set to <CODE>fr_FR</CODE>. If the locale is set to <CODE>de_DE</CODE>, the string <CODE>Werteinstellung</CODE> will be displayed. If it is neither, the default value of <CODE>Value setting</CODE> will be displayed.

<P>
The 
<FONT SIZE=-1>L</FONT> and 
<FONT SIZE=-1>/L</FONT> must be capitalized -- this is done for speed of processing as well as easy differentiation in text.


<P>
For longer series of strings, the configuration file recognizes:

<P>
<PRE>    Locale fr_FR &lt;&lt;EOF
    {
        &quot;Value setting&quot;,
        &quot;Configuration de valeur&quot;,
</PRE>
<P>
<PRE>        &quot;Search&quot;,
        &quot;Recherche&quot;
    }
    EOF
</PRE>
<P>
The above sets two string substitutions. As long as this is valid Perl
syntax describing a series of settings, the text will be matched. It can
contain any arbitrary set of characters that don't contain <CODE>[L]</CODE> and <CODE>[/L]</CODE>. If using double quotes, string literals like \n and \t are recognized.

<P>
You can also use a database to set locale information. It is added to any
in the catalog.cfg file, and values in it will overwrite previous settings.
See <EM>LocaleDatabase</EM>.

<P>
The <CODE>[L]default text[/L]</CODE> is set before any other page processing. It is equivalent to the characters
``default text'' or the appropriate Locale translation for all intents and
purposes. Minivend tags and Variable values can be embedded.

<P>
Since the <CODE>[L] message [/L]</CODE> substitution is done before any tag processing, you cannot do <CODE>[L][item-data table field][/L]</CODE> and expect success. There is an add-on <CODE>[loc] message [/loc]</CODE>  <EM>UserTag</EM> supplied with the distribution beginning at 
<FONT SIZE=-1>V3.09.</FONT> It does the same thing as <CODE>[L] [/L]</CODE> except after all tag substitution is done. See <EM>minivend.cfg.dist</EM> for the definition.

<P>
You will need to be quite careful in editing pages with localization
information. Changing even one character of the message will change the key
value and invalidate the message for other languages. To prevent this, you
can instead use:

<P>
<PRE>    [L key]The default.[/L]
</PRE>
<P>
The key <CODE>msg_key</CODE> will then be used to index the message. This may be preferable for many
applications.

<P>

<FONT SIZE=-1>A</FONT> <CODE>localize</CODE> script is included with minivend. It will parse files included on the
command line and produce output that can be easily edited to produce
localized information. Given an existing file, it will merge new
information where appropriate.

<P>
<HR>


code: 21.04
section: INTERNATIONALIZATION
type: item
title: Special Locale keys for price representation

<A NAME="Special_Locale_keys_for_price_re">Special Locale keys for price representation</A></H2>
<P>
MiniVend honors the standard 
<FONT SIZE=-1>POSIX</FONT> keys:

<P>
<PRE>    mon_decimal_point decimal_point 
    mon_thousands_sep thousands_sep 
    currency_symbol   int_currency_symbol
    frac_digits       p_cs_precedes
</PRE>
<P>
See the 
<FONT SIZE=-1>POSIX</FONT> <CODE>setlocale(3)</CODE> man page for more
information.

<P>
These will be used for formatting prices and will approximate the number
format used in most countries. To set the price format to something that is
exactly how you want it, you can use the special keys:

<DL>
<DT><STRONG><A NAME="item_price_picture">price_picture</A></STRONG><DD>

MiniVend will format a currency number based on a ``picture'' given to it.
The basic form is:

<P>
<PRE>    Locale en_US price_picture &quot;$ ###,###,###.##&quot;
</PRE>
<P>
This is the presumably for locale <CODE>en_US</CODE>, the United States, and it would display <CODE>4452.3</CODE> as <CODE>$ 4,445.30</CODE>.

<P>
The same display can be achieved with:

<P>
<PRE>     Locale en_US mon_thousands_sep ,
     Locale en_US mon_decimal_point .
     Locale en_US p_cs_precedes     1
     Locale en_US currency_symbol   $
</PRE>
<P>

<FONT SIZE=-1>A</FONT> common price_picture for European countries would be <CODE>###.###.###,##</CODE>, which would display the same number as <CODE>4.452,30</CODE>. To add a franc notation at the end for the locale <CODE>fr_FR</CODE>, you would use the setting:

<P>
<PRE>    Locale fr_FR price_picture &quot;##.###,## fr&quot;
</PRE>
<P>

<FONT SIZE=-1>IMPORTANT</FONT> 
<FONT SIZE=-1>NOTE:</FONT> The decimal point in use, set by
 <CODE>mon_decimal_point</CODE>, and the thousands separator <CODE>mon_thousands_sep</CODE>  <STRONG>must</STRONG> match the settings in the picture. The <CODE>frac_digits</CODE> setting is not used in this case -- it is derived from the location of the
decimal (if any).

<P>
The same setting for fr_FR above can be achieved with:

<P>
<PRE>     Locale fr_FR mon_thousands_sep .
     Locale fr_FR mon_decimal_point ,
     Locale fr_FR p_cs_precedes     0
     Locale fr_FR currency_symbol   fr
</PRE>
<P>
If the number of digits is greater than the # locations in the picture, the
digits will be changed to asterisks. An overflow number above would show as <CODE>**.***,** fr</CODE>.

<P><DT><STRONG><A NAME="item_picture">picture</A></STRONG><DD>

Same as <A HREF="#item_price_picture">price_picture</A>, but sets the value returned if the <CODE>[currency]</CODE>
tag is not used.

<P>
If the number of digits is greater than the # locations in the picture, the
digits will be changed to asterisks, displaying something like
<CODE>**,***.**</CODE>.

<P></DL>
<P>
<HR>


code: 21.05
section: INTERNATIONALIZATION
type: item
title: Dynamic locale directive changes

<A NAME="Dynamic_locale_directive_changes">Dynamic locale directive changes</A></H2>
<P>
If you set Locale keys corresponding to some MiniVend <CODE>catalog.cfg</CODE> directives, those values will be set when setting the locale.

<DL>
<DT><STRONG><A NAME="item_PageDir">PageDir</A></STRONG><DD>

To use a different page directory for different locales, set the PageDir
key. To have two separate language page sets, French and English, you would
set:

<P>
<PRE>    # Establish the default at startup
    PageDir   english
    Locale fr_FR  PageDir  francais
    Locale en_US  PageDir  english
</PRE>
<P><DT><STRONG><A NAME="item_ImageDir">ImageDir</A></STRONG><DD>

To use a different image directory for different locales, set the ImageDir
key. To have two separate language button sets, French and English, you
would set:

<P>
<PRE>    # Establish the default at startup
    ImageDir   /images/english/
    Locale fr_FR  ImageDir   /images/francais/
    Locale en_US  ImageDir   /images/english/
</PRE>
<P><DT><STRONG><A NAME="item_ImageDirSecure">ImageDirSecure</A></STRONG><DD>

Same as ImageDir.

<P><DT><STRONG><A NAME="item_PriceField">PriceField</A></STRONG><DD>

To use a different field in the products database for pricing based on
locale, set the PriceField locale setting.

<P>
<PRE>    # Establish the default at startup
    PriceField    price
    Locale fr_FR  PriceField  prix
</PRE>
<P>
The default will always be <CODE>price</CODE>, but if the locale <CODE>fr_FR</CODE> is set, the PriceField directive will change to <CODE>prix</CODE> to give prices in francs instead of dollars.

<P>
If <EM>PriceBreaks</EM> is enabled, then the field <CODE>prix</CODE> from the <A HREF="#item_pricing">pricing</A> database will be used to develop the quantity pricing. 
<FONT SIZE=-1>NOTE:</FONT> If no Locale settings are present, it will
always be <CODE>price</CODE>, irrespective of the <A HREF="#item_PriceField">PriceField</A> setting. Otherwise it will always match <A HREF="#item_PriceField">PriceField</A>.

<P><DT><STRONG><A NAME="item_PriceDivide">PriceDivide</A></STRONG><DD>

Normally used to enable penny pricing with a setting of 100, this can be
used to do an automatic conversion factor based on locale.

<P>
<PRE>    # Default at startup is 1 if not set
    # Franc is strong these days!
    Locale fr_FR  PriceDivide  .20
</PRE>
<P>
The price will now be divided by <CODE>.20</CODE>, yielding franc prices five times that of the dollar.

<P><DT><STRONG><A NAME="item_PriceCommas">PriceCommas</A></STRONG><DD>

Perhaps this isn't a good name anymore, but it controls whether the
<CODE>mon_thousands_sep</CODE> will be used for standard currency formatting. Ignored if using <A HREF="#item_price_picture">price_picture</A>. Set to 1 or 0, to enable and disable respectively. 
<FONT SIZE=-1>DO</FONT> 
<FONT SIZE=-1>NOT</FONT> 
<FONT SIZE=-1>USE</FONT> Yes and No.


<P>
<PRE>    # Default at startup is Yes if not set
    PriceCommas  Yes
    Locale fr_FR  PriceCommas  0
    Locale en_US  PriceCommas  1
</PRE>
<P><DT><STRONG><A NAME="item_UseModifier">UseModifier</A></STRONG><DD>

Changes the fields from that set shopping cart options.

<P>
<PRE>    # Default at startup is 1 if not set
    # Franc is strong these days!
    UseModifier format
    Locale fr_FR  UseModifier formats
</PRE>
<P>
If a previous setting was made for an item based on another locale, it will
be maintained.

<P><DT><STRONG><A NAME="item_PriceAdjustment">PriceAdjustment</A></STRONG><DD>

Changes the fields from UseModifier that will be used to adjust pricing.
used to do an automatic conversion factor based on locale.

<P>
<PRE>    # Default at startup
    PriceAdjustment  format
    Locale fr_FR  PriceAdjustment  formats
</PRE>
<P><DT><STRONG><A NAME="item_TaxShipping">TaxShipping,SalesTax</A></STRONG><DD>

Same as the standard directives.

<P><DT><STRONG><A NAME="item_DescriptionField">DescriptionField</A></STRONG><DD>

This changes the field accessed by default with the <CODE>[item-description]</CODE> and
<CODE>[description code]</CODE> tags.

<P>
<PRE>    # Establish the default at startup
    DescriptionField    description
    Locale fr_FR  DescriptionField desc_fr
</PRE>
<P><DT><STRONG><A NAME="item_The">The [locale] tag</A></STRONG><DD>

You can set standard error messages based on Locale settings. Make sure you
don't use any of the predefined keys -- it will be safe if you begin the
key with msg_ or such. The default message is set between the 
<CODE>[locale key]</CODE> and <CODE>[/locale]</CODE> tags. See the example above.

<P></DL>
<P>
<HR>


code: 21.05
section: INTERNATIONALIZATION
type: item
title: Placing Locale information in a Database

<A NAME="Placing_Locale_information_in_a_">Placing Locale information in a Database</A></H2>
<P>
MiniVend has the capability to read its locale information from a database,
named with the <EM>LocaleDatabase</EM> directive. The database can be of any valid MiniVend type. The locales are
in columns, and the keys are in rows. So to set up price information:

<P>
<PRE>    key                 en_US   fr_FR   de_DE
    PriceDivide         1       .1590   .58
    mon_decimal_point   .       ,       ,
    mon_thousands_sep   ,       .        
    currency_symbol     $        frs    DM 
    ps_cs_precedes      1       0       0   
</PRE>
<P>
That would translate <EM>exactly</EM> into:

<P>
<PRE>    Locale en_US PriceDivide         1
    Locale en_US mon_decimal_point   .
    Locale en_US mon_thousands_sep   ,
    Locale en_US currency_symbol     $
    Locale en_US ps_cs_precedes      1
</PRE>
<P>
<PRE>    Locale fr_FR PriceDivide         .1590
    Locale fr_FR mon_decimal_point   ,
    Locale fr_FR mon_thousands_sep   .
    Locale fr_FR currency_symbol     &quot; frs&quot;
    Locale fr_FR ps_cs_precedes      0
</PRE>
<P>
<PRE>    Locale de_DE PriceDivide         .58
    Locale de_DE mon_decimal_point   ,
    Locale de_DE mon_thousands_sep   &quot; &quot;
    Locale de_DE currency_symbol     &quot;DM &quot;
    Locale de_DE ps_cs_precedes      1           
</PRE>
<P>
These settings add on to <STRONG>but overwrite</STRONG> any that are set in the catalog configuration files, including any #include
files.

<P>

<FONT SIZE=-1>IMPORTANT</FONT> 
<FONT SIZE=-1>NOTE:</FONT> The information is only read on catalog configuration. It is not reasonable to access a database for translation or currency conversion in the normal course of events.


<P>
<HR>


code: 21.06
section: INTERNATIONALIZATION
type: item
title: Sorting based on Locale

<A NAME="Sorting_based_on_Locale">Sorting based on Locale</A></H2>
<P>
The MiniVend <CODE>[sort database:field]</CODE> keys will use the 
<FONT SIZE=-1>LC_COLLATE</FONT> setting for a locale provided that:

<UL>
<LI>

Your operating system and 
<FONT SIZE=-1>C</FONT> compiler have such support for 
<FONT SIZE=-1>POSIX,</FONT> and you have the locale definitions set.


<P><LI>

You have Perl 5.004.

<P><LI>

The locale setting matches one of your configured locales.

<P></UL>
<P>
It is beyond the scope of this document to discuss these issues, and you should contact your system administrator or local wizard to help you set up locales on your system. 
<FONT SIZE=-1>NOTE:</FONT> Windows locales are not supported for sorting.


<P>
If you had this arbitrary database named <CODE>letters</CODE>:

<P>
<PRE>    code        letter
    00-0011     f
    99-102      
    19-202      a
</PRE>
<P>
and this loop:

<P>
<PRE>    [loop 19-202 00-0011 99-102]
    [sort letters:letter]
    [loop-data letters letter]   [loop-code]
    [/loop]
</PRE>
<P>
Using the default 
<FONT SIZE=-1>C</FONT> setting for 
<FONT SIZE=-1>LC_COLLATE</FONT> it would display:


<P>
<PRE>    a  19-202
    f  00-0011
      99-102
</PRE>
<P>
If the proper 
<FONT SIZE=-1>LC_COLLATE</FONT> settings for locale <CODE>fr_FR</CODE> were in effect, then it would become:

<P>
<PRE>    a  19-202
      99-102
    f  00-0011
</PRE>
<P>
<HR>


code: 22.00
section: INTERNATIONALIZATION
type: overview
title: INTERNATIONALIZATION

<A NAME="INTERNATIONALIZATION">INTERNATIONALIZATION</A></H1>
<P>
MiniVend 3.07 adds a rich set of 
<FONT SIZE=-1>I18N</FONT> features to allow conditional message display,
differing price formats, different currency definitions, price factoring,
sorting, and other settings.

<P>
The definitions are maintained in the catalog.cfg file through the use of built in 
<FONT SIZE=-1>POSIX</FONT> support and MiniVend's
 <EM>Locale</EM> directive.

<P>
All settings are independent for each catalog and each user of that catalog
-- you can have customers accessing the same catalog in any of an unlimited
number of languages and currencies.

<P>
<HR>


code: 23.00
section: MINIVEND_CONFIGURATION_FILES
type: overview
title: MINIVEND CONFIGURATION FILES

<A NAME="MINIVEND_CONFIGURATION_FILES">MINIVEND CONFIGURATION FILES</A></H1>
<P>
MiniVend can and usually does run multiple catalogs on the same server. If
no <EM>Catalog</EM> directives are present in the main
<EM>minivend.cfg</EM> file, the server will read only a single catalog's information from the one <EM>minivend.cfg</EM> file, just as in early versions of the program.

<P>
You normally call configuration directives with the directive as the first
word on the line, with it's value or values following. Leading whitespace
is stripped from the value.

<P>
You may call additional files with a rudimentary <EM>#include file</EM>
statement. The directives called with includes are always appended at the
end of the main configuration file. Though order is rarely important in the
configuration files, you must define any directory settings in the main
configuration file near the top if they are to be used to base the file
calls of subsequent directives. Files are relative to the catalog directory
(or MiniVend software directory, if in the main minivend.cfg file).

<P>
You can also use a type of ``here document'' to specify MiniVend directives, with the usual 
<FONT SIZE=-1>&lt;&lt;MARKER</FONT> syntax. No semicolon is used to terminate the marker.


<P>
<HR>


code: 23.02
section: MINIVEND_CFG
type: item
title: AdminSub

<A NAME="AdminSub">AdminSub</A></H2>
<P>
Specifies subroutine names that may not be run unless the user is the
administrative user for the catalog. (See <EM>MasterHost</EM>, 
<EM>Password</EM>, and <EM>RemoteUser</EM>).

<P>
<PRE>    AdminSub  export_database
</PRE>
<P>
<HR>


code: 23.03
section: MINIVEND_CFG
type: item
title: AdminUser

<A NAME="AdminUser">AdminUser</A></H2>
<P>

<FONT SIZE=-1>A</FONT> space or colon-separated list of users who have
global MiniVend administration permission for the special mv_admin catalog.
The password is encrypted unless the Global <EM>Variable</EM> 
<FONT SIZE=-1>MV_NO_CRYPT</FONT> is set to a true value. This is the case
in the distribution minivend.cfg file, which has these settings:

<P>
<PRE>    Variable    MV_NO_CRYPT
    AdminUser   minivend:nevairbe
</PRE>
<P>
Obviously you should change the password at your first opportunity. To
begin with, the catalog is defined with a <EM>MasterHost</EM> value of 127.0.0.1 to disallow access from the outside world. To access it
from another system besides <CODE>localhost</CODE>, you will need to remove or change the value.

<P>
<HR>


code: 23.04
section: MINIVEND_CFG
type: item
title: AllowGlobal

<A NAME="AllowGlobal">AllowGlobal</A></H2>
<P>
Specifies catalog identifiers that may define subroutines and UserTag
entries that can operate with the full permissions of the server. <STRONG>DON'T USE THIS UNLESS YOU TRUST THE CATALOG USER IMPLICITLY.</STRONG>
Default is blank.

<P>
<PRE>    AllowGlobal  simple
</PRE>
<P>
<HR>


code: 23.05
section: MINIVEND_CFG
type: item
title: Catalog

<A NAME="Catalog">Catalog</A></H2>
<P>
Specifies a catalog that can run using this MiniVend server. There are
three required parameters, separated by spaces and/or tabs.

<P>
The first is the name of the catalog -- it will be referred to as that name
in error, warning, and informational messages. It must contain only
alphanumeric characters, hyphens, and underscores.

<P>
The second is the base directory of the catalog. If the directory does not
contain a <EM>catalog.cfg</EM> file, the server will report an error and refuse to start.

<P>
The third directive is very important to get right -- it is the 
<FONT SIZE=-1>SCRIPT_NAME</FONT> of the vlink program that runs the catalog. It must be unique from other 
<FONT SIZE=-1>CGI</FONT> program paths that run on this server -- that is how the catalog is selected for operation.


<P>
<PRE>    Catalog    simple   /home/minivend/simple  /cgi-bin/simple
</PRE>
<P>
As of MiniVend 3.0, you can specify any number of alias script names as additional parameters. This allows the calling path to be different while still calling the same catalog -- it is most probably useful when calling an 
<FONT SIZE=-1>SSL</FONT> server or a members-only executable that requires a username/password via 
<FONT SIZE=-1>HTTP</FONT> Basic authorization. All branched links will be called using the aliased 
<FONT SIZE=-1>URL.</FONT>


<P>
In addition, if you set the global directive <EM>FullUrl</EM> to <EM>yes</EM>, you can (and must in all catalogs) specify the server name that will call the catalog. This allows you to have many virtual domains, all of which use /cgi-bin/shop as the calling 
<FONT SIZE=-1>URL.</FONT>


<P>
<HR>


code: 23.06
section: MINIVEND_CFG
type: item
title: DisplayErrors

<A NAME="DisplayErrors">DisplayErrors</A></H2>
<P>
While all errors are reported in the error log file, you can also have
errors displayed by the browser. This is convenient while you are testing
your configuration. Unless this is set, the DisplayErrors setting in the
user catalogs will have no effect. Default is <EM>No</EM>.

<P>
<PRE>    DisplayErrors       Yes
</PRE>
<P>
<HR>


code: 23.07
section: MINIVEND_CFG
type: item
title: DomainTail

<A NAME="DomainTail">DomainTail</A></H2>
<P>
Implements the domain/IP session qualifiers so that only the major domain is used to qualify the session 
<FONT SIZE=-1>ID.</FONT> This is a compromise on security, but it allows non-cookie-accepting browsers like AOL's 
<FONT SIZE=-1>V2.0</FONT> to use multiple proxy servers. Default is yes.


<P>
<PRE>    DomainTail No
</PRE>
<P>
If you are encrypting your credit cards with 
<FONT SIZE=-1>PGP</FONT> or 
<FONT SIZE=-1>GPG,</FONT> or are using a payment service like CyberCash, you may want to look at the
 <EM>WideOpen</EM> directive, which enables more browser compatibility at the cost of some
security.

<P>
<HR>


code: 23.08
section: MINIVEND_CFG
type: item
title: Environment

<A NAME="Environment">Environment</A></H2>
<P>
Environment variables to inherit from the calling 
<FONT SIZE=-1>CGI</FONT> link program. And example might be 
<FONT SIZE=-1>PGPPATH,</FONT> used to set the directory which 
<FONT SIZE=-1>PGP</FONT> will use to find its key ring.


<P>
<PRE>    Environment  MSQL_HOME MSQL_TCP_PORT MSQL_UNIX_PORT
</PRE>
<P>
<HR>


code: 23.09
section: MINIVEND_CFG
type: item
title: FullUrl

<A NAME="FullUrl">FullUrl</A></H2>
<P>
Normally MiniVend determines which catalog to call by determining the 
<FONT SIZE=-1>SCRIPT_NAME</FONT> from the 
<FONT SIZE=-1>CGI</FONT> call. This means that different (and maybe virtual) hosts cannot use the same 
<FONT SIZE=-1>SCRIPT_NAME</FONT> to call different catalogs. Set FullUrl to
 <STRONG>Yes</STRONG> to differentiate based on the calling host. You must then set the server name in the Catalog directive accordingly, i.e. yourdomain.com/cgi-bin/simple. 
<FONT SIZE=-1>A</FONT> yes/no directive, the default is
 <STRONG>No</STRONG>.

<P>
<PRE>    FullUrl  Yes
</PRE>
<P>
<HR>


code: 23.10
section: MINIVEND_CFG
type: item
title: GlobalSub

<A NAME="GlobalSub">GlobalSub</A></H2>
<P>
Defines a <EM>global</EM> subroutine for use by the <CODE>[perl sub] subname arg [/perl]</CODE>
construct. Use the ``here document'' capability of MiniVend configuration
files to make it easy to define:

<P>
<PRE>    GlobalSub &lt;&lt;EOF
</PRE>
<P>
<PRE>    sub count_orders {
        my $counter = new <A HREF="File::CounterFile">File::CounterFile</A> &quot;/tmp/count_orders&quot;, '1';
        my $number = $counter-&gt;inc();
        return &quot;There have been $number orders placed.\n&quot;;
    }
    EOF
</PRE>
<P>
As with Perl ``here documents'', the 
<FONT SIZE=-1>EOF</FONT> (or other end marker) must be the 
<FONT SIZE=-1>ONLY</FONT> thing on the line, with no leading or trailing white space. Do not append a semicolon to the marker. (The above appears indented -- it should not be that way in the file!)


<P>
<STRONG>IMPORTANT NOTE:</STRONG> These global subroutines are <STRONG>not</STRONG> subject to security checks -- they can do most anything! For most purposes,
scratch subroutines or catalog subroutines (also <EM>Sub</EM>) are better.

<P>
GlobalSub routines are subject to full Perl <EM>use strict</EM> checking, so you will get errors if you do not use lexical variables or
complete package qualifications for your variables.

<P>
<HR>


code: 23.11
section: MINIVEND_CFG
type: item
title: HammerLock

<A NAME="HammerLock">HammerLock</A></H2>
<P>
The number of seconds after which a locked session could be considered to
be lost due to malfunction. This will kill the lock on the session. Only
here for monitoring of session hand-off, if this error shows up in the
error log the system setup should be examined. Default is 30.

<P>
<PRE>    HammerLock          60
</PRE>
<P>
<HR>


code: 23.12
section: MINIVEND_CFG
type: item
title: HouseKeeping

<A NAME="HouseKeeping">HouseKeeping</A></H2>
<P>
How often, in seconds, the MiniVend server will ``wake up'' and look for
user reconfiguration requests and hung search processes. On some systems,
this wakeup is the only time the server will terminate in response to a
stop command. Default is 60.

<P>
<PRE>    HouseKeeping    10
</PRE>
<P>
<HR>


code: 23.13
section: MINIVEND_CFG
type: item
title: IpHead

<A NAME="IpHead">IpHead</A></H2>
<P>
Implements the domain/IP session qualifiers so that only the first two dot-quads of the 
<FONT SIZE=-1>IP</FONT> address are used to qualify the session 
<FONT SIZE=-1>ID.</FONT> This is a compromise on security, but it allows non-cookie-accepting browsers like AOL's 
<FONT SIZE=-1>V2.0</FONT> to use multiple proxy servers.
 

<P>
DomainTail is preferable unless one of your 
<FONT SIZE=-1>HTTP</FONT> servers does not do host name lookups.

<P>
Default is <CODE>No</CODE>, and DomainTail must be set to <CODE>No</CODE> for it to operate.

<P>
<PRE>    IpHead Yes
</PRE>
<P>
<HR>


code: 23.14
section: MINIVEND_CFG
type: item
title: LockoutCommand

<A NAME="LockoutCommand">LockoutCommand</A></H2>
<P>
The name of a command (as you would enter it from the shell) that will lock out the host 
<FONT SIZE=-1>IP</FONT> of an offending system. The 
<FONT SIZE=-1>IP</FONT> address will be substituted for the first occurrence of the string %s.


<P>
This will be executed with the user 
<FONT SIZE=-1>ID</FONT> that MiniVend runs under, so any commands that require root access will have to be wrapped with an 
<FONT SIZE=-1>SUID</FONT> program.


<P>
On Linux, you might lock out a host with:

<P>
<PRE>    ipfwadm -I -i deny -S %s
</PRE>
<P>
This would require root permissions, however, under normal circumstances.
You can use <CODE>sudo</CODE> or another method to wrap and allow the command.

<P>
You can write a script which modifies an appropriate access control file, such as .htaccess for your 
<FONT SIZE=-1>CGI</FONT> directory, to do another level of lockout. 
<FONT SIZE=-1>A</FONT> simple command line containing

<CODE>perl -0777 -npi -e 's/deny/deny from %s\ndeny/' /home/me/cgi-bin/.htaccess</CODE>
would work as well (remember, the <A HREF="#item__s">%s</A> will become the 
<FONT SIZE=-1>IP</FONT> address of the offending user).


<P>
<PRE>    LockoutCommand   lockout %s
</PRE>
<P>
<HR>


code: 23.15
section: MINIVEND_CFG
type: item
title: MaxServers

<A NAME="MaxServers">MaxServers</A></H2>
<P>
The maximum number of servers that will be spawned to handle page requests.
If more than MaxServers requests are pending, they will be queued (within
the defined capability of the operating system, usually 5 pending requests)
until the number of active servers goes below that value.

<P>
<PRE>    MaxServers     4
</PRE>
<P>
<HR>


code: 23.16
section: MINIVEND_CFG
type: item
title: NoAbsolute

<A NAME="NoAbsolute">NoAbsolute</A></H2>
<P>
Whether MiniVend <A HREF="#item__file_">[file ...]</A> and other tags can read any file on the system (that is readable by the
user id running the MiniVend daemon). The default is
<STRONG>No</STRONG>, which allows any file to be read -- this should be changed in a
multi-user environment to minimize security problems.

<P>
<PRE>    NoAbsolute     Yes
</PRE>
<P>
<HR>


code: 23.17
section: MINIVEND_CFG
type: item
title: PIDcheck

<A NAME="PIDcheck">PIDcheck</A></H2>
<P>
If non-zero, enables a check of running MiniVend processes during the
housekeeping routine. If a process has been running (or is hung) for longer
than <EM>PIDcheck</EM> seconds then a kill -9 will be issued and the server count decremented.

<P>
During the housekeeping routine, the number of servers checked by 
<EM>MaxServers</EM> will be recounted based on 
<FONT SIZE=-1>PID</FONT> files.

<P>
Default is <STRONG>0</STRONG>, disabling the check. It is recommended that you use this only for
MiniVend 3.12 or higher, and it is recommended that you <STRONG>do</STRONG> use it for that version.

<P>
<PRE>    PIDcheck   300
</PRE>
<P>
If you have long-running database builds, you will need to disable this,
set it to a high value (perhaps 600, for 10 minutes), or use the
<EM>offline</EM> script.

<P>
<HR>


code: 23.18
section: MINIVEND_CFG
type: item
title: SafeSignals

<A NAME="SafeSignals">SafeSignals</A></H2>
<P>

<FONT SIZE=-1>NOTE:</FONT> This directive no longer applies as of MiniVend
3.12.

<P>
If your operating system does not have a re-entrant 
<FONT SIZE=-1>C</FONT> library that can guarantee that signal race conditions will not occur, then set this to 
<FONT SIZE=-1>NO.</FONT>


<P>

<FONT SIZE=-1>BSDI</FONT> and FreeBSD libraries are 
<FONT SIZE=-1>NOT</FONT> safe, and SafeSignals will automatically be disabled for those operating systems.


<P>
In general, if MiniVend ever just ``hangs'', particularly if you can see a
perl.core file, disable this directive.

<P>
<PRE>    SafeSignals  No
</PRE>
<P>
<HR>


code: 23.19
section: MINIVEND_CFG
type: item
title: SafeUntrap

<A NAME="SafeUntrap">SafeUntrap</A></H2>
<P>
Sets the codes that will be untrapped in the Safe.pm module, used for
embedded Perl and conditional operations. You can see the Safe.pm
documentation by typing <CODE>perldoc Safe</CODE> at the command prompt. The default is <CODE>249 148</CODE> for Perl 5.003, and <CODE>ftfile sort</CODE> for Perl 5.003_20 and above, which untraps the file existence test operator
and the sort operator. Define it as blank to not allow any besides the
default restrictive operators.

<P>
<PRE>    SafeUntrap     ftfile sort ftewrite
</PRE>
<P>
<HR>


code: 23.20
section: MINIVEND_CFG
type: item
title: SendMailProgram

<A NAME="SendMailProgram">SendMailProgram</A></H2>
<P>
Specifies the program used to send email. Defaults to '/usr/lib/sendmail'.
If it is not found at startup, MiniVend will complain and refuse to start.

<P>
<PRE>    SendMailProgram     /bin/mailer
</PRE>
<P>

<FONT SIZE=-1>A</FONT> value of 'none' will disable the sending of emailed
orders. Orders must be read from a tracking file, log, or by other means.

<P>
<HR>


code: 23.21
section: MINIVEND_CFG
type: item
title: SubCatalog

<A NAME="SubCatalog">SubCatalog</A></H2>
<P>
Allows definition of a catalog which shares most of the characteristics of another catalog. Only the directives that are changed from the base catalog are added. The parameters are 1) the catalog 
<FONT SIZE=-1>ID</FONT> 2) the base catalog 
<FONT SIZE=-1>ID,</FONT> 3) the directory to use (typically the same as the base catalog), and 4) the 
<FONT SIZE=-1>SCRIPT_NAME</FONT> that will trigger the catalog. Any additional parameters are aliases for the 
<FONT SIZE=-1>SCRIPT_NAME.</FONT>


<P>
The main reason that this would be used would be to conserve memory in a
series of stores that share most of the same pages or databases.

<P>
<PRE>    SubCatalog   sample2 sample /usr/catalogs/sample /cgi-bin/sample2
</PRE>
<P>
<HR>


code: 23.22
section: MINIVEND_CFG
type: item
title: TcpHost

<A NAME="TcpHost">TcpHost</A></H2>
<P>
When running in 
<FONT SIZE=-1>INET</FONT> mode, using <CODE>tlink</CODE>, specifies the hosts that are allowed to send/receive transactions from any catalog on this MiniVend server. Can be either an name or 
<FONT SIZE=-1>IP</FONT> number, and multiple hosts can be specified in a space-separated list. Default is localhost.


<P>
<PRE>    TcpHost         localhost secure.domain.com
</PRE>
<P>
<HR>


code: 23.23
section: MINIVEND_CFG
type: item
title: TcpMap

<A NAME="TcpMap">TcpMap</A></H2>
<P>
When running in 
<FONT SIZE=-1>INET</FONT> mode, using <CODE>tlink</CODE> or the internal 
<FONT SIZE=-1>HTTP</FONT> server, specifies the <CODE>port(s)</CODE> which
will be monitored. by the MiniVend server. Default is 7786, which is mapped
to the special mv_admin catalog.

<P>
To use the internal 
<FONT SIZE=-1>HTTP</FONT> server (perhaps only for password-protected
queries), you can map a catalog to a port. If you had three catalogs
running on the server <EM>www.minivend.com</EM>, named <A HREF="#item_simple">simple</A>, <CODE>sample</CODE>, and <A HREF="#item_search">search</A>, you might have in the directive:

<P>
<PRE>    TcpPort   7786 mv_admin  7787 simple 7788 sample 7789 search
</PRE>
<P>

<FONT SIZE=-1>NOTE:</FONT> To map large numbers of ports, you can use the 
<FONT SIZE=-1>&lt;&lt;MARKER</FONT> here document notation in minivend.cfg.


<P>
With this in effect, the internal 
<FONT SIZE=-1>HTTP</FONT> server would map the following addresses:

<P>
<PRE>    <A HREF="http://www.minivend.com:7786">http://www.minivend.com:7786</A>   mv_admin
    <A HREF="http://www.minivend.com:7787">http://www.minivend.com:7787</A>   simple
    <A HREF="http://www.minivend.com:7788">http://www.minivend.com:7788</A>   sample
    <A HREF="http://www.minivend.com:7789">http://www.minivend.com:7789</A>   search
</PRE>
<P>

<FONT SIZE=-1>NOTE:</FONT> This does not pertain to the use of <CODE>tlink</CODE>, which still relies on the 
<FONT SIZE=-1>CGI</FONT> 
<FONT SIZE=-1>SCRIPT_PATH.</FONT>


<P>
To enable this, the 
<FONT SIZE=-1>SCRIPT_PATH</FONT> aliases /simple, /sample, etc. must be set
in the <CODE>Catalog</CODE> directive. This would look like:

<P>
<PRE>  Catalog  simple  /home/minivend/catalogs/simple /cgi-bin/simple /simple
</PRE>
<P>
<HR>


code: 23.24
section: MINIVEND_CFG
type: item
title: TcpPort

<A NAME="TcpPort">TcpPort</A></H2>
<P>
This is superceded by the <EM>TcpMap</EM> directive. It will still accept only a number, but it is not used. (The
Global::TcpPort) variable is now used to signify which monitored port is
connected.

<P>
<HR>


code: 23.25
section: MINIVEND_CFG
type: item
title: TolerateGet

<A NAME="TolerateGet">TolerateGet</A></H2>
<P>
Sometimes proxy servers screw up and cache 
<FONT SIZE=-1>POST</FONT> forms. This is mainly a problem from forms that
are identical, such as popular items being placed in the basket and then
the user pushing the checkout button.

<P>
Set TolerateGet to <CODE>Yes</CODE> to allow 
<FONT SIZE=-1>GET</FONT> forms. You will be able to use 
<FONT SIZE=-1>METHOD=GET</FONT> on the form if necessary, subject to the normal limits of query string length. You will want to set the variable

<CODE>mv_session_id</CODE> to ensure that the session is not lost on browsers that don't support
cookies:

<P>
<PRE>    &lt;INPUT TYPE=hidden NAME=mv_session_id VALUE=&quot;[data session id]&quot;&gt;
</PRE>
<P>
It would be typical to employ this on your shopping cart page or perhaps
put it on the <EM>interact</EM> page that is shown when the normal error is received.

<P>
<PRE>    TolerateGet   Yes
</PRE>
<P>
<HR>


code: 23.25
section: MINIVEND_CFG
type: item
title: Variable

<A NAME="Variable">Variable</A></H2>
<P>
Defines a global variable that will be available in <STRONG>all</STRONG> catalogs with the notation @@Variable@@. Variable identifiers must begin
with a capital letter, and can contain only word characters (<STRONG>A-Z,a-z,0-9</STRONG> and underscore) -- they are case-sensitive. If using the
<EM>ParseVariables</EM> directive, only variables in 
<FONT SIZE=-1>ALL</FONT> 
<FONT SIZE=-1>CAPS</FONT> will be parsed. These are substituted first in any MiniVend page, and can contain any valid MiniVend tags including catalog variables.


<P>
<PRE>    Variable   DOCUMENT_ROOT   /usr/local/etc/httpd/htdocs
</PRE>
<P>
There are several standard variables which you should not use:

<DL>
<DT><STRONG><A NAME="item_MV_FILE">MV_FILE</A></STRONG><DD>

Name of the last file read in, as in <A HREF="#item__file_">[file ...]</A> or an externally located perl routine

<P><DT><STRONG><A NAME="item_MV_NO_CRYPT">MV_NO_CRYPT</A></STRONG><DD>

Set this to 1 to disable encrypted passwords for the <CODE>AdminUser</CODE>.

<P><DT><STRONG><A NAME="item_MV_PAGE">MV_PAGE</A></STRONG><DD>

Name of the last page read in, as in the page called with mv_nextpage or
mv_orderpage

<P><DT><STRONG><A NAME="item_CURRENCY">CURRENCY</A></STRONG><DD>

The current locale for currency

<P><DT><STRONG><A NAME="item_LANG">LANG</A></STRONG><DD>

The current locale for language

<P></DL>
<P>
<HR>


code: 23.26
section: MINIVEND_CFG
type: item
title: UserTag

<A NAME="UserTag">UserTag</A></H2>
<P>
This defines a UserTag which is global in nature, meaning not limited by
the <EM>Safe.pm</EM> module, and which tag is available to all MiniVend catalogs running on the
server. Otherwise this is the same as a catalog <EM>UserTag</EM>.

<P>
<HR>


code: 24.00
section: MINIVEND_CFG
type: overview
title: MINIVEND.CFG

<A NAME="MINIVEND_CFG">MINIVEND.CFG</A></H1>
<P>
The VendRoot directory, specified in the main program <CODE>minivend</CODE>, is the default location of all of the MiniVend program, configuration,
special, and library files. Unless changed in <CODE>minivend</CODE>, the main MiniVend server configuration file will be minivend.cfg in the
VendRoot directory.

<P>
If no <EM>Catalog</EM> directives are present, only the special MiniVend admin catalog will be
started.

<P>
The directives defined in minivend.cfg affect the entire MiniVend server
and all catalogs running under it; though you may run multiple MiniVend
servers on the same machine with totally independent operation.

<P>
<HR>


code: 24.02
section: CATALOG_CFG
type: item
title: VendURL

<A NAME="VendURL">VendURL</A></H2>
<P>
Specifies the base 
<FONT SIZE=-1>URL</FONT> that will run vlink as a cgi-bin program.

<P>
<PRE>        VendURL  <A HREF="http://machine.company.com/cgi-bin/vlink">http://machine.company.com/cgi-bin/vlink</A>
</PRE>
<P>
<HR>


code: 24.03
section: CATALOG_CFG
type: item
title: MailOrderTo

<A NAME="MailOrderTo">MailOrderTo</A></H2>
<P>
Specifies the email address to mail completed orders to.

<P>
<PRE>        MailOrderTo  orders@xyzcorp.com
</PRE>
<P>
<HR>


code: 24.04
section: CATALOG_CFG
type: item
title: Optional Configuration Directives

<A NAME="Optional_Configuration_Directive">Optional Configuration Directives</A></H2>
<P>
These directives all have default values and are optional.



code: 24.05
section: CATALOG_CFG
type: item
title: ActionMap

<A NAME="ActionMap">ActionMap</A></H2>

Allows setting of button actions for particular names. The predefined names
are:

<P>
<PRE> cancel   Cancel order and wipe credit card numbers
 control  Control help, colors, etc.
 checkout Call checkout form
 refresh  Refresh order page (update quantities, etc.)
 return   Go to previous page (or page defined in mv_nextpage variable)
 search   Search for an item in the catalog
 set      Update a database
 submit   Submit order or form
</PRE>
<P>
Actions are overwritten, even the default ones, if re-defined. Default is
blank. Can be set as many times as necessary. Not case sensitive.

<P>
<PRE>    ActionMap           refresh change
    ActionMap           refresh validate
    ActionMap           cancel erase
    ActionMap           submit next
    ActionMap           control color
</PRE>
<P>
This directive can be set in the <EM>DirectiveDatabase</EM>.

<P>

code: 24.06
section: CATALOG_CFG
type: item
title: AdminDatabase

<A NAME="AdminDatabase">AdminDatabase</A></H2>

When set to one or more MiniVend database identifiers, any pages using data
items from the specified <CODE>database(s)</CODE> will not be allowed for
display unless the user the catalog operator -- i.e. is authenticated by
one of <EM>Password</EM>,
<EM>MasterHost</EM>, or <EM>RemoteUser</EM>. The special page <A HREF="#item_violation">violation</A> will be displayed if another user attempts to access a page containing
elements from the <CODE>database(s).</CODE>

<P>
<PRE>    AdminDatabase   inventory
</PRE>
<P>
If the file <CODE>.access_gate</CODE> is present in the products directory, the database name will be checked
according to the same scheme as for page access checking. See <EM>MINIVEND SECURITY</EM>.

<P>

code: 24.07
section: CATALOG_CFG
type: item
title: AdminPage

<A NAME="AdminPage">AdminPage</A></H2>

When set to one or more MiniVend page names, pages with that name will not
be allowed for display unless the user the catalog operator -- i.e. is
authenticated by one of <EM>Password</EM>, <EM>MasterHost</EM>, or <EM>RemoteUser</EM>. The special page <A HREF="#item_violation">violation</A> will be displayed if another user attempts to access the
<CODE>page(s).</CODE>

<P>
<PRE>    AdminPage       config/menu
</PRE>
<P>

code: 24.08
section: CATALOG_CFG
type: item
title: AlwaysSecure

<A NAME="AlwaysSecure">AlwaysSecure</A></H2>

Determines whether checkout page operations should always be secure. Set it
to the pages that should always be secure, separated by spaces and/or tabs.

<P>
<PRE>    AlwaysSecure    checkout
</PRE>
<P>

code: 24.09
section: CATALOG_CFG
type: item
title: AsciiBackend

<A NAME="AsciiBackend">AsciiBackend</A></H2>


<FONT SIZE=-1>A</FONT> file name to log order fields in (set by
BackendOrder). Unless preceded by a leading '/', will be placed relative to
VendRoot. If the first character is a '|', it is the name of a program to
send the fields to. Disabled by default.

<P>
<PRE>    AsciiBackend  |/usr/order/scripts/place_order
</PRE>
<P>

code: 24.10
section: CATALOG_CFG
type: item
title: AsciiTrack

<A NAME="AsciiTrack">AsciiTrack</A></H2>


<FONT SIZE=-1>A</FONT> file name to log formatted orders in. Unless
preceded by a leading '/', will be placed relative to the catalog
directory. Disabled by default.

<P>
<PRE>    AsciiTrack     etc/orders.txt
</PRE>
<P>

code: 24.100
section: CATALOG_CFG
type: item
title: SaveExpire

<A NAME="SaveExpire">SaveExpire</A></H2>

The length of time that saved sessions will persist before being expired.
See <EM>SessionExpire</EM> for the format. Default is 30 days.

<P>
<PRE>    SaveExpire    8 weeks
</PRE>
<P>

code: 24.101
section: CATALOG_CFG
type: item
title: ScratchDir

<A NAME="ScratchDir">ScratchDir</A></H2>

The directory where scratch files will be written, notably cached searches.
Defaults to VendRoot/etc.

<P>
<PRE>    ScratchDir          /tmp
</PRE>
<P>

code: 24.102
section: CATALOG_CFG
type: item
title: SearchCache

<A NAME="SearchCache">SearchCache</A></H2>

Whether searches will be cached. Caching is disabled for browsers that don't allow cookies to be set. 
<FONT SIZE=-1>A</FONT> yes/no directive -- default is No. The cached pages are stored in the directory
 <EM>ScratchDir</EM>/SearchCache.

<P>
<PRE>    SearchCache         Yes
</PRE>
<P>

code: 24.103
section: CATALOG_CFG
type: item
title: SearchFrame

<A NAME="SearchFrame">SearchFrame</A></H2>

The frame name where search results will go, if frames are enabled. If the
frame doesn't exist, a new frame will be created. The default is '_self'.

<P>
<PRE>    SearchFrame         main
</PRE>
<P>

code: 24.104
section: CATALOG_CFG
type: item
title: SearchProfile

<A NAME="SearchProfile">SearchProfile</A></H2>

Allows an unlimited number of search profiles to be set up, specifying
complex searches based on a single click. The directive accepts a file
name, based in the catalog directory if the path is relative:

<P>
<PRE>    SearchProfile    etc/search.profiles
</PRE>
<P>
As an added measure of control, the specification is evaluated with the
special MiniVend tag syntax to provide conditional setting of search
parameters.

<P>
The following file specifies a dictionary-based search in the file
'dict.product':

<P>
<PRE>  __NAME__ dict_search
  mv_search_file=dict.product
  mv_return_fields=1
  [if value fast_search]
    mv_dict_limit=-1
    mv_last=1
  [/if]
  __END__
</PRE>
<P>
The 
<FONT SIZE=-1>__NAME__</FONT> is the value you will specify in the
mv_profile variable on the search form, as in

<P>
<PRE>  &lt;INPUT TYPE=hidden NAME=mv_profile VALUE=&quot;dict_search&quot;&gt;
</PRE>
<P>
or with mp=profile in the one-click search.

<P>
<PRE>  [page scan se=Renaissance/mp=dict_search]Renaissance Art[/page]
</PRE>
<P>
Multiple profiles can reside in the same file, if separated by 
<FONT SIZE=-1>__END__</FONT> tokens. 
<FONT SIZE=-1>__NAME__</FONT> tokens should be left-aligned, and 
<FONT SIZE=-1>__END__</FONT> must be on a line by itself with no leading or trailing whitespace.


<P>

code: 24.105
section: CATALOG_CFG
type: item
title: SecureURL

<A NAME="SecureURL">SecureURL</A></H2>

The base 
<FONT SIZE=-1>URL</FONT> for secure forms/page transmissions. Normally it
is the same as <EM>VendURL</EM> except for the <CODE>https:</CODE> protocol definition. Default is blank, disabling secure access.

<P>
<PRE>    SecureURL   https://machine.com/xyzcorp/cgi-bin/vlink
</PRE>
<P>

code: 24.106
section: CATALOG_CFG
type: item
title: SendMailProgram

<A NAME="SendMailProgram">SendMailProgram</A></H2>

The location of the sendmail binary, needed for mailing orders. Must be found at startup. This often needs to be set for FreeBSD or 
<FONT SIZE=-1>BSDI.</FONT>


<P>
<PRE>   SendMailProgram    /usr/sbin/sendmail
</PRE>
<P>

code: 24.107
section: CATALOG_CFG
type: item
title: SeparateItems

<A NAME="SeparateItems">SeparateItems</A></H2>

Changes the default when ordering an item via MiniVend to allowing multiple
lines on the order form for each item. The default, <CODE>No</CODE>, puts all orders with the same part number on the same line.

<P>
Setting SeparateItems to <CODE>Yes</CODE> allows the item attributes to be easily set for different instances of the
same part number, allowing easy setting of things such as size or color.

<P>
<PRE>    SeparateItems       Yes
</PRE>
<P>
Can be overridden with the <EM>mv_separate_items</EM> variables (both scratch and user).

<P>

code: 24.108
section: CATALOG_CFG
type: item
title: SessionDatabase

<A NAME="SessionDatabase">SessionDatabase</A></H2>

When storing sessions in a 
<FONT SIZE=-1>DBM</FONT> database, specify the base name of the 
<FONT SIZE=-1>DBM</FONT> file to use. The file extensions of .pag, .dir, .db, or .gdbm (depending on the 
<FONT SIZE=-1>DBM</FONT> implementation used) will be appended.


<P>
<PRE>    SessionDatabase     session-data
</PRE>
<P>
It is possible for multiple catalogs to share the same session file. This
allows a ``mall'' to be set up where many store fronts use a common
ordering point. It would be wise to share the order pages, salestax
database, and shipping database if that is the case. You will also need to
set
<EM>SessionLockFile</EM> appropriately if the database is to be shared. Defaults to <A HREF="#item_session">session</A>, which is appropriate for separate session files (and therefore standalone
catalogs). Can be an absolute path name if desired.

<P>

code: 24.109
section: CATALOG_CFG
type: item
title: SessionExpire

<A NAME="SessionExpire">SessionExpire</A></H2>


<FONT SIZE=-1>A</FONT> customer can exit their browser or leave the catalog pages at any time, and no indication is given to the 
<FONT SIZE=-1>HTTPD</FONT> server aside from the lack of further requests that have the same session id. Old session information needs to be periodically expired. The SessionExpire specifies the minimum time to keep track of session information. Defaults to one day. Format is an integer number, followed by <CODE>s(econds),</CODE> <CODE>m(inutes),</CODE> <CODE>h(ours),</CODE> <CODE>d(ays),</CODE> or <CODE>w(eeks).</CODE>


<P>
<PRE>    SessionExpire       4 hours
</PRE>
<P>

code: 24.11
section: CATALOG_CFG
type: item
title: BackendOrder

<A NAME="BackendOrder">BackendOrder</A></H2>

Controls the fields that are prepended to the item codes and quantities for
the backend ordering capability. These are the values from the user
checkout forms. You can access any value in that hash. If blank, no backend
ordering is in force. Default is blank.

<P>
<PRE>     BackendOrder    name,address,city,state,zip,mv_shipmode
</PRE>
<P>

code: 24.110
section: CATALOG_CFG
type: item
title: SessionLockFile

<A NAME="SessionLockFile">SessionLockFile</A></H2>

The file to use for locking coordination of the sessions.

<P>
<PRE>    SessionLockFile     session-data.lock
</PRE>
<P>
It is possible for multiple catalogs to share the same session file. You
will also need to set <EM>SessionDatabase</EM> appropriately if the database is to be shared. Defaults to <CODE>session.lock</CODE>, which is appropriate for separate session files (and therefore standalone
catalogs). Can be an absolute path name if desired.

<P>

code: 24.111
section: CATALOG_CFG
type: item
title: Shipping

<A NAME="Shipping">Shipping</A></H2>

Specifies a shipping charge to add onto the total price for items ordered.
If you do not want to include a fixed shipping charge on the order page,
leave this 0 and do not include the <A HREF="#item__shipping_">[shipping]</A> element in the order page. Defaults to 0. Overridden by the <EM>CustomShipping</EM>
directive.

<P>
<PRE>    Shipping            5.00
</PRE>
<P>

code: 24.112
section: CATALOG_CFG
type: item
title: SpecialPage

<A NAME="SpecialPage">SpecialPage</A></H2>

Sets a special page to other than its default value. Can be set as many
times as necessary -- will have no effect if not one of the MiniVend <EM>Required Pages</EM>.

<P>
<PRE>    SpecialPage         checkout ord/checkout
    SpecialPage         failed special/error_on_order
    SpecialPage         interact special/browser_problem
    SpecialPage         noproduct special/no_product_found
    SpecialPage         order  ord/basket
    SpecialPage         search srch/results
</PRE>
<P>

code: 24.113
section: CATALOG_CFG
type: item
title: Static

<A NAME="Static">Static</A></H2>


<FONT SIZE=-1>A</FONT> yes/no directive. Enables static page building and
display features. Default is <A HREF="#item_no">no</A>.

<P>
<PRE>     Static   Yes
</PRE>
<P>

code: 24.114
section: CATALOG_CFG
type: item
title: StaticAll

<A NAME="StaticAll">StaticAll</A></H2>


<FONT SIZE=-1>A</FONT> yes/no directive. Tells MiniVend to try and build
all pages in the catalog statically when called with the static page build
option. This is subject to the settings of <EM>StaticFly</EM>, <EM>StaticPath</EM>, and <EM>NoCache</EM>. Default is No. (Of course pages that have dynamic elements will not be
built statically, though that may be overridden with <CODE>[tag flag build][/tag]</CODE> on the page in question.)

<P>
<PRE>     StaticAll   Yes
</PRE>
<P>

code: 24.115
section: CATALOG_CFG
type: item
title: StaticDepth

<A NAME="StaticDepth">StaticDepth</A></H2>

The number of levels of static search building that will be done if a
search results page contains a search. Default is one -- beware that it
could be very long if you set it higher. Set to 0 to disable re-scanning of
search results pages.

<P>
<PRE>     StaticDepth 2
</PRE>
<P>

code: 24.116
section: CATALOG_CFG
type: item
title: StaticDir

<A NAME="StaticDir">StaticDir</A></H2>

The absolute path of the directory which should be used as the root for static pages. The user 
<FONT SIZE=-1>ID</FONT> executing MiniVend must have write permission on the directory (and all files within) if this is to work.


<P>
<PRE>     StaticDir   /home/you/www/catalog
</PRE>
<P>

code: 24.117
section: CATALOG_CFG
type: item
title: StaticFly

<A NAME="StaticFly">StaticFly</A></H2>


<FONT SIZE=-1>A</FONT> yes/no directive. If set to <CODE>Yes</CODE>, static builds will attempt to generate a page for every part number in
the database using the on-the-fly page build capability. If pages are
already present with those names, they will be overwritten. The default is <CODE>No</CODE>.

<P>
<PRE>     StaticFly   Yes
</PRE>
<P>

code: 24.118
section: CATALOG_CFG
type: item
title: StaticPage

<A NAME="StaticPage">StaticPage</A></H2>

Tells MiniVend to build the named page (or pages, whitespace separated)
when employing the static page-building capability of MiniVend. Not
necessary if using StaticAll.

<P>
<PRE>     StaticPage   info/about_us  info/terms_and_conditions
</PRE>
<P>

code: 24.119
section: CATALOG_CFG
type: item
title: StaticPath

<A NAME="StaticPath">StaticPath</A></H2>

The path (relative to 
<FONT SIZE=-1>HTTP</FONT> document root) which should be used in pages
built with the static page-building capability of MiniVend.

<P>
<PRE>     StaticPath    /catalog
</PRE>
<P>

code: 24.12
section: CATALOG_CFG
type: item
title: ButtonBars

<A NAME="ButtonBars">ButtonBars</A></H2>

The ButtonBars directive allows you to define several preset button bars that reside in files. The button bar file will usually contain an 
<FONT SIZE=-1>IMG</FONT> link, along with its associated client-side image map. This allows you to insert a
 <CODE>[buttonbar 1]</CODE> or <CODE>[buttonbar 2]</CODE> directive instead of the equivalent 
<FONT SIZE=-1>HTML,</FONT> and is designed to make it easy to change the
look of your pages with the change of one file. If the file does not exist
at program configuration time, the tag is simply stripped. The line in the
<EM>catalog.cfg</EM> file takes the form of the directive, followed by any number of vend-style
file names (relative to the PageDir, with no .html suffix).

<P>
<PRE>    ButtonBars  bars/button0 bars/button1 bars/button2 bars/button3
</PRE>
<P>
The ButtonBars directive is deprecated in favor of <EM>Variable</EM> and
<EM>UserTag</EM>.

<P>

code: 24.120
section: CATALOG_CFG
type: item
title: StaticPattern

<A NAME="StaticPattern">StaticPattern</A></H2>


<FONT SIZE=-1>A</FONT> perl regular expression which is used to qualify
pages that are to be built statically. The default is blank, which means
all pages qualify.

<P>
<PRE>     StaticPattern  ^info|^help
</PRE>
<P>

code: 24.121
section: CATALOG_CFG
type: item
title: StaticSuffix

<A NAME="StaticSuffix">StaticSuffix</A></H2>

The extension to be appended to a normal MiniVend page name when building
statically. Default is <CODE>.html</CODE>. Also affects the name of pages in the MiniVend page directory -- if set
to .htm the pages must be named with that extension.

<P>
<PRE>     StaticSuffix   .htm
</PRE>
<P>

code: 24.122
section: CATALOG_CFG
type: item
title: Sub

<A NAME="Sub">Sub</A></H2>

Defines a catalog subroutine for use by the <CODE>[perl sub] subname arg [/perl]</CODE>
construct. Use the ``here document'' capability of MiniVend configuration
files to make it easy to define:

<P>
<PRE>    Sub &lt;&lt;EOF
</PRE>
<P>
<PRE>    sub sort_cart {
        my(%items) = @_;
        my($item,$name);
        my $out = '&amp;ltTABLE BORDER=1&gt;';
        foreach $name (sort keys %items) {
            $out .= '&amp;lt;TR&gt;&amp;lt;TD&gt;';
            $out .= $items{$name};
            $out .= '&amp;lt;/TD&gt;&amp;lt;TD&gt;';
            $out .= $name;
            $out .= '&amp;lt;/TD&gt;&amp;lt;/TR&gt;';
        }
        $out .= '&amp;lt/TABLE&gt;';
        return $out;
    }
    EOF
</PRE>
<P>
As with Perl ``here documents'', the 
<FONT SIZE=-1>EOF</FONT> (or other end marker) must be the 
<FONT SIZE=-1>ONLY</FONT> thing on the line, with no leading or trailing white space. Do not append a semicolon to the marker.


<P>
The above would be called with:

<P>
<PRE>    [perl sub]
        sort_cart ( [item-list]
                        &quot;[item-description]&quot;, &quot;[item-code]&quot;,
                    [/item-list] )
    [/perl]
</PRE>
<P>
and will display an 
<FONT SIZE=-1>HTML</FONT> table of the items in the current shopping cart,
sorted by the description. (Using an alternative form of quoting such as q{
} will minimize problems with quotes in the passed parameters -- you may
use any style you like, including here documents. Syntax errors will be
reported to <CODE>error.log</CODE>.)

<P>
Catalog subroutines may not perform unsafe operations -- the <EM>Safe.pm</EM>
module enforces this.

<P>

code: 24.123
section: CATALOG_CFG
type: item
title: SubArgs

<A NAME="SubArgs">SubArgs</A></H2>

Standard arguments that should be supplied to any routine with a name as
defined.

<P>
Defining

<P>
<PRE>    SubArgs passwd values cgi
</PRE>
<P>
and calling the routine with

<P>
<PRE>    [perl sub]
        passwd ('[value username]', '[value password]
    [/perl]
</PRE>
<P>
is the same as calling

<P>
<PRE>    [perl sub values cgi]
        passwd ('[value username]', '[value password]
    [/perl]
</PRE>
<P>
This can make calling routines more natural, and is especially useful in
combination with <A HREF="#item_mv_subroutine">mv_subroutine</A>.

<P>

code: 24.124
section: CATALOG_CFG
type: item
title: TaxShipping

<A NAME="TaxShipping">TaxShipping</A></H2>


<FONT SIZE=-1>A</FONT> comma or space separated list of states or jurisdictions that tax shipping cost, i.e. 
<FONT SIZE=-1>UT.</FONT> Blank by default, never taxing shipping.


<P>
<PRE>    TaxShipping         UT,NV,94024
</PRE>
<P>

code: 24.125
section: CATALOG_CFG
type: item
title: Tracking

<A NAME="Tracking">Tracking</A></H2>

This option is removed in MiniVend 3.0. It will provide a warning, but will
not stop the catalog from becoming operational.

<P>
Most users now use the simpler and more flexible <EM>Easy ASCII Tracking</EM>
capability.

<P>

code: 24.126
section: CATALOG_CFG
type: item
title: TransparentItem

<A NAME="TransparentItem">TransparentItem</A></H2>

When set to the name of a product attribute (which must be defined in the
directive <EM>UseModifier</EM>, and that attributes evaluates to true (yes, true, or 1, not
case-sensitive), that item will not be shown on <EM>Item Lists</EM>.

<P>
<PRE>    TransparentItem          option
</PRE>
<P>

code: 24.127
section: CATALOG_CFG
type: item
title: UpsZoneFile

<A NAME="UpsZoneFile">UpsZoneFile</A></H2>

The file containing the 
<FONT SIZE=-1>UPS</FONT> zone information, specified relative to the catalog directory unless it begins with a /. It can be in the format distributed by 
<FONT SIZE=-1>UPS</FONT> (for 1997, at least) -- or can be in a tab-delimited format, with the three-letter zip prefix of the customer used to determine the zone. It interpolates based on the value in
 <CODE>mv_shipmode</CODE>. 
<FONT SIZE=-1>A</FONT> user database <STRONG>named the same as the mv_shipmode variable</STRONG> must be present or the lookup will return zero.

<P>

<FONT SIZE=-1>&lt;IMPORTANT</FONT> 
<FONT SIZE=-1>NOTE:&gt;</FONT> You must obtain the zone information and updated pricing from 
<FONT SIZE=-1>UPS</FONT> in order for this to work properly. The zone information is specific to your region!


<P>
<PRE>    UpsZoneFile         /usr/minivend/data/ups_zone.asc
</PRE>
<P>

code: 24.128
section: CATALOG_CFG
type: item
title: UseCode

<A NAME="UseCode">UseCode</A></H2>

This determines whether the part number field in the 
<FONT SIZE=-1>ASCII</FONT> product file will be used to determine the link
to the item for the <CODE>[item-link]</CODE> tag. If set, this has the effect of creating a different 
<FONT SIZE=-1>HTML</FONT> page link for every part number. If not set (the
default), the <CODE>[item-link]</CODE> tag uses the value of the last field in the 
<FONT SIZE=-1>ASCII</FONT> product file as the link value. This option is
largely deprecated by the on-the-fly page building facility.

<P>
<PRE>    UseCode             yes
</PRE>
<P>

code: 24.129
section: CATALOG_CFG
type: item
title: UseModifier

<A NAME="UseModifier">UseModifier</A></H2>

Determines whether any attributes, the modifiers specified in the
directive, can be attached to the item. See <EM>Item Attributes</EM>. The default is no modifier. Don't use a value of <CODE>quantity</CODE> -- it will not do what you want.

<P>
<PRE>    UseModifier         size,color
</PRE>
<P>

code: 24.129
section: CATALOG_CFG
type: item
title: VariableDatabase

<A NAME="VariableDatabase">VariableDatabase</A></H2>

Set to the MiniVend database <EM>identifier</EM> of a table that contains
<EM>Variable</EM> settings. These settings add on to but overwrite any that are set in the
catalog configuration files, including any #include files.

<P>
<PRE>    Database         variable  variable.asc  TAB
    VariableDatabase variable
</PRE>
<P>
Only a key and value are needed; multiple columns don't make sense, though
you could include variable values in another table. In that case, append
the column name to the database identifier, separated by a colon; i.e.
variable:variable_setting.

<P>

code: 24.13
section: CATALOG_CFG
type: item
title: CheckoutFrame

<A NAME="CheckoutFrame">CheckoutFrame</A></H2>

The frame name where the checkout page will go, if frames are enabled.
Default is not set, or making it subject to the default target.

<P>
<PRE>    CheckoutFrame  _blank
</PRE>
<P>

code: 24.130
section: CATALOG_CFG
type: item
title: Variable

<A NAME="Variable">Variable</A></H2>

Defines a catalog variable that will be available in the current catalog
with the notation __Variable__. Variable identifiers must begin with a
capital letter, and can contain only word characters (<STRONG>A-Z,a-z,0-9</STRONG> and underscore). These are substituted second (right after global
Variables) in any MiniVend page, and can contain any valid MiniVend tags
except global variables.

<P>
<PRE>    Variable   DOCUMENT_ROOT   /usr/local/etc/httpd/htdocs
</PRE>
<P>

code: 24.14
section: CATALOG_CFG
type: item
title: CheckoutPage

<A NAME="CheckoutPage">CheckoutPage</A></H2>


<FONT SIZE=-1>NOTE:</FONT> This directive is deprecated and may disappear
from future versions of MiniVend. It is typical to route people to the
checkout page via a form value (<A HREF="#item_mv_nextpage">mv_nextpage</A>) or link.

<P>
The name of the default page to send the user to when the <CODE>[finish-order]</CODE>
tag is used. Default is ``order''. This is overridden in any number of ways
from order forms.

<P>
<PRE>    CheckoutPage  basket
</PRE>
<P>

code: 24.15
section: CATALOG_CFG
type: item
title: ClearCache

<A NAME="ClearCache">ClearCache</A></H2>


<FONT SIZE=-1>A</FONT> yes/no directive. When set to yes, each time the
catalog is reconfigured or the MiniVend server is restarted the page and
search caches will be cleared. Default is <EM>No</EM>. The cache can always be cleared by removing all files in the <EM>ScratchDir</EM>/PageCache and <EM>ScratchDir</EM>/SearchCache directories. In addition, if static page building is being
used, the output directory will be cleared before build if this directive
is set.

<P>
<PRE>    ClearCache  Yes
</PRE>
<P>

code: 24.16
section: CATALOG_CFG
type: item
title: CollectData

<A NAME="CollectData">CollectData</A></H2>

The points at which to log various data items collected by MiniVend, such as failed or successful searches. This allows you to find out what your customers are searching for and 
<FONT SIZE=-1>NOT</FONT> finding -- perhaps you want to add it, or change your product description to match. Uses something like the 
<FONT SIZE=-1>HTTP</FONT> common log format.


<P>
The choices to enter are:

<P>
<PRE>  matched    Search strings that match
  nomatch    Search strings that fail to match
  page       Pages that are accessed
  nopage     Pages that are not found
  basket     Items placed in shopping carts
  cache      Pages/searches added to cache
</PRE>
<P>
Enter as a space or comma-separated list, i.e.

<P>
<PRE>    CollectData   matched,nomatch,page
</PRE>
<P>
Orders are typically logged to other files via AsciiTrack, AsciiBackend, or
the <CODE>[tag log ...]data[/tag]</CODE> construct.

<P>

code: 24.17
section: CATALOG_CFG
type: item
title: CommonAdjust

<A NAME="CommonAdjust">CommonAdjust</A></H2>


<FONT SIZE=-1>IMPORTANT</FONT> 
<FONT SIZE=-1>NOTE:</FONT> <CODE>CommonAdjust</CODE> has been changed to support a chained pricing scheme. The following text
describes the old definition of CommonAdjust when used in concert with <A HREF="#item_PriceAdjustment">PriceAdjustment</A>. See
<EM>Price Maintenance with CommonAdjust</EM>.

<P>

<FONT SIZE=-1>A</FONT> MiniVend database identifier specifying a database
that contains, keyed on the item attribute value (not the product code!),
any price adjustments that are to be done based on item attributes.

<P>
Care needs to be used. Each attribute specified in <EM>PriceAdjustment</EM>
must have a corresponding column with the same name (case-sensitive), which
when keyed by the item attribute value yields the price adjustment (if any)
to be made for <EM>any</EM> item having that attribute and containing that value. Used in concert with <EM>PriceAdjustment</EM>, and is not set by default, disabling the common adjustment database
feature.

<P>
<PRE>    CommonAdjust   adjustments
</PRE>
<P>
Can be set in the <EM>Locale</EM> settings to allow different price adjustment databases for different currencies 
<FONT SIZE=-1>(MV3.07</FONT> and up).


<P>

code: 24.18
section: CATALOG_CFG
type: item
title: ConfigDir

<A NAME="ConfigDir">ConfigDir</A></H2>

The default directory where directive values will be read from when using
the &lt;file notation. Default is <A HREF="#item_config">config</A>. The name is relative to the catalog directory unless preceded by a /.

<P>
<PRE>    ConfigDir      variables
</PRE>
<P>

code: 24.19
section: CATALOG_CFG
type: item
title: CookieDomain

<A NAME="CookieDomain">CookieDomain</A></H2>

Allows you to set a domain so that two servers can handle traffic. For
example, if you wanted to use server addresses of <STRONG>secure.yourdomain.com</STRONG>
and <STRONG>www.yourdomain.com</STRONG> then you could set it to:

<P>
<PRE>    CookieDomain    .yourdomain.com
</PRE>
<P>
More than one domain can be set. It <STRONG>must</STRONG> have at least two periods or browsers will ignore it.

<P>

code: 24.20
section: CATALOG_CFG
type: item
title: CookieLogin

<A NAME="CookieLogin">CookieLogin</A></H2>

Allows users to save their username/password (for Vend::UserDB) in a cookie. Expiration set by SaveExpire, renewed every time they log in. To cause the cookie to be generated originally, the 
<FONT SIZE=-1>CGI</FONT> variable
 <CODE>mv_cookie_password</CODE> or <CODE>mv_cookie_username</CODE>
must be set. The former causes both username and password to be saved, the
latter just the username.

<P>
<PRE>    CookieLogin  Yes
</PRE>
<P>
Default is <CODE>No</CODE>.

<P>

code: 24.21
section: CATALOG_CFG
type: item
title: Cookies

<A NAME="Cookies">Cookies</A></H2>

Determines whether we will send (and read back) a cookie to get the session 
<FONT SIZE=-1>ID</FONT> for links that go outside the catalog. Allows arbitrary 
<FONT SIZE=-1>HREF</FONT> links to be placed in MiniVend pages, while still saving the contents of the session. The default is
 <STRONG>Yes</STRONG>, which is a change from MiniVend 2.x.

<P>
<PRE>    Cookies         Yes
</PRE>
<P>
If the <EM>Cookies</EM> directive is enabled, and mv_save_session is set upon submission of a user form (or in the 
<FONT SIZE=-1>CGI</FONT> variables through a perl

<EM>GlobalSub</EM>), the cookie will be persistent for the period defined by <EM>SaveExpire</EM>.

<P>
Caching and static page building will never be in effect unless this
directive is enabled.

<P>

code: 24.22
section: CATALOG_CFG
type: item
title: CreditCardAuto

<A NAME="CreditCardAuto">CreditCardAuto</A></H2>

If set to <EM>Yes</EM>, enables the automatic encryption and saving of credit card information. In order for this to work properly, the EncryptProgram directive must be set to properly encode the field. The best way to set EncryptProgram is with 
<FONT SIZE=-1>PGP</FONT> in the 
<FONT SIZE=-1>ASCII</FONT> armor mode.


<P>
This option uses the following standard fields on MiniVend order processing
forms:

<P><DL>
<DT><STRONG><A NAME="item_mv_credit_card_number">mv_credit_card_number</A></STRONG><DD>

The actual credit card number, which will be wiped from memory after checking to see if it is a valid Amex, Visa, 
<FONT SIZE=-1>MC,</FONT> or Discover card number. This variable will never be carried forward in the user session.

 

<P><DT><STRONG><A NAME="item_mv_credit_card_exp_all">mv_credit_card_exp_all</A></STRONG><DD>

The expiration date, as a text field in the form 
<FONT SIZE=-1>MM/YY</FONT> (will take a four-digit year as well). If it is
not present, the fields <A HREF="#item_mv_credit_card_exp_month">mv_credit_card_exp_month</A> and
<A HREF="#item_mv_credit_card_exp_year">mv_credit_card_exp_year</A> are looked at. It is set by MiniVend when the card validation returns, if
not previously set.
 

<P><DT><STRONG><A NAME="item_mv_credit_card_exp_month">mv_credit_card_exp_month</A></STRONG><DD>

The expiration date month, used if the <A HREF="#item_mv_credit_card_exp_all">mv_credit_card_exp_all</A> field is not present. It is set by MiniVend when the card validation
returns, if not previously set.
 

<P><DT><STRONG><A NAME="item_mv_credit_card_exp_year">mv_credit_card_exp_year</A></STRONG><DD>

The expiration date year, used if the <A HREF="#item_mv_credit_card_exp_all">mv_credit_card_exp_all</A> field is not present. It is set by MiniVend when the card validation
returns, if not previously set.
 

<P><DT><STRONG><A NAME="item_mv_credit_card_error">mv_credit_card_error</A></STRONG><DD>

Set by MiniVend to indicate the error if the card does not validate
properly. The error message is not too enlightening if validation is the
problem.
 

<P><DT><STRONG><A NAME="item_mv_credit_card_force">mv_credit_card_force</A></STRONG><DD>

Set this value to 1 to force MiniVend to encrypt the card despite its idea
of validity. Will still set the flag for validity to 0 if the number/date
does not validate. Still won't accept badly formatted expiration dates.
 

<P><DT><STRONG><A NAME="item_mv_credit_card_info">mv_credit_card_info</A></STRONG><DD>

Set by MiniVend to the encrypted card information if the card validates properly. If 
<FONT SIZE=-1>PGP</FONT> is used in 
<FONT SIZE=-1>ASCII</FONT> armor mode, this field can be placed on the order report and embedded in the order email, replete with markers. This allows a secure order to be read for content, without exposing the credit card number to risk.

 

<P><DT><STRONG><A NAME="item_mv_credit_card_valid">mv_credit_card_valid</A></STRONG><DD>

Set by Minivend to true, or 1, if the the card validates properly. Set to 0
otherwise.

<P>


<FONT SIZE=-1>PGP</FONT> is recommended as the encryption program, though you should remember that 
<FONT SIZE=-1>US</FONT> commercial organizations may require a license for 
<FONT SIZE=-1>RSA.</FONT> MiniVend will work with 
<FONT SIZE=-1>GPG,</FONT> the Gnu Privacy Guard.


<P>
<PRE>    CreditCardAuto     Yes
</PRE>
<P>

code: 24.23
section: CATALOG_CFG
type: item
title: CustomShipping

<A NAME="CustomShipping">CustomShipping</A></H2>

If not blank, enables the addition of shipping charges based on quantity or
weight of items ordered. See <EM>SHIPPING</EM>.

<P>
<PRE>    CustomShipping      Yes
</PRE>
<P>

code: 24.24
section: CATALOG_CFG
type: item
title: CyberCash

<A NAME="CyberCash">CyberCash</A></H2>


<FONT SIZE=-1>A</FONT> yes/no directive, default no. Enables CyberCash
payment protocols -- see <EM>Using CyberCash</EM>.

<P>
<PRE>    CyberCash           Yes
</PRE>
<P>

code: 24.25
section: CATALOG_CFG
type: item
title: DataDir

<A NAME="DataDir">DataDir</A></H2>

The location of the extra database files if no path information is
provided. Set to ``products'' as the default, and is relative to VendRoot
if there is no leading slash. May not be set to an absolute directory
unless NoAbsolute is defined as No.

<P>
<PRE>    DataDir             /user/data
</PRE>
<P>

code: 24.26
section: CATALOG_CFG
type: item
title: Database

<A NAME="Database">Database</A></H2>

Definition of an arbitrary database, in the form ``Database database file type'', where ``file'' is the name of an 
<FONT SIZE=-1>ASCII</FONT> file in the same format as the products database. The file is relative to VendRoot, and is put in

<EM>DataDir</EM> if no path is provided. Records can be accessed with the
<CODE>[data database field key]</CODE> tag. Database names are restricted to the alphanumeric characters
(including the underscore). See <EM>DATABASES</EM>.

<P>
<PRE>    Database      BookReviews  reviews.txt   3
</PRE>
<P>

code: 24.27
section: CATALOG_CFG
type: item
title: DefaultShipping

<A NAME="DefaultShipping">DefaultShipping</A></H2>

This sets the default shipping mode by initializing the variable
<CODE>mv_ship_mode</CODE>. If not set in <EM>catalog.cfg</EM>, it is <EM>default</EM>.

<P>
<PRE>    DefaultShipping     UPS
</PRE>
<P>

code: 24.28
section: CATALOG_CFG
type: item
title: Delimiter

<A NAME="Delimiter">Delimiter</A></H2>

One of 
<FONT SIZE=-1>TAB,</FONT> 
<FONT SIZE=-1>PIPE,</FONT> 
<FONT SIZE=-1>CSV,</FONT> or your own custom delimiter. (It is not suggested that you use a custom delimiter). 
<FONT SIZE=-1>TAB</FONT> means a tab-delimited database (the default if not set), 
<FONT SIZE=-1>PIPE</FONT> a pipe-delimited one, and 
<FONT SIZE=-1>CSV</FONT> a quote-comma format.


<P>
<PRE>    Delimiter           PIPE
</PRE>
<P>

<FONT SIZE=-1>IMPORTANT</FONT> 
<FONT SIZE=-1>NOTE:</FONT> It is not recommended that you use 
<FONT SIZE=-1>CSV,</FONT> as it prevents MiniVend's enhanced search features from working properly. It is also very slow for importing large databases.


<P>

code: 24.29
section: CATALOG_CFG
type: item
title: DescriptionField

<A NAME="DescriptionField">DescriptionField</A></H2>

The field that will be accessed with the <CODE>[item-description]</CODE> element.

<P>
<PRE>    DescriptionField    ProductDescription
</PRE>
<P>
Default is <A HREF="#item_description">description</A>. It is no longer a fatal error if this field does not exist.

<P>

code: 24.30
section: CATALOG_CFG
type: item
title: DisplayErrors

<A NAME="DisplayErrors">DisplayErrors</A></H2>

If the administrator has enabled <EM>DisplayErrors</EM> globally, then setting this to ``Yes'' will display the error returned from
MiniVend in case something is wrong with embedded Perl programs, tags, or
(horrors!) MiniVend itself. Usually you will only want to use this during
development or debugging -- default is <STRONG>no</STRONG>.

<P>
<PRE>    DisplayErrors       Yes
</PRE>
<P>

code: 24.31
section: CATALOG_CFG
type: item
title: DynamicData

<A NAME="DynamicData">DynamicData</A></H2>

When set to one or more MiniVend database identifiers, any pages using data
items from the specified <CODE>database(s)</CODE> will not be cached or
built statically. This allows dynamic updating of certain arbitrary (or
even product) databases while still allowing static/cached page performance
gains on pages not using those data items.

<P>
<PRE>    DynamicData         inventory
</PRE>
<P>
Overridden by <CODE>[tag flag build][/tag]</CODE> or <CODE>[tag flag cache][/tag]</CODE>, depending on context.

<P>

code: 24.32
section: CATALOG_CFG
type: item
title: EncryptProgram

<A NAME="EncryptProgram">EncryptProgram</A></H2>

Contains a program command line specification that indicates how an
external encryption program will work. Two placeholders, <CODE>%p</CODE> and
<A HREF="#item__f">%f</A>, are defined, which are replaced at encryption time with the password and
temporary file name respectively. See <EM>Order Security</EM>.

<P>
This is separate from the <EM>PGP</EM> directive, which enables 
<FONT SIZE=-1>PGP</FONT> encryption of the entire order.

<P>
If 
<FONT SIZE=-1>PGP</FONT> is the encryption program (MiniVend determines
this by searching for the string <CODE>pgp</CODE> in the command string), no password field or file field need be used -- the
field mv_credit_card_number will never be written to disk in that case.

<P>
<PRE>    EncryptProgram      /usr/local/bin/pgp -feat sales@company.com
</PRE>
<P>

code: 24.33
section: CATALOG_CFG
type: item
title: ErrorFile

<A NAME="ErrorFile">ErrorFile</A></H2>

This is where MiniVend will write its runtime errors for 
<FONT SIZE=-1>THIS</FONT> 
<FONT SIZE=-1>CATALOG</FONT> 
<FONT SIZE=-1>ONLY.</FONT> It can be shared with other catalogs or the main MiniVend error log, but if you make it root-based, be careful that you have permission to write the file, or bad things will happen.


<P>
<PRE>    ErrorFile   /home/minivend/error.log
</PRE>
<P>

code: 24.34
section: CATALOG_CFG
type: item
title: ExtraSecure

<A NAME="ExtraSecure">ExtraSecure</A></H2>

Disallows access to pages which are marked with AlwaysSecure unless the browser is in 
<FONT SIZE=-1>HTTPS</FONT> mode. 
<FONT SIZE=-1>A</FONT> yes/no directive -- default is 'No'.


<P>
<PRE>    ExtraSecure  Yes
</PRE>
<P>

code: 24.35
section: CATALOG_CFG
type: item
title: FieldDelimiter

<A NAME="FieldDelimiter">FieldDelimiter</A></H2>

In conjunction with <EM>RecordDelimiter</EM>, allows custom database formats to be defined. The first string is the
database type identifier, and the second is the field delimiter with C/Perl
style double-quoted string format, i.e. \n is a newline.

<P>
<PRE>    FieldDelimiter   Tilde   ~
    RecordDelimiter  Tilde   \n
    Database  mydata mydata.txt Tilde
</PRE>
<P>

code: 24.36
section: CATALOG_CFG
type: item
title: FinishOrder

<A NAME="FinishOrder">FinishOrder</A></H2>


<FONT SIZE=-1>A</FONT> text string or image tag which is substituted for
the <CODE>[finish_order]</CODE> tag.

<P>
<PRE>    FinishOrder &lt;IMG SRC=&quot;/icons/fin_ord.gif&quot; ALT=&quot;Check Basket&quot;&gt;
</PRE>
<P>
This is deprecated, and may be removed from future versions of MiniVend.

<P>

code: 24.37
section: CATALOG_CFG
type: item
title: FormIgnore

<A NAME="FormIgnore">FormIgnore</A></H2>

Set to the <CODE>name(s)</CODE> of variables that should not be carried in
the user session values. Must match exactly and are case sensitive.

<P>
<PRE>    FormIgnore    mv_searchtype
</PRE>
<P>

code: 24.38
section: CATALOG_CFG
type: item
title: FractionalItems

<A NAME="FractionalItems">FractionalItems</A></H2>

Whether items in the shopping cart should be allowed to be fractional, i.e.
2.5 or 1.25. Default is no.

<P>
<PRE>    FractionalItems     Yes
</PRE>
<P>

code: 24.39
section: CATALOG_CFG
type: item
title: FrameFlyPage

<A NAME="FrameFlyPage">FrameFlyPage</A></H2>

The MiniVend-style page name (i.e. no .html extension, relative to <EM>PageDir</EM>) which contains the special on-the-fly page for when frames are in use. If
not set (the default), the standard flypage will be used.

<P>
<PRE>    FrameFlyPage      fr_flypage
</PRE>
<P>

code: 24.40
section: CATALOG_CFG
type: item
title: FrameLinkDir

<A NAME="FrameLinkDir">FrameLinkDir</A></H2>

This parameter controls the directory where frame-based on-the-fly pages
will be built during static builds. This allows a different presentation
for frames and non-frames catalog incarnations.

<P>
It is not an absolute path, but is relative to <EM>StaticDir</EM>. Default is
<CODE>framefly</CODE>. 
<FONT SIZE=-1>A</FONT> <EM>StaticDir</EM> of /var/www/htdocs/simple/pages would yield a FrameLinkDir location of
/var/www/htdocs/simple/pages/framefly.

<P>
<PRE>    FrameLinkDir      frames
</PRE>
<P>

code: 24.41
section: CATALOG_CFG
type: item
title: FrameOrderPage

<A NAME="FrameOrderPage">FrameOrderPage</A></H2>

The MiniVend-style page name (i.e. no .html extension, relative to <EM>PageDir</EM>) which contains the special order page for when frames are in use. If not
set (the default), the standard order page will be used. Vaguely
deprecated, as multiple order pages are better set with the <A HREF="#item_mv_orderpage">mv_orderpage</A> variable.

<P>
<PRE>    FrameOrderPage      fr_order
</PRE>
<P>

code: 24.42
section: CATALOG_CFG
type: item
title: FrameSearchPage

<A NAME="FrameSearchPage">FrameSearchPage</A></H2>

The MiniVend-style page name (i.e. no .html extension, relative to <EM>PageDir</EM>) which contains the special search page for when frames are in use. If not
set (the default), the standard search page will be used. Vaguely
deprecated, as multiple search pages are better set with the <A HREF="#item_mv_search_page">mv_search_page</A> variable.

<P>
<PRE>    FrameSearchPage     fr_resul
</PRE>
<P>

code: 24.43
section: CATALOG_CFG
type: item
title: FramesDefault

<A NAME="FramesDefault">FramesDefault</A></H2>

Whether the first access by a user will place them in frames mode. Default
is <STRONG>no</STRONG>.

<P>
<PRE>    FramesDefault       Yes
</PRE>
<P>

code: 24.44
section: CATALOG_CFG
type: item
title: Glimpse

<A NAME="Glimpse">Glimpse</A></H2>

The pathname for the glimpse command, used if glimpse searches are to be
enabled. If you wish to use <CODE>glimpseserver</CODE>, you must include the 
<FONT SIZE=-1>-C,</FONT> 
<FONT SIZE=-1>-J,</FONT> and 
<FONT SIZE=-1>-K</FONT> tags if they are needed.


<P>
<PRE>    Glimpse  /usr/local/bin/glimpse -C -J srch_engine -K2345
</PRE>
<P>

code: 24.45
section: CATALOG_CFG
type: item
title: Help

<A NAME="Help">Help</A></H2>

The Help directive allows you to define an unlimited number of help
messages or image specifications that reside in a file (or files). It is
called by the <CODE>[help item]</CODE> tag, where item is the first line of a help file entry which looks like:

<P>
<PRE> help1
 This is help item one. It ends after a blank line, and
 is called by a [help help1] element embedded in a MiniVend page.
 
 help2
 This is help item two. It ends after a blank line, and
 is called by a [help help2] element embedded in a MiniVend page.
</PRE>
<P>
If the file (or the entry) does not exist at program configuration time,
the tag is simply stripped. The line in the <EM>catalog.cfg</EM> file takes the form of the directive, followed by any number of vend-style
file names (relative to the PageDir, with no .html suffix). See the demo
for an example of how it is used.

<P>
<PRE>    Help  help/hintfile
</PRE>
<P>
The Help directive is vaguely deprecated in favor of arbitrary databases
and <EM>Variable</EM>.

<P>

code: 24.46
section: CATALOG_CFG
type: item
title: ImageAlias

<A NAME="ImageAlias">ImageAlias</A></H2>

Aliases for images, ala Apache/NCSA ScriptAlias and Alias directives.
Relocates images based in a particular directory to another for MiniVend
use -- operates <EM>after</EM> ImageDir. Useful for editing MiniVend pages with an 
<FONT SIZE=-1>HTML</FONT> editor. Default is blank.

<P>
<PRE>    ImageAlias  /images/  /thiscatalog/images/
</PRE>
<P>

code: 24.47
section: CATALOG_CFG
type: item
title: ImageDir

<A NAME="ImageDir">ImageDir</A></H2>

The directory where all <EM>relative</EM> 
<FONT SIZE=-1>IMG</FONT> and 
<FONT SIZE=-1>INPUT</FONT> source file specifications are based. 
<FONT SIZE=-1>IT</FONT> 
<FONT SIZE=-1>MUST</FONT> 
<FONT SIZE=-1>HAVE</FONT> 
<FONT SIZE=-1>A</FONT> 
<FONT SIZE=-1>TRAILING</FONT> / 
<FONT SIZE=-1>TO</FONT> 
<FONT SIZE=-1>WORK.</FONT> If the images are to be in the DocumentRoot (of the 
<FONT SIZE=-1>HTTP</FONT> server or virtual server) subdirectory
 <EM>images</EM>, for example, you would use the ImageDir specification '/images/'. This would change SRC=``order.gif'' to SRC=``/images/order.gif'' in 
<FONT SIZE=-1>IMG</FONT> and 
<FONT SIZE=-1>INPUT</FONT> tags. It has no effect on other 
<FONT SIZE=-1>SRC</FONT> tags.


<P>
<PRE>    ImageDir /images/
</PRE>
<P>
Can be set in the <EM>Locale</EM> settings to allow different image sets for different locales 
<FONT SIZE=-1>(MV3.07</FONT> and up).

<P>

code: 24.48
section: CATALOG_CFG
type: item
title: ImageDirInternal

<A NAME="ImageDirInternal">ImageDirInternal</A></H2>


<FONT SIZE=-1>A</FONT> value for <EM>ImageDir</EM> only when the internal 
<FONT SIZE=-1>HTTP</FONT> server is in use. It must have a trailing / to
work, and should always begin with a fully-qualified path starting with <CODE>http://</CODE>.

<P>
<PRE>    ImageDirInternal <A HREF="http://www.server.name/images/">http://www.server.name/images/</A>
</PRE>
<P>

code: 24.49
section: CATALOG_CFG
type: item
title: ImageDirSecure

<A NAME="ImageDirSecure">ImageDirSecure</A></H2>


<FONT SIZE=-1>A</FONT> value for <EM>ImageDir</EM> only the pages are being served via 
<FONT SIZE=-1>HTTPS.</FONT> It must have a trailing / to work, and should
always begin with a fully-qualified path starting with <CODE>http://</CODE>.

<P>
<PRE>    ImageDirSecure   /secure/images/
</PRE>
<P>
This is useful if you are using a separate 
<FONT SIZE=-1>HTTPS</FONT> and 
<FONT SIZE=-1>HTTP</FONT> server, and cannot make the image directory path heads match.


<P>

code: 24.50
section: CATALOG_CFG
type: item
title: ItemLinkDir

<A NAME="ItemLinkDir">ItemLinkDir</A></H2>

The directory where the <CODE>[item-link]</CODE> tag will base all of its hot links in, relative to the pages directory. The
default is blank, basing all links in the pages directory. If set, it needs
a trailing '/' to operate properly. This directive is deprecated, and may
disappear in future versions of MiniVend.

<P>
<PRE>    ItemLinkDir     partno/
</PRE>
<P>

code: 24.51
section: CATALOG_CFG
type: item
title: ItemLinkValue

<A NAME="ItemLinkValue">ItemLinkValue</A></H2>

Specifies the text or image you want to use to provide a clickable link to
the catalog page when using the <CODE>[item-link]</CODE> tag (in the search form, or other forms). This directive is deprecated, and
may disappear in future versions of MiniVend.

<P>
<PRE>    ItemLinkValue   &lt;IMG SRC=&quot;/images/gopage.gif&quot; ALT=&quot;GO TO PAGE&quot;&gt;
</PRE>
<P>

code: 24.52
section: CATALOG_CFG
type: item
title: Locale

<A NAME="Locale">Locale</A></H2>

Sets the special locale array. Tries to use 
<FONT SIZE=-1>POSIX</FONT> setlocale based on the value of itself, then
tries to accept a custom setting with the proper definitions of <CODE>mon_decimal_point</CODE>, <CODE>thousands_sep</CODE>, and <CODE>frac_digits</CODE>, which are the the only international settings required. Default if not
set is to use US-English settings.

<P>
Example of the custom setting:

<P>
<PRE>    Locale     custom mon_decimal_point , mon_thousands_sep . frac_digits 0
</PRE>
<P>
Example of 
<FONT SIZE=-1>POSIX</FONT> setlocale for France, if properly aliased:

<P>
<PRE>    Locale     fr
</PRE>
<P>
See <CODE>setlocale(3)</CODE> for more information. If embedded Perl code
is used to sort search returns, then the <CODE>setlocale()</CODE> will
carry through to string collation.

<P>
MiniVend 3.07 extends the Locale array to accept many more settings. See <EM>Internationalization</EM>.

<P>

code: 24.53
section: CATALOG_CFG
type: item
title: LocaleDatabase

<A NAME="LocaleDatabase">LocaleDatabase</A></H2>

Set to the MiniVend database <EM>identifier</EM> of a table that contains Locale settings. These settings add on to and
overwrite any that are set in the catalog configuration files, including
any #include files.

<P>
<PRE>    Database       locale_info  locale_info.asc  TAB
    LocaleDatabase locale_info
</PRE>
<P>

code: 24.54
section: CATALOG_CFG
type: item
title: LogFile

<A NAME="LogFile">LogFile</A></H2>


<FONT SIZE=-1>A</FONT> file where user pages accesses and search
specifications will be logged if CollectData is set. Defaults to <CODE>etc/log</CODE>.

<P>
<PRE>    LogFile        etc/log
</PRE>
<P>

code: 24.55
section: CATALOG_CFG
type: item
title: MasterHost

<A NAME="MasterHost">MasterHost</A></H2>

The 
<FONT SIZE=-1>IP</FONT> address that can reconfigure the catalog. Default is blank, disabling remote check of 
<FONT SIZE=-1>IP</FONT> address.


<P>
<PRE>    MasterHost    10.10.10.1
</PRE>
<P>

code: 24.56
section: CATALOG_CFG
type: item
title: MixMatch

<A NAME="MixMatch">MixMatch</A></H2>


<FONT SIZE=-1>A</FONT> yes/no directive. 
<FONT SIZE=-1>A</FONT> setting of
 <STRONG>yes</STRONG> says that quantity price breaks will be on 
<FONT SIZE=-1>TOTAL</FONT> quantity, <STRONG>no</STRONG> says that quantity price breaks are on a per-item quantity. Default is <STRONG>no</STRONG>.

<P>
<PRE>    MixMatch        yes
</PRE>
<P>

code: 24.57
section: CATALOG_CFG
type: item
title: MsqlDB

<A NAME="MsqlDB">MsqlDB</A></H2>

Sets the name of the mSQL database (must be present on the default server).
Defaults to <EM>minivend</EM>.

<P>
<PRE>    MsqlDB          catalog
</PRE>
<P>

code: 24.58
section: CATALOG_CFG
type: item
title: Mv_AlinkColor

<A NAME="Mv_AlinkColor">Mv_AlinkColor</A></H2>

Sets the accessed link colors to be used in the color schemes. The line must begin with 
<FONT SIZE=-1>'BEGIN',</FONT> then is followed by up to 15 
<FONT SIZE=-1>RGB</FONT> color specifications for visited link color. The specification can be in 
<FONT SIZE=-1>#RRGGBB</FONT> color format, or can be one of the colors that will be recognized (steelblue, white, etc.) Each color should be separated by one or more spaces. Set to
 <CODE>none</CODE> to disable a color (use the browser default) for a particular scheme.
Remember, the schemes are numbered in the order that they occur.

<P>
<PRE>    Mv_VlinkColor BEGIN  orange none blue
</PRE>
<P>

code: 24.59
section: CATALOG_CFG
type: item
title: Mv_Background

<A NAME="Mv_Background">Mv_Background</A></H2>

Sets the background patterns to be used in the color schemes. The line must begin with 
<FONT SIZE=-1>'BEGIN',</FONT> then is followed by up to 15 pattern URLs containing background patterns to be used with the color schemes. Each pattern should be separated by one or more spaces. set to 0 to disable a background pattern for a particular scheme. Remember, the schemes are numbered in the order that they occur.


<P>
<PRE>    Mv_Background BEGIN /images/blue_pap.gif 0 /images/temple.jpg
</PRE>
<P>

code: 24.60
section: CATALOG_CFG
type: item
title: Mv_BgColor

<A NAME="Mv_BgColor">Mv_BgColor</A></H2>

Sets the background colors to be used in the color schemes. The line must begin with 
<FONT SIZE=-1>'BEGIN',</FONT> then is followed by up to 15 
<FONT SIZE=-1>RGB</FONT> color specifications for background color. The specification can be in 
<FONT SIZE=-1>#RRGGBB</FONT> color format, or can be one of the colors that will be recognized (steelblue, white, etc.) Each color should be separated by one or more spaces. Set to
 <CODE>none</CODE> to disable a color (use the browser default) for a particular scheme.
Remember, the schemes are numbered in the order that they occur.

<P>
<PRE>    Mv_BgColor BEGIN  steelblue none white
</PRE>
<P>

code: 24.61
section: CATALOG_CFG
type: item
title: Mv_LinkColor

<A NAME="Mv_LinkColor">Mv_LinkColor</A></H2>

Sets the link colors to be used in the color schemes. The line must begin with 
<FONT SIZE=-1>'BEGIN',</FONT> then is followed by up to 15 
<FONT SIZE=-1>RGB</FONT> color specifications for link color. The specification can be in 
<FONT SIZE=-1>#RRGGBB</FONT> color format, or can be one of the colors that will be recognized (steelblue, white, etc.) Each color should be separated by one or more spaces. Set to
 <CODE>none</CODE> to disable a color (use the browser default) for a particular scheme.
Remember, the schemes are numbered in the order that they occur.

<P>
<PRE>    Mv_LinkColor BEGIN  ltgreen none red
</PRE>
<P>

code: 24.62
section: CATALOG_CFG
type: item
title: Mv_TextColor

<A NAME="Mv_TextColor">Mv_TextColor</A></H2>

Sets the text colors to be used in the color schemes. The colors are
accessed with the <CODE>[body n]</CODE> tag, where n is the color scheme number. The line must begin with 
<FONT SIZE=-1>'BEGIN',</FONT> then is followed by up to 15 
<FONT SIZE=-1>RGB</FONT> color specifications for text color. The specification can be in 
<FONT SIZE=-1>#RRGGBB</FONT> color format, or can be one of the colors that will be recognized (steelblue, white, etc.) Each color should be separated by one or more spaces. Set to
 <CODE>none</CODE> to disable a color (use the browser default) for a particular scheme.
Remember, the schemes are numbered in the order that they occur, beginning
with 1.

<P>
<PRE>    Mv_TextColor BEGIN  white none black
</PRE>
<P>

code: 24.63
section: CATALOG_CFG
type: item
title: Mv_VlinkColor

<A NAME="Mv_VlinkColor">Mv_VlinkColor</A></H2>

Sets the visited link colors to be used in the color schemes. The line must begin with 
<FONT SIZE=-1>'BEGIN',</FONT> then is followed by up to 15 
<FONT SIZE=-1>RGB</FONT> color specifications for visited link color. The specification can be in 
<FONT SIZE=-1>#RRGGBB</FONT> color format, or can be one of the colors that will be recognized (steelblue, white, etc.) Each color should be separated by one or more spaces. Set to
 <CODE>none</CODE> to disable a color (use the browser default) for a particular scheme.
Remember, the schemes are numbered in the order that they occur.

<P>
<PRE>    Mv_VlinkColor BEGIN  orange none blue
</PRE>
<P>

code: 24.64
section: CATALOG_CFG
type: item
title: NewEscape

<A NAME="NewEscape">NewEscape</A></H2>


<FONT SIZE=-1>A</FONT> yes/no directive. When set to <STRONG>Yes</STRONG>, it disallows the old-style period escaping of one-click search spec
strings, and allows HTTP-style escaping of passed arguments (the <CODE>[page name arg]</CODE>
tag, among others).

<P>
This should probably be set to <CODE>Yes</CODE> for new catalogs.

<P>
<PRE>    NewEscape  Yes
</PRE>
<P>

code: 24.65
section: CATALOG_CFG
type: item
title: NewReport

<A NAME="NewReport">NewReport</A></H2>


<FONT SIZE=-1>A</FONT> yes/no directive. When set to <STRONG>No</STRONG>, it allows the old-style <CODE>$variable</CODE> interpolation on MiniVend
order reports. Default is
<EM>Yes</EM>, where <CODE>$variable</CODE> values are not interpolated with user
session values (you use the <CODE>[value variable]</CODE> tag instead).

<P>
The default prevents clashes with embedded Perl code.

<P>
<PRE>    NewReport  No
</PRE>
<P>

code: 24.66
section: CATALOG_CFG
type: item
title: NewTags

<A NAME="NewTags">NewTags</A></H2>


<FONT SIZE=-1>A</FONT> yes/no directive. When set to <STRONG>Yes</STRONG>, it defaults all pages to using the new page syntax. This can be
counteracted with an <CODE>[old]</CODE> tag at the very top of the page, or by surrounding older sections of code
with the
<CODE>[compat] MINIVEND TAGS [/compat]</CODE> tag pair. Default is <STRONG>No</STRONG>.

<P>
<PRE>    NewTags    No
</PRE>
<P>

code: 24.67
section: CATALOG_CFG
type: item
title: NoCache

<A NAME="NoCache">NoCache</A></H2>

The names of MiniVend pages that are not to be cached (if <EM>Page Cache</EM>
is being used) or built statically (if <EM>STATIC PAGE BUILDING</EM> is in use). If the name is a directory, then no pages in that directory (or
any below it) be cached or built statically.

<P>
<PRE>    NoCache    ord
    NoCache    special
</PRE>
<P>

code: 24.68
section: CATALOG_CFG
type: item
title: NoImport

<A NAME="NoImport">NoImport</A></H2>

When set to one or more MiniVend database identifiers, those <CODE>database(s)</CODE> will never be subject to import. Useful for 
<FONT SIZE=-1>SQL</FONT> databases, or databases that will *never* change.


<P>
<PRE>    NoImport   inventory
</PRE>
<P>

code: 24.69
section: CATALOG_CFG
type: item
title: NonTaxableField

<A NAME="NonTaxableField">NonTaxableField</A></H2>

The name of the field in the products database that is set (to 1 or yes) if
an item is not to be taxed. Will log an error and tax it anyway if the
field doesn't exist in the database. Blank by default, disabling the
feature.

<P>
<PRE>    NonTaxableField    wholesale
</PRE>
<P>

code: 24.70
section: CATALOG_CFG
type: item
title: OfflineDir

<A NAME="OfflineDir">OfflineDir</A></H2>

The location of the offline database files for use with the MiniVend
offline database build command. Set to ``offline'' as the default, and is
relative to VendRoot if there is no leading slash.

<P>
<PRE>    OfflineDir          /usr/data/minivend/offline
</PRE>
<P>

code: 24.71
section: CATALOG_CFG
type: item
title: OldShipping

<A NAME="OldShipping">OldShipping</A></H2>

Defines compatibility with older MiniVend shipping files -- they will break
if using formulas where <A HREF="#item_x">x</A> is used as the substituted-for string for the accumulated total. 
<FONT SIZE=-1>A</FONT> yes/no directive -- default is No. This will
disappear soon.

<P>
<PRE>    OldShipping  Yes
</PRE>
<P>

code: 24.72
section: CATALOG_CFG
type: item
title: OrderCounter

<A NAME="OrderCounter">OrderCounter</A></H2>

The name of the file (relative to catalog root if no leading /) that
maintains the order number counter. If not set, the order will be assigned
a string based on the time of the order and the user's session number.

<P>
<PRE>    OrderCounter       etc/order.number
</PRE>
<P>

code: 24.73
section: CATALOG_CFG
type: item
title: OrderFrame

<A NAME="OrderFrame">OrderFrame</A></H2>

The frame name where the order page will go, if frames are enabled. If the
frame doesn't exist, a new frame will be created. The default is '_top',
which fills the browser window with the page.

<P>
<PRE>    OrderFrame          _blank
</PRE>
<P>

code: 24.74
section: CATALOG_CFG
type: item
title: OrderLineLimit

<A NAME="OrderLineLimit">OrderLineLimit</A></H2>

The number of items that the user is allowed to place in the shopping cart.
Some poorly-mannered robots may ``attack'' your site by following all links
one after another. Some even ignore any <CODE>robots.txt</CODE> file you may have created. If one of these bad robots orders several dozen
or more items, then the time required to save and restore the shopping cart
from the user session may become excessive.

<P>
If the limit is exceeded, then the command defined in the Global directive
<EM>LockoutCommand</EM> will be executed and the shopping cart will be emptied. The default is 0,
disabling the check. Set it to a number greater than the number of line
items you ever expect a user to order.

<P>
<PRE>    OrderLineLimit   50
</PRE>
<P>

code: 24.75
section: CATALOG_CFG
type: item
title: OrderProfile

<A NAME="OrderProfile">OrderProfile</A></H2>

Allows an unlimited number of order profiles to be set up, specifying
complex checks to be performed at each of the steps in the checkout
process. The files specified can be located anywhere -- if relative paths
are used, they are relative to the catalog root directory.

<P>
<PRE>    OrderProfile    prof/order0 prof/order1 prof/order2
</PRE>
<P>
They are accessed by setting the <A HREF="#item_mv_order_profile">mv_order_profile</A> variable to the name of the order profile. Multiple profiles can reside in the same file, if separated by 
<FONT SIZE=-1>__END__</FONT> tokens, which must be on a line by themselves.


<P>
The profile is named by placing a name following a 
<FONT SIZE=-1>__NAME__</FONT> pragma:

<P>
<PRE>  __NAME__ billing
</PRE>
<P>
The 
<FONT SIZE=-1>__NAME__</FONT> must begin the line, and be followed by
whitespace and then the name. The search profile can then be accessed by
<EM>mv_order_profile="billing"</EM>. See <EM>Advanced Multi-level Order Pages</EM>.

<P>

code: 24.76
section: CATALOG_CFG
type: item
title: OrderReport

<A NAME="OrderReport">OrderReport</A></H2>

The location of the simple order report file. Defaults to <EM>etc/report</EM>. Not used frequently in later MiniVends, as the custom order report file
is much more flexible.

<P>
<PRE>    OrderReport          /data/order-form
</PRE>
<P>

code: 24.77
section: CATALOG_CFG
type: item
title: PageCache

<A NAME="PageCache">PageCache</A></H2>

When set to <STRONG>Yes</STRONG>, it will enable the caching of pages if the client browser has cookie
capability. If the page has dynamic elements, it will not be cached. This
can improve performance especially on large pages, since the page does not
have to be parsed every time -- just the first. It does not make sense to
enable this while enabling <EM>StaticFly</EM> -- however catalogs with large numbers of items may wish to enable this. 
<FONT SIZE=-1>A</FONT> yes/no directive -- default is No.

<P>
<PRE>    PageCache  yes
</PRE>
<P>

code: 24.78
section: CATALOG_CFG
type: item
title: PageDir

<A NAME="PageDir">PageDir</A></H2>

Location of catalog pages. Defaults to the pages subdirectory in the
VendRoot directory.

<P>
<PRE>    PageDir    /data/catalog/pages
</PRE>
<P>
Can be set in the <EM>Locale</EM> settings to allow different page sets for different locales 
<FONT SIZE=-1>(MV3.07</FONT> and up).

<P>

code: 24.79
section: CATALOG_CFG
type: item
title: PGP

<A NAME="PGP">PGP</A></H2>

If credit card information is to be accepted, and the emailed order will go over an insecure network to reach its destination, 
<FONT SIZE=-1>PGP</FONT> security should be used. The key ring to be used must be for the user that is running the MiniVend server, or defined by the environment variable 
<FONT SIZE=-1>PGPPATH,</FONT> and the key user specified must have a key on the public key ring of that user.


<P>
<PRE>    PGP        /usr/local/bin/pgp -feat orders@company.com
</PRE>
<P>
If this directive is non-null, the 
<FONT SIZE=-1>PGP</FONT> command string as specified will be used to
encrypt the <EM>entire order</EM> -- in addition to any encryption done as a result if <EM>CreditCardAuto</EM>, If for some reason an error comes from 
<FONT SIZE=-1>PGP,</FONT> the customer will be given the special page <A HREF="#item_failed">failed</A>.

<P>

code: 24.80
section: CATALOG_CFG
type: item
title: PageSelectField

<A NAME="PageSelectField">PageSelectField</A></H2>

Sets a products database column which can be used to select the on-the-fly
template page. This allows multiple on-the-fly pages to be defined. If the
field is empty (no spaces, either!) then the default &lt;flypage&gt; will
be used.

<P>
<PRE>    PageSelectField    display_page
</PRE>
<P>

code: 24.81
section: CATALOG_CFG
type: item
title: ParseVariables

<A NAME="ParseVariables">ParseVariables</A></H2>

Determines whether global and catalog variables will be parsed in the
configuration file. Should be set to No until parsing is needed, turned on
for the parsed directives, then set back to No. Default is No.

<P>
<PRE>    Variable STORE_ID  topshop
    ParseVariables Yes
    StaticDir  /home/__STORE_ID__/www/cat
    ParseVariables No
</PRE>
<P>

code: 24.82
section: CATALOG_CFG
type: item
title: Password

<A NAME="Password">Password</A></H2>

The encrypted password that, when entered and sent as 
<FONT SIZE=-1>RECONFIGURE_MINIVEND</FONT> by the reconfigure program, will
be checked against the user entry to enable reconfiguration.

<P>
If you use MiniVend's htpasswd.pl (from 2.03 or higher) it will write the
catalog configuration file if given <CODE>catalog.cfg</CODE> as the file name. The demo starts with an encrypted blank password,
allowing you to just hit enter.

<P>
<PRE>    Password                bAWoVkuzphOX.
</PRE>
<P>

code: 24.83
section: CATALOG_CFG
type: item
title: PriceAdjustment

<A NAME="PriceAdjustment">PriceAdjustment</A></H2>


<FONT SIZE=-1>A</FONT> MiniVend item attribute (see <EM>UseModifier</EM>) which contains a value upon which a price adjustment to the item may be
made.

<P>

<FONT SIZE=-1>A</FONT> common case would be size. For shirts that are size <EM>XXL</EM>, you might wish to add a dollar to the price for an item. In that case,
you can define a column in the standard pricing database <A HREF="#item_pricing">pricing</A> which is named 
<FONT SIZE=-1>``XXL''.</FONT> If a value is found in that column it will be
added to the price for the item. Negative numbers result in subtraction if
you wish to reduce the price based on an attribute.

<P>
Numbers that begin with an equals sign (<CODE>=</CODE>) are used as absolute prices -- and are interpolated for MiniVend tags
first, so you can use subroutines to set the price. To facilite
coordination with the subroutine, the session variables <CODE>item_code</CODE> and <CODE>item_quantity</CODE> are set to the code and quantity of the item being evaluated. They would be
accessed in a global subroutine with <CODE>$Vend::Session-</CODE>&gt;<CODE>{item_code}</CODE>
and <CODE>$Vend::Session-</CODE>&gt;<CODE>{item_quantity}</CODE>.

<P>
The pricing information must always come from a database because of
security.

<P>
See <EM>CommonAdjust</EM> for another scheme that makes the same adjustment for any item having the
attribute -- both schemes cannot be used at the same time. (This is true
even if you were to change the value of $Vend::Cfg-&gt;{CommonAdjust} in a
subroutine -- the pricing algorithm is built at catalog startup.)

<P>
<PRE>    PriceAdjustment   size
</PRE>
<P>
Can be set in the <EM>Locale</EM> settings to allow different price adjustment fields for different currencies 
<FONT SIZE=-1>(MV3.07</FONT> and up).


<P>

code: 24.84
section: CATALOG_CFG
type: item
title: PriceBreaks

<A NAME="PriceBreaks">PriceBreaks</A></H2>

The quantities where price breaks should be placed. Used to set up the
pricing.asc entries to match actual pricing. Unlimited number of breaks --
only enter the lowest quantity it applies to.

<P>
<PRE>    PriceBreaks         10 25 50 100 1000
</PRE>
<P>

code: 24.85
section: CATALOG_CFG
type: item
title: PriceCommas

<A NAME="PriceCommas">PriceCommas</A></H2>

If you desire no commas in your price numbers (for the <CODE>[item-price]</CODE> tag) set this to <A HREF="#item_no">no</A>. The default is to use commas (or whatever is the thousands separator for
your locale).

<P>
<PRE>    PriceCommas         no
</PRE>
<P>
This would be overridden if a <EM>Locale</EM>  <A HREF="#item_price_picture">price_picture</A> is set.

<P>

code: 24.86
section: CATALOG_CFG
type: item
title: PriceDivide

<A NAME="PriceDivide">PriceDivide</A></H2>

The number the price should be divided by to get the price in units
(dollars or such). The default is one -- if you use penny pricing you can
set it to 100.

<P>
<PRE>    PriceDivide         100
</PRE>
<P>
Can be set in the <EM>Locale</EM> settings to allow a price adjustment factor for different currencies 
<FONT SIZE=-1>(MV3.07</FONT> and up).

<P>

code: 24.87
section: CATALOG_CFG
type: item
title: PriceField

<A NAME="PriceField">PriceField</A></H2>

The field in the product database that will be accessed with the <CODE>[item-price]</CODE> element. Default is ``price''.

<P>
<PRE>    PriceField          ProductPrice
</PRE>
<P>
Can be set in the <EM>Locale</EM> settings to allow different price fields for different currencies 
<FONT SIZE=-1>(MV3.07</FONT> and up).

<P>

code: 24.88
section: CATALOG_CFG
type: item
title: ProductDir

<A NAME="ProductDir">ProductDir</A></H2>

Location of the product files. Defaults to the products subdirectory of the
VendRoot directory. May not be set to an absolute directory unless
NoAbsolute is defined as No.

<P>
<PRE>    ProductDir          /data/catalog/for-sale
</PRE>
<P>
Most people never set this directive and use the default of
<A HREF="#item_products">products</A>.

<P>

code: 24.89
section: CATALOG_CFG
type: item
title: ProductFiles

<A NAME="ProductFiles">ProductFiles</A></H2>

Database tables that should be seen as the ``products'' database.

<P>
<PRE>    ProductFiles    vendor_a vendor_b
</PRE>
<P>
The key thing about this is that each will be searched in sequence for a
product code to order or an <CODE>[item-field ....]</CODE> or <CODE>[loop-field ...]</CODE>
to insert. The main difference between <CODE>[item-field ....]</CODE> and 
<CODE>[item-data table ...]</CODE> is this fall-through behavior.

<P>
Default is <A HREF="#item_products">products</A>.

<P>

code: 24.90
section: CATALOG_CFG
type: item
title: Random

<A NAME="Random">Random</A></H2>

The Random directive allows you to define an unlimited number of random
messages or image specifications that reside in files. It is called by the <CODE>[random]</CODE> tag. You don't know which one will show up! Even 
<FONT SIZE=-1>I</FONT> don't, it is random. If the file does not exist at
program configuration time, the tag is simply stripped. The line in the <EM>minivend.cfg</EM> file takes the form of the directive, followed by any number of vend-style
file names (relative to the PageDir, with no .html suffix).

<P>
<PRE>    Random  rand/message1 rand/message2 rand/message3 rand/message4
</PRE>
<P>

code: 24.91
section: CATALOG_CFG
type: item
title: ReadPermission and WritePermission

<A NAME="ReadPermission_and_WritePermissi">ReadPermission and WritePermission</A></H2>

By default, only the user account that MiniVend runs under (as set by the
setuid permission on vlink) can read and write files created by MiniVend.
WritePermission and ReadPermission can be set to <CODE>user</CODE>, <CODE>group</CODE>, or 'world'.

<P>
<PRE>    ReadPermission      group
    WritePermission     group
</PRE>
<P>

code: 24.92
section: CATALOG_CFG
type: item
title: ReceiptPage

<A NAME="ReceiptPage">ReceiptPage</A></H2>

The page to be displayed as a receipt after the user has submitted an
order. Replaces the standard <A HREF="#item_confirmation">confirmation</A> page. Blank by default, showing no receipt page to the user. Overridden by
the value of <EM>mv_order_receipt</EM>.

<P>
<PRE>    ReceiptPage         receipt
</PRE>
<P>

code: 24.93
section: CATALOG_CFG
type: item
title: RecordDelimiter

<A NAME="RecordDelimiter">RecordDelimiter</A></H2>

In conjunction with <EM>FieldDelimiter</EM>, allows custom database formats to be defined. The first string is the
database type identifier, and the second is the record delimiter with
C/Perl style double-quoted string format, i.e. \n is a newline.

<P>
<PRE>    FieldDelimiter   Tilde   ~
    RecordDelimiter  Tilde   \n
    Database  mydata mydata.txt Tilde
</PRE>
<P>

code: 24.94
section: CATALOG_CFG
type: item
title: RemoteUser

<A NAME="RemoteUser">RemoteUser</A></H2>

The value of the 
<FONT SIZE=-1>HTTP</FONT> environment variable 
<FONT SIZE=-1>REMOTE_USER</FONT> that will enable catalog reconfiguration. You need to enable 
<FONT SIZE=-1>HTTP</FONT> basic authentication for this to work. Default is blank, disabling this check.


<P>
<PRE>    RemoteUser   Billyboy
</PRE>
<P>

code: 24.95
section: CATALOG_CFG
type: item
title: ReportIgnore

<A NAME="ReportIgnore">ReportIgnore</A></H2>


<FONT SIZE=-1>A</FONT> comma-separated list of items you don't want to have
sent by email on the default order report. Default is blank, or none.
Fields beginning with 'mv_', the MiniVend special variables, are
automatically ignored. No additional fields will be used if you are relying
on the newer HTML-style order report.

<P>
<PRE>    ReportIgnore        credit_card_no
</PRE>
<P>

code: 24.96
section: CATALOG_CFG
type: item
title: RequiredFields

<A NAME="RequiredFields">RequiredFields</A></H2>


<FONT SIZE=-1>A</FONT> comma-separated list of items you want to make sure
the customer fills in before an order can be submitted. If an empty field
is found when the customer submits the order, the special page <EM>needfield.html</EM> will be displayed to request that they enter the information. No default.
If custom order profiles are used, this is only done upon the final
placement of the order.

<P>
<PRE>    RequiredFields      name,company,email,address,city,state,zip
</PRE>
<P>

code: 24.97
section: CATALOG_CFG
type: item
title: RobotLimit

<A NAME="RobotLimit">RobotLimit</A></H2>

The RobotLimit directive defines the number of consecutive pages a user
session may access without a 30 second pause. If the limit is exceeded,
then the command defined in the Global directive <EM>LockoutCommand</EM>
will be executed. The default is 0, disabling the check.

<P>
<PRE>    RobotLimit  200
</PRE>
<P>

code: 24.98
section: CATALOG_CFG
type: item
title: Rotate

<A NAME="Rotate">Rotate</A></H2>

The Rotate directive allows you to define an unlimited number of rotating
messages or image specifications that reside in files. It is called by the <CODE>[rotate]</CODE> tag. If the file does not exist at program configuration time, the tag is
simply stripped. The line in the <CODE>catalog.cfg</CODE> file takes the form of the directive, followed by any number of vend-style
file names (relative to the PageDir, with no .html suffix).

<P>
<PRE>    Rotate  rotate/banner1 rotate/banner2 rotate/banner3 rotate/banner4
</PRE>
<P>

code: 24.99
section: CATALOG_CFG
type: item
title: SalesTax

<A NAME="SalesTax">SalesTax</A></H2>

If non-blank, enables automatic addition of sales tax based on the order
form. The value is a comma-separated list of the field names (as placed in
order.html), in priority order, which should be used to look up sales tax
percentage in the salestax.asc database. This database is not supplied with
MiniVend -- it is typically received from a third party by quarterly or
monthly subscription.

<P>
<PRE>    SalesTax            zip,state
</PRE>
<P>

code: 25.00
section: CATALOG_CFG
type: overview
title: CATALOG.CFG

<A NAME="CATALOG_CFG">CATALOG.CFG</A></H1>
<P>
If multiple catalogs are to be run, each must have a <CODE>catalog.cfg</CODE>
file located in the catalog base directory. It contains most of the
configurable parameters for MiniVend -- each is independent from catalog to
catalog.

<P>
In the catalog configuration file, the directives MailOrderTo and VendURL
are <STRONG>required</STRONG>. They are not defined with defaults, and no catalog will operate unless
and until they are set with a value.

<P>
<HR>


code: 25.02
section: ADMINISTERING_MINIVEND
type: item
title: Starting, Stopping, and Re-starting the Servers

<A NAME="Starting_Stopping_and_Re_start">Starting, Stopping, and Re-starting the Servers</A></H2>

The following commands need to have 
<FONT SIZE=-1>VENDROOT</FONT> changed to the main directory where you
installed MiniVend. If you made /home/minivend your MiniVend base
directory, the start command would be /home/minivend/bin/start.

<P>
To start the server:

<P>
<PRE>    VENDROOT/bin/start
</PRE>
<P>
<PRE>          or
</PRE>
<P>
<PRE>    VENDROOT/bin/minivend -serve
</PRE>
<P>
Assuming the server starts correctly, you will see the names of catalogs as they are configured, along with a message stating the process 
<FONT SIZE=-1>ID</FONT> it is running under.


<P>
To re-start the server:

<P>
<PRE>    VENDROOT/bin/restart
</PRE>
<P>
<PRE>          or
</PRE>
<P>
<PRE>    VENDROOT/bin/stop; VENDROOT/bin/minivend -serve
</PRE>
<P>
This is typically done to force MiniVend to re-read its configuration. You will see a message stating that a 
<FONT SIZE=-1>TERM</FONT> signal has been sent to the process 
<FONT SIZE=-1>ID</FONT> the servers are running under -- that information is also sent to /home/minivend/error.log. Check the error.log file for confirmation that the server has restarted properly.


<P>
To stop the server:

<P>
<PRE>    VENDROOT/bin/stop
</PRE>
<P>
You will see a message stating that a 
<FONT SIZE=-1>TERM</FONT> signal has been sent to the process 
<FONT SIZE=-1>ID</FONT> the server is running under -- that information is also sent to /home/minivend/error.log.


<P>
Because processes waiting for selection on some operating systems block
signals, they may have to wait for <EM>HouseKeeping</EM> seconds to stop. The default is 60.

<P>

code: 25.03
section: ADMINISTERING_MINIVEND
type: item
title: UNIX and INET modes

<A NAME="UNIX_and_INET_modes">UNIX and INET modes</A></H2>

As of MiniVend 3.00, both UNIX-domain (the default) or INET-domain sockets can be used for communication. 
<FONT SIZE=-1>INET</FONT> domain sockets are useful when more than one server, connected via a local-area network 
<FONT SIZE=-1>(LAN),</FONT> is used for accessing a MiniVend server.


<P>
<STRONG>IMPORTANT NOTE:</STRONG> When sending sensitive information like credit card numbers over a network,
always ensure that the data is secured by a firewall, or that the MiniVend
server runs on the same machine as any SSL-based server used for
encryption.

<P>
If you only want to run with one method of communication, use the
<CODE>-</CODE>i and <CODE>-</CODE>u flags.

<P>
<PRE>    # Start only in UNIX mode
    VENDROOT/bin/start -u
</PRE>
<P>
<PRE>    # Start only in INET mode
    VENDROOT/bin/start -i
</PRE>
<P>

code: 25.04
section: ADMINISTERING_MINIVEND
type: item
title: User reconfiguration

<A NAME="User_reconfiguration">User reconfiguration</A></H2>

The individual catalogs can be reconfigured by the user by running the
reconfig command. At least one check must be made to authenticate -- by
coming from a particular host (see <EM>MasterHost</EM>), having validated by 
<FONT SIZE=-1>HTTP</FONT> basic authorization (see <EM>RemoteUser</EM>), or by password entry (see <EM>Password</EM>). The ideal way to use it is in combination with 
<FONT SIZE=-1>HTTP</FONT> basic authorization to allow remote reconfiguration by web browser. It is possible at that point to have a completely 
<FONT SIZE=-1>FTP-</FONT> and HTTP-configured catalog.


<P>

<FONT SIZE=-1>A</FONT> <A HREF="#item_reconfig">reconfig</A> script is included with the demo catalogs, set up with the <EM>Password</EM> method of authentication and a blank password, suitable for the user to reconfigure the catalog from a Unix shell. To set it up as a 
<FONT SIZE=-1>CGI,</FONT> use the
 <EM>MasterHost</EM> or <EM>RemoteUser</EM>
authentication methods.

<P>

code: 25.05
section: ADMINISTERING_MINIVEND
type: item
title: Expiring Sessions

<A NAME="Expiring_Sessions">Expiring Sessions</A></H2>

If you have 
<FONT SIZE=-1>DBM</FONT> capability and MiniVend is using it to store the
sessions, you should periodically expire old sessions to keep the session
database file from growing too large.

<P>
<PRE>    expire -c catalog
</PRE>
<P>
There is also an <CODE>expireall</CODE> script which reads all catalog entries in <CODE>minivend.cfg</CODE> and runs <CODE>expire</CODE> on them.

<P>
The <CODE>expire</CODE> script accepts a <CODE>-r</CODE> option which tells it to recover lost disk space.

<P>
On 
<FONT SIZE=-1>UNIX,</FONT> you could add a crontab entry such as the
following:

<P>
<PRE>    # once a day at 4:40 am
    40 4 * * *    perl /home/minivend/bin/expireall -r
</PRE>
<P>
MiniVend will wait until the current transaction is finished before
expiring, so you can do this at any time without disabling web access. Any
search paging files for the affected session (kept in <EM>ScratchDir</EM>) will be removed as well.

<P>
With Windows or other operating systems which don't <CODE>fork(),</CODE>
you will need to stop the server before running <CODE>expire</CODE> -- this will prevent corruption of the database.

<P>
If you are not running 
<FONT SIZE=-1>DBM</FONT> sessions, you can use a perl script to delete all
files not modified in the last one or two days. The following will work if
given an argument of your <STRONG>session directory or session files</STRONG>:

<P>
<PRE>    #!perl
    # expire_sessions.pl -- delete files 2 days old or older
</PRE>
<P>
<PRE>    my @files;
    my $dir;
    foreach $dir (@ARGV) {
        # just push files on the list
        if (-f $dir) { push @files, $_; next; }
</PRE>
<P>
<PRE>        next unless -d $dir;
        
        # get all the file names in the directory
        opendir DIR, $dir or die &quot;opendir $dir: $!\n&quot;;
        push @files, ( map { &quot;$dir/$_&quot; } grep(! /^\.\.?$/, readdir DIR) ) ;
    }
</PRE>
<P>
<PRE>    for (@files) {
        unless (-f $_) {
            warn &quot;skipping $_, not a file.\n&quot;;
            next;
        }
        next unless -M $_ &gt;= 2;
        unlink $_ or die &quot;unlink $_: $!\n&quot;;
    }
</PRE>
<P>
It would be run with a command invocation like:

<P>
<PRE>    perl expire_sessions.pl /home/you/catalogs/simple/session
</PRE>
<P>
You can give it multiple directory names if you have more than one catalog.

<P>
You can adjust this script to do what you wish, of course. Refinements
might include reading the file to ``eval'' the session reference and expire
only customers who are not members.

<P>

code: 25.05
section: ADMINISTERING_MINIVEND
type: item
title: Making the Product Database

<A NAME="Making_the_Product_Database">Making the Product Database</A></H2>

The 
<FONT SIZE=-1>DBM</FONT> product databases can be built offline with the <CODE>offline</CODE>
command. The directory to be used for output is specified either on the
command line with the -d option, or is taken from the <CODE>catalog.cfg</CODE>
directive <EM>OfflineDir</EM> -- <CODE>offline</CODE> in the catalog directory by default. The directory must exist. The source 
<FONT SIZE=-1>ASCII</FONT> files should be present in that directory, and the 
<FONT SIZE=-1>DBM</FONT> files are created there. Existing files will be overwritten.


<P>
<PRE>    offline -c catalog [-d offline_dir]
</PRE>
<P>

code: 25.06
section: ADMINISTERING_MINIVEND
type: item
title: Updating Individual Records

<A NAME="Updating_Individual_Records">Updating Individual Records</A></H2>

If you have a very large 
<FONT SIZE=-1>DBM</FONT> database that takes a long time to build, you may
want to use the <CODE>bin/update</CODE> script to change just one field in a record, or to add from a corrections
list.

<P>
The following updates the products database <CODE>price</CODE> field for item 19-202 with the new value 25.00

<P>
<PRE>    update -c catalog -f price 25.00
</PRE>
<P>
More than one field can be updated on a single command line

<P>
<PRE>    update -c catalog -f price -f comment 25.00 &quot;That pitchfork couple&quot;
</PRE>
<P>
The following takes input from <A HREF="#item_file">file</A>, which must be
<STRONG>formatted exactly like the original database</STRONG>
and adds/corrects any records contained therein.

<P>
<PRE>    update -c catalog -i file
</PRE>
<P>
Invoke the command without any arguments for a usage message describing the
options.

<P>

code: 26.00
section: ADMINISTERING_MINIVEND
type: overview
title: ADMINISTERING MINIVEND

<A NAME="ADMINISTERING_MINIVEND">ADMINISTERING MINIVEND</A></H1>

Many utilities are supplied in the VendRoot/bin directory:

<P>
<PRE>  start        Symbolic link to start_unix or start_inet
  stop         Stops the server
  start_inet   Starts the server in INET mode
  start_unix   Starts the server in UNIX mode
  restart      Symbolic link to restart_unix or restart_inet
  restart_inet Re-starts the server in INET mode
  restart_unix Re-starts the server in UNIX mode
  dump         Dumps the session file for a particular catalog
  expire       Expires sessions for a particular catalog
  expireall    Expires all catalogs
  reconfig     Runtime reconfiguration of catalogs
  check        Template script to monitor server health
  checkstat.sh Template script to monitor server upness
  htpasswd.pl  Program to create .htpasswd files
  offline      Does offline build of the database(s)
  update       Does in-place update of the database(s)
  makecat      Make catalog
  localize     Help build a locale file from MiniVend pages
</PRE>
<P>
Some thought should be given to where the databases, error logs, and session files should be located, especially on an 
<FONT SIZE=-1>ISP</FONT> that might have multiple users sharing a MiniVend server. In particular, you might put all of the session files and logs in a directory that is not writable by the user -- if the directory or file is corrupted the catalog may go down.


<P>
To test the format of user catalog configuration files before restarting
the server, you can do (from VendRoot):

<P>
<PRE>    minivend -test
</PRE>
<P>
That will check all configuration files for syntax errors, which might
otherwise prevent a catalog from coming up. Once a catalog configures
properly, user reconfiguration will not crash it, just cause an error. But
it must come up when the server is started.

<P>

code: 27.00
section: DEBUGGING
type: overview
title: DEBUGGING

<A NAME="DEBUGGING">DEBUGGING</A></H1>

As of version 3.06, MiniVend allows you to see debugging information based
on the state of several controls.

<P>
MiniVend comes with debugging output disabled by default -- this is for
speed and code compactness. To enable debugging, change directory to the
MiniVend root (the software directory) and run:

<P>
<PRE>    # Must change to MiniVend software directory first!
    bin/ifdef -y -t DEBUG
</PRE>
<P>
This only works for MiniVend 3.06 and above. Earlier MiniVend versions have only a crude debug available with the 
<FONT SIZE=-1>-D</FONT> startup options.


<P>
To disable, use the command

<P>
<PRE>    # Must change to MiniVend software directory first!
    bin/ifdef -n -t DEBUG
</PRE>
<P>
Note that some warnings may be generated by the debugging itself, typically
``use of uninitialized variable'' warnings generated by undefined debug
references. You can safely ignore these if they occur pointing to lines
where the logDebug routine is called.

<P>
The controls are accessed in one of several ways.

<P><DL>
<DT><STRONG><A NAME="item__Dnnnn">-Dnnnn</A></STRONG><DD>

If you start MiniVend with the 
<FONT SIZE=-1>-D</FONT> option, it will run in the foreground and extensive
debug information will be output on the terminal that started the program.
If <CODE>nnnn</CODE>, a numeric option set, is present, that debug level will be set. The
default level is 4097, running in the foreground with only a few debug
outputs (normal mode) present. If you want to run in the foreground with
maximum information, use the level 4351.

<P>

<FONT SIZE=-1>IMPORTANT</FONT> 
<FONT SIZE=-1>NOTE:</FONT> This may affect some program operations. If something new fails in debug mode, try it again in normal background server mode. In particular, changes to the configuration made on the fly in the page will stick since the process is not forked.


<P><DT><STRONG>[tag flag debug] level1 level2 ... [/tag]</STRONG><DD>

This sets the debug level in the page. If you want to see what is happening
with a particular type of operation, the debug levels are:

<P>
<PRE>    DESCRIPTION           NUM  TEXT    DISABLE
    -----------           ---  -----   -----
    Disable all debug       0  off     N/A
    Normal operations       1  normal  !normal
    Tag interpretation      2  tag     !tag
    Database operations     4  data    !data
    Configuration info      8  config  !config
    Search operations      16  search  !search
    Session operations     32  session !session
    Server operations      64  server  !server
    Cache/benchmark       128  cache   !cache
    Show calling package  512  caller  !caller
    Show in page comment 1024  comment !comment
    Place in mvdebug     2048  N/A     N/A
    Run in foreground    4096  N/A     N/A
 
    Verbose in HTML      2047
    Verbose foreground   5119
</PRE>
<P>

<FONT SIZE=-1>NOTE:</FONT> The text levels only operate in conjunction with <CODE>[tag flag debug]</CODE>.

<P>
If you want to output the debug information embedded in an 
<FONT SIZE=-1>HTML</FONT> comment at the end of the page you get from your
browser, add level 1024. This overrides the output to mvdebug temporarily,
or to foreground output indefinitely, if those are enabled.

<P>
Use this to set verbose but no tag details, with output to 
<FONT SIZE=-1>HTML:</FONT>

<P>
<PRE>    [tag flag debug]comment verbose !tag[/tag]
</PRE>
<P>
Use this to look at only database operations, with output to 
<FONT SIZE=-1>HTML:</FONT>

<P>
<PRE>    [tag flag debug]comment !verbose data[/tag]
</PRE>
<P><DT><STRONG><A NAME="item_MINIVEND_DEBUG">MINIVEND_DEBUG environment variable</A></STRONG><DD>

Prior to starting the server, you can determine the level to run at by
setting the environment variable <A HREF="#item_MINIVEND_DEBUG">MINIVEND_DEBUG</A>. It is an ANDed set of debug levels yielding a decimal number. For example, to show debug information in 
<FONT SIZE=-1>HTML</FONT> comments with maximum verbosity, use one of the following command prior to starting the MiniVend daemons:


<P>
<PRE>   # UNIX C-shell types (tcsh, csh, etc.)
   setenv MINIVEND_DEBUG 1279
</PRE>
<P>
<PRE>   # UNIX Bourne-shell types (bash, sh, ksh, etc.)
   MINIVEND_DEBUG=1279
   export MINIVEND_DEBUG
</PRE>
<P>
<PRE>   # Windows/DOS command box
   set MINIVEND_DEBUG=1279
</PRE>
<P><DT><STRONG><A NAME="item_DebugMode">DebugMode directive</A></STRONG><DD>

The debug mode can be set both globally (in <CODE>minivend.cfg</CODE>) and for each catalog (in <CODE>catalog.cfg</CODE>) with the DebugMode directive, with levels as above.

<P><DT><STRONG><A NAME="item_DisplayErrors">DisplayErrors</A></STRONG><DD>

To enable display of fatal errors (those things that would normally cause a
500 server error) then the DisplayErrors directive must be set to <CODE>Yes</CODE>
in <STRONG>both</STRONG>  <CODE>minivend.cfg</CODE> and <CODE>catalog.cfg</CODE>. Debug information will be included if available and level 1024 is set.

<P>
The debug mode of 8192 will enable DisplayErrors for every catalog.

<P>


code: 27.02
section: MANUAL_INSTALLATION_OF_CATALOGS
type: item
title: Needed Directories

<A NAME="Needed_Directories">Needed Directories</A></H2>

The MiniVend program, and its supporting libraries, should all go into one
directory as installed by the installation program.

<P>
User catalog pages, user databases, and user configuration files should all go into their private directories. Because the catalog pages are served through the MiniVend cgi-bin program and contain nonstandard elements, they should not be put into a public 
<FONT SIZE=-1>WWW</FONT> directory, nor do they need to have world-readable file permissions.


<P>
<STRONG>IMPORTANT NOTE</STRONG>: As of MiniVend 2.0, since catalogs are all run under one server,
permissions are complex and very important. Please let the MiniVend
configuration program do the work!

<P>
You will want a public 
<FONT SIZE=-1>WWW</FONT> directory for in-line image graphic files. MiniVend does not serve the images, only the 
<FONT SIZE=-1>HTML</FONT> tags calling them. 
<FONT SIZE=-1>A</FONT> useful convention is to place all buttonbars, backgrounds, and icons in the /images directory, with the catalog items perhaps located in the /images/catalog directory. It is up to you, but remember that you must use an
 <EM>absolute path</EM> -- relative paths will not do. MiniVend 2.0 supports the <EM>ImageDir</EM> directive, which places that as the absolute path in front of all relative 
<FONT SIZE=-1>IMG</FONT> and 
<FONT SIZE=-1>INPUT</FONT> 
<FONT SIZE=-1>SRC</FONT> specifications.


<P>
You will need a cgi-bin directory in which to put the vlink or tlink
program.

<P>

code: 27.03
section: MANUAL_INSTALLATION_OF_CATALOGS
type: item
title: Compiling VLINK and TLINK

<A NAME="Compiling_VLINK_and_TLINK">Compiling VLINK and TLINK</A></H2>

Change directories to the <CODE>src</CODE> directory, then run the 
<FONT SIZE=-1>GNU</FONT> configure script:

<P>
<PRE>    cd src
    ./configure
</PRE>
<P>
You will see some output as the configure script checks your system. Then
compile the programs:

<P>
<PRE>    cc vlink.c -o vlink
    cc tlink.c -o tlink
</PRE>
<P>
You can ensure your 
<FONT SIZE=-1>C</FONT> compiler will be invoked properly with this little
ditty:

<P>
<PRE>    perl -e 'do &quot;syscfg&quot;; system(&quot;$CC $LIBS $CFLAGS $DEFS -o tlink tlink.c&quot;);'
    perl -e 'do &quot;syscfg&quot;; system(&quot;$CC $LIBS $CFLAGS $DEFS -o vlink vlink.c&quot;);'
</PRE>
<P>
On some systems you can make the executable smaller with the strip program.
But don't worry about it if strip is not on your system.

<P>
<PRE>    strip vlink
    strip tlink
</PRE>
<P>
If you want MiniVend to run under a different user account than your own,
make that user the owner of vlink. (You probably need to be root to do
this). Do not make vlink owned by root, because making vlink setuid root is
an huge and unnecessary security risk. It should also <STRONG>not</STRONG>
normally run as the default 
<FONT SIZE=-1>WWW</FONT> user (often <CODE>nobody</CODE> or <CODE>http</CODE>)).

<P>
<PRE>    chown minivend vlink
</PRE>
<P>
Move the vlink executable to your cgi-bin directory:

<P>
<PRE>    mv vlink /the/cgi-bin/directory
</PRE>
<P>
Make vlink setuid:

<P>
<PRE>    chmod u+s /the/cgi-bin/directory/vlink
</PRE>
<P>
Most systems unset the 
<FONT SIZE=-1>SUID</FONT> bit when moving the file, so you should change it
after moving.

<P>
The 
<FONT SIZE=-1>SCRIPT_NAME</FONT> as produced by the 
<FONT SIZE=-1>HTTP</FONT> server must match the name of the program. (As usual, you should let the makecat program do the work.)


<P>

code: 27.03
section: MANUAL_INSTALLATION_OF_CATALOGS
type: item
title: The Demo Systems

<A NAME="The_Demo_Systems">The Demo Systems</A></H2>

Sample catalog pages are in the directory simple/. If you would like to use them as a starting point for your own catalog, you can either have the configure script install the demo for you, or you can copy the files into the MiniVend directory and your 
<FONT SIZE=-1>HTML</FONT> directory.


<P>
To install the demo:

<P>
<PRE> bin/makecat simple
</PRE>
<P>
Answer the prompts supplied by the program. Note that there are two types of paths asked for, 
<FONT SIZE=-1>URL</FONT> paths like the /cgi-bin inside <A HREF="http://www.machine.com/cgi-bin/simple,">http://www.machine.com/cgi-bin/simple,</A> and file paths that are complete fully-qualified file path names.


<P>

code: 27.04
section: MANUAL_INSTALLATION_OF_CATALOGS
type: item
title: Setting up VLINK and TLINK

<A NAME="Setting_up_VLINK_and_TLINK">Setting up VLINK and TLINK</A></H2>

The <CODE>vlink</CODE> and <CODE>tlink</CODE> programs, compiled from <CODE>vlink.c</CODE> and
<CODE>tlink.c</CODE>, are small 
<FONT SIZE=-1>C</FONT> programs which contact and interface to a running
MiniVend daemon. The vlink executable is normally made setuid to the user
account which runs MiniVend, so that the UNIX-domain socket file can be set
to secure permissions (user read-write only). It is normally not necessary
for the user to do anything -- they will be compiled by the configuration
program. If the MiniVend daemon is not running, either will display a
message indicating that the server is not available. The following defines
in the produced <CODE>config.h</CODE> should be set:

<P><DL>
<DT><STRONG><A NAME="item_LINK_FILE">LINK_FILE</A></STRONG><DD>

Set this to the name of the socket file that will be used for
configuration, usually ``/usr/local/lib/minivend/etc/socket'' or the
``etc/socket'' under the directory you chose for the VendRoot.

<P><DT><STRONG><A NAME="item_LINK_HOST">LINK_HOST</A></STRONG><DD>

Set this to the 
<FONT SIZE=-1>IP</FONT> number of the host which should be contacted. The
default of 127.0.0.1 (the local machine) is probably best for most
installations.

<P><DT><STRONG><A NAME="item_LINK_PORT">LINK_PORT</A></STRONG><DD>

Set this to the 
<FONT SIZE=-1>TCP</FONT> port number that the MiniVend server will monitor. The default is 7786 (the 
<FONT SIZE=-1>ASCII</FONT> codes for 
<FONT SIZE=-1>'M'</FONT> and 
<FONT SIZE=-1>'V')</FONT> and does not normally need to be changed.


<P><DT><STRONG><A NAME="item_LINK_TIMEOUT">LINK_TIMEOUT</A></STRONG><DD>

Set this to the number of seconds vlink or tlink should wait before
announcing that the MiniVend server is not running. The default of 45 is
probably a reasonable value.

<P>


code: 28.00
section: ACKNOWLEDGEMENTS
type: overview
title: ACKNOWLEDGEMENTS

<A NAME="ACKNOWLEDGEMENTS">ACKNOWLEDGEMENTS</A></H1>

Original author of Vend was Andrew Wilcox. MiniVend was based on Vend 0.2,
with portions from Vend 0.3.

<P>
Contributions to MiniVend have been made by:

<P>
<PRE>    Andreas Koenig     Heinz Wittenbecher
    Birgitt Funk       Jochen Wiedmann
    Bob Jordan         Larry Leszczynski
    Brian Bullen       Marc Austin
    Bruce Albrecht     Michael McCune
    Don Grodecki       Tim Baverstock
    Frank Bonita       William Dan Terry
    Gunnar Hellekson   many others
</PRE>
<P>
and, of course, the entire Perl team without whom MiniVend could not exist.

<P></DL>
</BODY>

</HTML>


code: 28.00
section: MANUAL_INSTALLATION_OF_CATALOGS
type: overview
title: MANUAL INSTALLATION OF CATALOGS

<A NAME="MANUAL_INSTALLATION_OF_CATALOGS">MANUAL INSTALLATION OF CATALOGS</A></H1>


<FONT SIZE=-1>A</FONT> MiniVend installation is complex, and requires quite a few distinct steps. That is why there is an interactive configuration script that is included with MiniVend -- it merely does automatically what is described below. It makes the process much easier, and will install the demo catalog. This configuration script has been tested on many 
<FONT SIZE=-1>UNIX</FONT> systems.


<P>
The installation program (makecat) can be used to install your own custom
catalog template. See the supplied demo template
<A HREF="#item_simple">simple</A> for examples.

<P>
There is also, starting with MiniVend 3.11, a ``wizard'' interface that operates completely through 
<FONT SIZE=-1>HTML.</FONT>


<P>

code: 29.00
section: AUTHOR
type: overview
title: AUTHOR

<A NAME="AUTHOR">AUTHOR</A></H1>

Mike Heins, <EM>mike@minivend.com</EM>.

<P>

