NAME

MiniVend - WWW Catalog Ordering

VERSION

This document describes MiniVend 1.03, based on Andrew Wilcox's original Vend, Version 0.2.

DESCRIPTION

MiniVend allows customers to select items to buy from catalog pages. The program tracks which products they have selected and the quantity desired. From the ordering page they may complete the ordering process by entering their name and address, or return to browsing and select more items.

MiniVend plugs into a system with an SSL (Secure Sockets Layer) server, allowing encrypted transmission of sensitive customer data. This capability makes the entry of credit card numbers practical and secure.

With V1.03, multiple servers can now be started to serve the same catalog, and searches are forked. This ensures fast response while searching the catalog.

You can jump to any of the following sections:

"OVERVIEW OF MINIVEND"

- "How MiniVend Manages Sessions"

- "Where to Download MiniVend"

- Perl

- "Setup for the CERN HTTPD Server"

- "Setup for the NCSA and Apache Servers"

"QUICK START"

- "If something goes wrong"

"MANUAL INSTALLATION"

- "Needed Directories"

- "Unpacking the Distribution"

- "The Demo Systems"

- "Testing Your CGI-BIN Directory"

- "Setting up SVEND"

- "Setting up VLINK"

- "Setting up minivend.pl"

"SETTING UP YOUR CATALOG"

- products.asc

- "Arbitrary Databases"

- "Catalog Pages"

- "MiniVend Conditional HTML"

- "On-the-fly Catalog Pages"

- "The Order Page"

- "The Search Engine"

- "The Search Page"

- "Customer Input Fields"

- "Special Fields"

- "Simple Order Report File"

- "Fully-configurable Order Reports"

- "Order Receipts"

- "Sales Tax"

- "Custom Shipping"

- "Tracking and Backend Order Entry"

- "Easy ASCII Tracking"

- "The Order Counter"

- "Order Security"

- "Using Frames"

- "Controlling Page Appearance"

"MINIVEND CONFIGURATION FILE"

- "Optional Configuration Directives"

- "Required Pages"

"ADMINISTERING MINIVEND"

- "Starting, Stopping, and Re-starting the Servers"

- "Checking Page Syntax"

- "Making the Product Database"

- "Expiring Sessions"

- "INDEX OF ITEMS"

AUTHORS

OVERVIEW OF MINIVEND

If you want to get started, just jump to "QUICK START" below. The following sections briefly describe how MiniVend works.

How MiniVend Manages Sessions

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.

MiniVend keeps track of who is ordering what by including in the URL a session id: a random string which is different for each customer browsing the catalog.

So that the session id can be included in URL's within catalog pages, every page in the catalog is served up by MiniVend running as a cgi-bin program. Here is an example of such a URL:

http://machine.company.com/cgi-bin/vlink/shirts?WehUkATn;;1

An explanation of each part:

machine.company.com

Internet address of server

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

Name of the program to run

shirts

Page of the catalog to display

WehUkATn;;1

The session id

As of Version 1.03, MiniVend now optionally supports Cookies, which allows interspersal of regular HTML references and MiniVend page references.

Catalog pages are written in regular HTML with extensions to support catalog ordering. Pages are delivered through the following steps:

  1.  The HTTPD server receives a request for a catalog page.

  2a. The server is already running as a daemon, and the request
      causes a small C program called vlink.  The vlink program
      communicates with the MiniVend program
      via a UNIX-domain socket. 

         -- OR --

  2b. The server runs svend as a cgi-bin program. svend is a small C
      program which is setuid to the account which owns the catalog
      files. svend executes the MiniVend Perl script minivend.pl.
      THIS IS MUCH SLOWER than 2a.

  3.  MiniVend reads the HTML source page from the catalog pages directory,
      and interprets the catalog ordering extensions 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 the template page flypage.html.

  4.  The page, which is now entirely in regular HTML, is delivered to
      the HTTPD server, which returns it to the browser.

Once the customer has finished, the completed order is emailed to the vendor.

Where to Download MiniVend

The MiniVend version described in this document is available from:

http://www.iac.net/~mikeh/download.html

If you are on a Solaris, Irix (SGI), or other UNIX which does not have native and complete flock() support, you must also obtain the File::Lock module at the same place that Perl is available from.

Perl

You will probably need Perl version 5.002 to run MiniVend 1.03. Many sites are still running lower Perl versions. In addition, on systems that do not have GDBM or DB_File installed, some of MiniVend's features (notably DBM order and page access tracking) will not be available. Large catalogs may be impossible to run due to memory limitations.

You can download a copy of Perl 5 from any CPAN (Comprehensive Perl Archive Network) site:

NORTH AMERICA

Florida 
   ftp://ftp.cis.ufl.edu/pub/perl/CPAN/ 
Illinois 
   ftp://uiarchive.cso.uiuc.edu/pub/lang/perl/CPAN/ 
Massachusetts 
   ftp://ftp.delphi.com/pub/mirrors/packages/perl/CPAN/ 
Oklahoma 
   ftp://ftp.uoknor.edu/mirrors/CPAN/ 
Texas 
   ftp://ftp.metronet.com/pub/perl/
   ftp://ftp.sedl.org/pub/mirrors/CPAN/ 
   ftp://ftp.sterling.com/programming/languages/perl/ 

EUROPE

Czech Republic
   ftp://sunsite.mff.cuni.cz/Languages/Perl/CPAN/
Finland 
   ftp://ftp.funet.fi/pub/languages/perl/CPAN/ 
France 
   ftp://ftp.ibp.fr/pub/perl/CPAN/ 
   ftp://ftp.pasteur.fr/pub/computing/unix/perl/CPAN/ 
Germany 
   ftp://ftp.leo.org/pub/comp/programming/languages/perl/CPAN/ 
   ftp://ftp.rz.ruhr-uni-bochum.de/pub/programming/languages/perl/CPAN/ 
Great Britain 
   ftp://ftp.demon.co.uk/pub/mirrors/perl/CPAN/ 
   ftp://unix.hensa.ac.uk/mirrors/perl-CPAN/
The Netherlands 
   ftp://ftp.cs.ruu.nl/pub/PERL/CPAN/ 
Poland
   ftp://ftp.pk.edu.pl/pub/lang/perl/CPAN/
Portugal 
   ftp://ftp.ci.uminho.pt/pub/lang/perl/ 
Slovenia
   ftp://ftp.arnes.si/software/perl/CPAN/
Sweden 
   ftp://ftp.sunet.se/pub/lang/perl/CPAN/ 
Switzerland 
   ftp://ftp.switch.ch/mirror/CPAN/ 

AUSTRALASIA

Australia 
   ftp://coombs.anu.edu.au/pub/perl/CPAN/
   ftp://ftp.mame.mu.oz.au/pub/perl/CPAN/
New Zealand 
   ftp://ftp.tekotago.ac.nz/pub/perl/CPAN/ 

ASIA

Japan 
   ftp://ftp.lab.kdd.co.jp/lang/perl/CPAN/ 
Taiwan 
   ftp://dongpo.math.ncu.edu.tw/perl/CPAN/ 

AFRICA

South Africa 
   ftp://ftp.is.co.za/programming/perl/CPAN/ 

Setup for the CERN HTTPD Server

MiniVend uses the user and machine name of the customer as an additional mechanism for distinguishing between users. Turn identity checking on in the HTTPD server with the IdentityCheck directive:

IdentityCheck  On

Unless changed by the UserId directive, the CERN httpd server will run programs as the user "nobody". To ensure that vlink or svend is only run as a cgi-bin program and not by other users on the system, svend will only run under this user account. If other programs on the system use the nobody account, you may want to change the UserId to an account which is only used by httpd.

UserId  hguest

You will also need rules to map URLs to your public HTML files and your cgi-bin directory. These may be already set up in the httpd configuration file. Here is an example:

Exec  /xyzcorp/cgi-bin/*  /home/xyzcorp/cgi-bin/*
Pass  /xyzcorp/*          /home/xyzcorp/WWW/*

The first line specifies that a URL such as "http://machine.company.com/cgi-bin/svend" will run the program svend located in the /home/xyzcorp/cgi-bin directory. The second line specifies that files in the /home/xyzcorp/WWW directory can be retrieved with a URL such as http://machine.com/xyzcorp/file.

The mapping described by Exec will always require two parts in the URL: one to specify the cgi-bin directory and another to specify the program to run. You can shorten the URL by specifying an additional mapping such as:

Map  /catalog/*  /xyzcorp/cgi-bin/svend/*

This will allow a URL such as "http://machine.com/catalog/shirts" to be used.

In the MiniVend configuration file, minivend.cfg, set the VendURL directive to the URL which runs svend in the cgi-bin directory.

VendURL  http://machine.company.com/catalog

Setup for the NCSA and Apache Servers

There is no special configuration required unless you plan on running the MAT administration program. Simply put vlink or svend in the cgi-bin directory (of course it must be script-aliased), and run the MiniVend program.

If the MAT program is to be installed in a protected CGI directory, you must:

1. Create the directory definition in the srm.conf file. This is what the entry should look like (if you are using the default NCSA/Apache installation directories):

ScriptAlias /prot-bin/   /usr/local/etc/httpd/prot-bin/

2. Actually make the directory if it doesn't exist:

mkdir /usr/local/etc/httpd/prot-bin

3. Add the following entry to the access.conf file:

<Directory /usr/local/etc/httpd/prot-bin>
    Options
    AuthUserFile /usr/local/etc/httpd/conf/.htpasswd
    AuthGroupFile /usr/local/etc/httpd/conf/.htgroup
    AuthName admin
    AuthType Basic
<Limit GET POST>
    require group admin
</Limit>
</Directory>

4. Create the password file with htpasswd or the like. For convenience, a Perl version of htpasswd (htpasswd.pl) may be included in your bin/ directory. Copy the password file to /usr/local/etc/httpd/conf/.htpasswd.

5. Create the /usr/local/etc/httpd/conf/.htgroup file with the user name(s) to use in the file:

admin:mike

6. Copy the mat executable to the protected bin directory.

7. Restart the HTTP server (send it a HUP signal), so it will re-read the configuration files.

8. Test by accessing the URL http://machine.company.com/prot-bin/mat -- you should be prompted for a password.

QUICK START

Before you begin, select the directory where you want to install MiniVend. You can unpack the tar file either there, or in another temporary directory -- the configure script handles either. The suggested directory is /usr/local/lib/minivend -- but really any directory will do. You must of course have write permission there; and you will eventually need to have write permission on your CGI-BIN and protected CGI-BIN directories.

Decompress and untar the distribution:

gzip -d mvend103.tar.gz
tar xfv mvend103.tar

If you have GNU tar, you can combine these steps:

tar xfvz mvend103.tar.gz

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

Run the configure script with:

./configure

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

perl configure.pl /usr/bin/perl

Replace the 'perl' and '/usr/bin/perl' with the proper paths to your Perl 5 binary.

The process should be self-explanatory. If you discover any problems, refer to the following section, "MANUAL INSTALLATION". Otherwise, MiniVend should be installed at the completion of the script. It is suggested that you install the demo as a starting point for your own catalog -- the configuration script will give you the opportunity to do so.

IMPORTANT NOTE: One point that is to be emphasized -- only your base html pages go in the document space of your http server. Any pages with MiniVend elements/tags go in the directory set by the PageDir directive (the default is VendRoot/pages). For the demos supplied with MiniVend, this means that only a few pages will be copied to your HTTP server's DocumentRoot, with the remainder of the pages staying in the directory defined as PageDir (sample or simple, depending on the demo selected).

If something goes wrong

First, check the FAQ and bug list at the official MiniVend web site for information:

http://www.iac.net/~mikeh/mvend.html

Second, double check that you have the following things:

1. The vlink program is SUID, or you have made appropriate changes in the ReadPermission and WritePermission directives.

2. That you have not made anything owned by root, and that you have not started the server as root.

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

If you have a problem you are not able to correct, you can send email to:

<mikeh@iac.net>

Please include your operating system name and version, your Perl version the DBM library in use, and a directory listing of the MiniVend directory (and its etc directory) after the attempt to run. This can be done by leaving a message at the MiniVend bug reporting station:

http://www.iac.net/~mikeh/bugreport.html

MiniVend is an ambitious and complex program, and is not presented as being easy to use, easy to install, or bug-free. The configuration script was 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 ISP. Determined and thoughtful users almost always make MiniVend work.

MANUAL INSTALLATION

NOTE: The manual installation procedure is not completely up to date. It is HIGHLY RECOMMENDED that you use the configure script.

The 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 some, but not all, UNIX systems. Please report problems to <mikeh@iac.net>.

Needed Directories

The MiniVend program, your catalog pages, and the products file should all go into a private directory. Because the catalog pages are served through the MiniVend cgi-bin program and contain nonstandard elements, they should not be put into a public WWW directory, nor do they need to have world-readable file permissions.

You will want a public WWW directory for in-line image graphic files. MiniVend does not serve the images, only the HTML tags calling them. A 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 absolute path -- relative paths will not do.

You will need a cgi-bin directory in which to put the svend program.

If using MAT, you will want a password-protected private cgi-bin directory. See the section Setting up the NCSA/Apache Server for details.

Unpacking the Distribution

Select a directory to use as your MiniVend base directory (referred to hereafter as VendRoot). Decompress and untar the distribution:

gzip -d mvend103.tar.gz
tar xfv mvend103.tar

If you have GNU tar, you can combine these steps:

tar xfvz mvend103.tar.gz

The Demo Systems

The products directory contains a sample product file and the file report in the main directory is the sample order report. Sample catalog pages are in the directories sample/ and 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 sample files into the MiniVend directory and your HTML directory, which for these examples is assumed to be /usr/local/etc/httpd/htdocs.

To install the full-featured demo:

cd /usr/minivend                   # wherever your vend directory is
mkdir pages                        # make if not already there
cp sample/*.html pages
mkdir /usr/local/etc/httpd/htdocs/sample  # or your document root
mkdir /usr/local/etc/httpd/htdocs/sample/images
cp sample/images/* /usr/local/etc/httpd/htdocs/sample/images
cp sample/special*.html /usr/local/etc/httpd/htdocs/sample
cp sample/index.html  /usr/local/etc/httpd/htdocs/sample
cp sample/intro.html  /usr/local/etc/httpd/htdocs/sample
cp sample/address.html /usr/local/etc/httpd/htdocs/sample

To install the simple demo:

cd /usr/minivend                   # wherever your vend directory is
mkdir pages                        # make if not already there
cp simple/*.html pages
mkdir /usr/local/etc/httpd/htdocs/sample  # or your document root
mkdir /usr/local/etc/httpd/htdocs/sample/images
cp sample/images/* /usr/local/etc/httpd/htdocs/sample/images
cp simple/index.html  /usr/local/etc/httpd/htdocs/sample

Testing Your CGI-BIN Directory

This is a good time to test your cgi-bin configuration and find out the numeric user-id which your HTTPD server runs cgi-bin programs under. Edit "src/testcgi" and change the first line to refer to your Perl version 5 (or higher) executable.

#!/usr/bin/perl

Copy "testcgi" into your cgi-bin directory, and make it executable.

cp src/testcgi /your/cgi-bin/directory
chmod a+rx /your/cgi-bin/directory/testcgi

Try running testcgi from your shell command line to make sure that everything is working.

/your/cgi-bin/directory/testcgi

testcgi should respond with the version of Perl that you are running and your numeric user id.

Now try running testcgi from your browser. Write down the numeric user id which you get there, as you will need it later for svend and mat.

Setting up SVEND

svend is a small C program which is setuid to the user account which can access the catalog data files. The following defines at the beginning of svend.c should be set:

CGIUSER

Set this to the numeric uid (user id) which HTTPD runs cgi-bin programs under. Typically this will be 'http', 'nobody' or 'guest'.

PERL

Set this to the location of the perl (version 5 or higher) executable.

VEND

Set to the location of minivend.pl, typically in the VendRoot directory.

Compile svend.c with your C compiler:

cc svend.c -o svend

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.

strip svend

If you want MiniVend to run under a different user account than your own, make that user the owner of svend. (You probably need to be root to do this). Do not make svend owned by root, because making svend setuid root is an unnecessary security risk.

chown vendacct svend

Make svend setuid:

chmod u+s svend

Move the svend executable to your cgi-bin directory:

mv svend /the/cgi-bin/directory

The vlink program, compiled from link.c, is a small C program which is setuid to the user account which can access the catalog data files, and contacts a running MiniVend daemon. If the MiniVend daemon, is not running, it will attempt to start it. The following defines at the beginning of link.c should be set:

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.

Set this to the number of seconds vlink should wait before announcing that the MiniVend server is not running. The default of 20 is probably a reasonable value.

NET_START

If you want the vlink program to start the server for you if it is not already running, set NET_START equal to "-netstart". If you set it to the default of "-notify", it will send email to the MailOrderTo address announcing that the MiniVend server is down. If you set it to anything else, it will just send an innocuous message that "we are probably doing development".

NOTE: If you are running with the CreditCards directive enabled, you will not be able to enter the password. The CreditCards directive is disabled by default if -netstart is used to start up MiniVend.

PERL

Set this to the location of the perl (version 5 or higher) executable.

VEND

Set to the location of minivend.pl, typically in the VendRoot directory.

Change directories to the src directory, then run the GNU configure script:

cd src
./configure

You will see some output as the configure script checks your system. Then compile the program:

cc link.c -o vlink

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.

strip vlink

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 unnecessary security risk.

chown vendacct vlink

Make vlink setuid:

chmod u+s vlink

Move the vlink executable to your cgi-bin directory:

mv svend /the/cgi-bin/directory

Some systems unset the SUID bit when moving the file -- re-set it if necessary.

Setting up minivend.pl

Edit minivend.pl and specify the root directory which contains the MiniVend distribution, along with the other needed paths:

$Config::VendRoot = '/usr/local/lib/minivend';
$Config::ConfDir = '/usr/local/lib/minivend/etc';
$Config::PERL = '/usr/bin/perl';
$Config::VEND = '/usr/local/lib/minivend/minivend.pl';

If you have the Des library and Perl Des module, uncomment the line:

use Des;

That will allow internal encryption of credit card numbers stored on disk.

SETTING UP YOUR CATALOG

MiniVend uses its own tags to implement catalog functions -- they are similar to normal HTML, but are in [square brackets]. They will be referred to as either tags or elements in this document. The next section describes how to set up the pages and the configuration directives to make your own catalog. The demo catalog is a good starting point -- in particular we suggest you pay attention to the order and search pages.

NOTE: If you are upgrading from MiniVend 1.01, you will have to add the following line to the beginning of your products.asc file:

code description price link

The words should be separated by one of the approved delimiting schemes (TAB, PIPE, or CSV, set with the Delimiter directive), and are case-sensitive. If you play with the case of the "description" or "price" field, you will have to appropriately set the PriceField and DescriptionField directives.

products.asc

Each product you are selling should be given a product code: a short code that identifies the product on the ordering page and in the catalog. You can use any combination of letters, digits, dashes, periods, pound signs, or underscores for the product code. The products.asc 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 'description' and 'price' (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.

Three delimiter schemes are provided as standard:

TAB     Fields separated by ^I characters

code    description             price   image
SH543   Men's fine cotton shirt 14.95   shirts.jpg


PIPE    Fields separated by | characters

code|description|price|image
SH543|Men's fine cotton shirt|14.95|shirts.jpg


CSV     Fields enclosed in quotes, separated by commas

"code", "description", "price", "image"
"SH543", "Men's fine cotton shirt", "14.95", "shirts.jpg"

The Delimiter directive sets the scheme, and should be set to one of those three values. TAB is the default scheme.

Field names are case-sensitive. Unless you have fields with the names "description" and "price" field, you will have to appropriately set the PriceField and DescriptionField directives to use the [item-price] and [item-description] tags.

The product code must be the first field in the line.

IMPORTANT NOTE: The items must be separated by a single delimiter character. The items are lined up for your reading convenience.

This version of MiniVend implements the database in either GDBM, DB_File, or in-memory format. If you use DBM, large catalogs can be used without using too much memory; or slowing down performance in static mode. The DBM files are built automatically at MiniVend startup from the products file -- if it has not changed they are not built. If the only DBM type on your system is NDBM, an in-memory product database will be used. Catalogs of more than, say, 5,000 items will use large amounts of memory.

IMPORTANT NOTE: The field names must be on the first line of the products.asc file. These field names must match exactly the field names of the [in_field] tags in your catalog pages, or the MiniVend server will not start. In addition, they can only contain the characters '-A-Za-z0-9_', with no whitespace, or they will not work properly.

When the products.asc file changes after import or edit, the DBM database is re-built upon the next server start.

Arbitrary Databases

MiniVend can manage an unlimited number of arbitrary databases, kept either in memory, or on disk if you don't have GDBM or DB_File. They are in the same format as the products file by default, but 6 addressable schemes are available:

Type 1      Default - same as products file (TAB, PIPE, or CSV)
Type 2      Each field on its own line, a blank line or lines
            separates the record
Type 3      Fields separated by a \n%%\n combination, records by
            \n%%%\n (where \n is a newline)
Type 4      CSV
Type 5      PIPE
Type 6      TAB

The databases are specified in Database directives, as:

Database    Arbitrary /usr/data/arbitrary.asc 4

That specifies a type 4 database, the ASCII version of which is located in the file /usr/data/arbitrary.asc (the DBM file will go there too, as /usr/data/arbitrary.db or arbitrary.gdbm), and the name it will be accessed under in MiniVend is "Arbitrary". The name is case sensitive. Fields are accessed with the [item_data name field] or [data name field key] elements.

Catalog Pages

Pages in the catalog are written in regular HTML with extensions to support catalog ordering. To distinguish them from regular HTML, these extended elements use square brackets instead of angular brackets.

NOTE: As of MiniVend 1.03, there are no real distinctions between order pages and other pages -- all may access the [item_list] tag.

The first page displayed in the catalog, if no argument is supplied to the vlink or svend cgi-bin program, is "catalog.html". This page will contain links to other catalog pages with the [page] element. Individual products can be ordered by the [order <item-code>] element, which brings up the order page "order.html". The order page contains input boxes for the customer to type in their name and address. Once the order has been sent the "confirmation.html" page is displayed.

If you use the vendpage utility, you will be able to write the pages in normal HTML, then convert them en masse to the Vend format. MiniVend tags (the ones in square brackets) can be passed in as HTML comments -- see vendpage for details.

Unless you are using the "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.

Inline images, on the other hand, are served in the normal fashion. You should include a regular <IMG SRC="URL"> element, where the URL refers to a graphic image.

As of MiniVend 1.03, all you need to do to have users with cookie-capable browsers retain session context is enable the Cookies directive. You can then intermix standard HREF and MiniVend page links without fear of losing the shopping basket.

NOTE: In the descriptions, parameters marked with an asterisk* are optional.

The following elements can be used in catalog pages:

Also allows specification of secure pages if the target ends with the string __secure (which will be stripped). If so specified, the page will be called with SecureURL instead of VendURL.

[areatarget pg frame] Inserts a Vend URL in a format to provide a targeted reference for a client-side imagemap. You set up the <AREA> tag with:
<AREA COORDS="220,0,270,20" HREF="[areatarget page frame]">

If frames are enabled, this will expand to:

<AREA COORDS="220,0,270,20"
   HREF="http://machine.company.com/vlink/page?ErTxVV8l;;38" TARGET="frame">

If frames are not enabled, this will expand to:

<AREA COORDS="220,0,270,20"
   HREF="http://machine.company.com/vlink/page?ErTxVV8l;;38">
[area pg] Like the areatarget element, except it will never yield a frame target.
[/page], [/pagetarget] Expands into </a>. Used with the page or pagetarget elements, such as: [page shirts]Our shirt collection[/page] or [pagetarget pants main] Our pants collection[/pagetarget]. They are syntactically the same, so you can use either to terminate an anchor -- the two different ones are provided for consistency.
[frames_on] Turns on the frames processing option, which is disabled by default. The proper way to use this is to put it ONLY in a page which is loaded by frame-based browsers, as part of the initial frame load. It is persistent for the entire session, or until counteracted with a [frames_off] tag.
[frames_off] Turns off the frames processing option. This can be used to disable frames, perhaps as a clickable option for users. It is persistent for the entire session, or until counteracted with a [frames_on] tag.
[finish_order page*] This element is used to give the customer, while browsing, a way to go to the order page (or optional checkout page) after they have ordered something. If they haven't ordered anything yet [finish_order] does not appear at all on the displayed page. If they have ordered an item, the element will expand into something like:
<a href="http://machine.company.com/cgi-bin/vlink/order;WehUkATn;;1">
Finish Incomplete Order</a>

If the optional page is supplied, that will be the order page used to finish the order.

[/order] Expands into </a>. Used with the order element, such as: Buy a [order TK112]Toaster[/order] today.
[price code] Expands into the price of the product identified by code as found in the products database.
[description code] Expands into the description of code as found in the products database.
[accessories code] Expands into the value of the accessories database entry for the product identified by code as found in the products database.
[field name code] Expands into the value of the field name for the product identified by code as found in the products database. IMPORTANT: If the field name is not a field in the database, the MiniVend server will stop with an error.
[body n] Selects from the predefined color schemes and/or backgrounds, and just becomes a <BODY> tag if none are defined. See "Controlling Page Appearance".
[buttonbar n] Selects from the predefined buttonbars, and is stripped if it doesn't exist. See "Controlling Page Appearance".
[random] Selects from the predefined random messages, and is stripped if none exist. See "Controlling Page Appearance".
[item_list] Places an iterative list of the items in the shopping cart. See "The Order Page" for a description.
[/item_list] Terminates the [item_list] tag.
[shipping_description] The text description of the shipping mode currently selected.
[row nn] Formats text in tables. Intended for use in reports or <PRE></PRE> HTML areas. The parameter nn gives the number of columns to use. Inside the row tag, [col param=value ...] tags may be used.
[/row] Terminates a [row nn] element.
[col width=nn wrap=yes|no gutter=n align=left|right|input spacing=n] Sets up a column for use in a [row]. This parameter can only be contained inside a [row nn] [/row] tag pair. Any number of columns (that fit within the size of the row) can be defined.

The parameters are:

width=nn        The column width, I<including the gutter>. Must be
                supplied, there is no default.  A shorthand method
                is to just supply the number as the I<first> 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<yes>.
    
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.
[/col] Terminates the column field.

MiniVend Conditional HTML

To build complex order forms and reports, MiniVend supplies some conditional capability with the [if ...] text [else] else-text [/else][/if] construct. It allows for testing for a condition within the Vend session, and if true, inserting text and/or HTML. If the condition is not true, no text (or the optional [else] text) will be inserted.

This facility cannot be considered a language, for constructs cannot be nested in a linear fashion, and operations cannot be performed (except as side effects to the [if] tag).

[if type field op* compare*] Allows conditional building of HTML based on the setting of various MiniVend session and database values. Accessible areas are:
session     The MiniVend session variables. Of particular interest
            are I<login>, I<frames>, I<secure>, and I<browser>.

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

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

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

accessory   The accessories database.

shipping    The shipping database.

salestax    The salestax database.

The field term is the specifier for that area. For example, [if session frames] would return true if the 'frames' session parameter was set.

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:

[if session frames]
    [buttonbar 1]
[else]
    [buttonbar 2]
[/else]
[/if]

Another example might be the when search matches are displayed. If you use the string '[value mv_match_count] titles found', it will display a plural for only one match. Use:

[if value mv_match_count != 1]
    [value mv_match_count] matches found.
[else]
[/else]
    Only one match was found.
[/if]

The op term is the compare operation to be used. Compare operations are as in Perl:

==  numeric equivalence
eq  string equivalence
>   numeric greater-than
gt  string greater-than
<   numeric less-than
lt  string less-than
!=  numeric non-equivalence
ne  string equivalence

Any simple perl test can be used, including some limited regex matching (no whitespace or conditionals can be contained in the comparison string). Discussion of this is beyond the scope of this document.

[else] text [/else] The optional else-text for an if or if_field conditional.
[/if] Terminates an if conditional.
[set variable]value[/set]

Sets a scratchpad variable to value. One way this is used is to save pages that a customer has seen -- perhaps for a rotating message. A rotating message implementation is shown in the sample page flypage.html.

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.

[data area field key]

Returns the value of the field in any of the arbitrary databases, or from the variable namespaces. Databases will hide variables, so don't name a database "session", "scratch", or any of the other reserved names! Case is sensitive, so in a pinch you could call the database "Session", but it would be better not to.

On-the-fly Catalog Pages

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 flypage.html, which is used as a template for building the page. If [item_field fieldname], [item_price], (etc.) elements are used on the page, quite complex and information-packed pages can be built. The [if_field fieldname] HTML [/if_field] pair can be used to only insert HTML if there is a non-blank value in a particular field.

The Order Page

The order page(s) are where the items are tracked and adjusted by the customer. It is possible, beginning with MiniVend 1.03, to have an unlimited number of order pages. This allows a basket/checkout type of ordering scheme, with custom order pages for items which have many accessories.

The Accessories database is a place to keep conditional accessory items for display on the order page (or anywhere else, for that matter). This allows you to place additional conditional items on the order page, perhaps checkboxes or a drop-down menu to select a color or style. Or you can have whole conditional trees to automatically configure a product to a customer's needs.

The structure of the Accessories database is a simple key-value pair -- if you have more complex accessory setups you can define one of the "Arbitrary Databases" and use that.

The following elements are used on the order page:

[value field] Expands into the current value of the customer input field named by field. See the section on input fields for more information.
[nitems] Expands into the total number of items ordered so far.
[subtotal] Expands into the subtotal cost, exclusive of sales tax, of all the items ordered so far.
[salestax] 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 whatever the default is. See Sales Tax for more information.
[total_cost] Expands into the total cost of all the items ordered so far, including sales tax (if any).

Within any order page, the [item_list] element shows a list of all the items ordered by the customer so far. It works by repeating the source between [item_list] and [/item_list] once for each item ordered. Between the item_list markers the following elements will return information for the current item:

[if_field fieldname] If the database field fieldname is non-blank, the following text up to the [/if_field] tag is substituted. This can be used to substitute IMG or other tags only if the corresponding source item is present.
[/if_field] Terminates an [if_field fieldname] element.
[item_code] Evaluates to the product code for the current item.
[item_data database fieldname] Evaluates to the field name fieldname in the arbitrary database table database, for the current item.
[item_description] Evaluates to the product description (from the products file) for the current item.
[item_field fieldname] Evaluates to the field name fieldname in the database, for the current item.
[item_accessories] Evaluates to the value of the Accessories database entry for the item.
[item_increment] Evaluates to the number of the item in the match list. Used for numbering search matches or order items in the list.
[item_price] Evaluates to the price (from the products file) of the current item.
[item_quantity] Evaluates to the subtotal (quantity * price) for the current item. Quantity price breaks are taken into account.
[item_quantity] Evaluates to the quantity ordered for the current item.
[quantity_name] Evaluates to the name to give an input box in which the customer can enter the quantity to order.

The Search Engine

MiniVend implements a search engine which will search the product database (or any other file) for items based on customer input. It uses the (example) nf_sel.html, nf_search.html, fr_comb.html, fr_help.html, and search.html files in the pages directory, and has some of its own special tags and variables.

Two search engine interfaces are provided, and three types of searching are available. The default is a text-based search of the products.asc file. A 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 Glimpse.

The default, a text based search, simply sequentially scans the lines in the target file. It returns the first field (delineated by the standard Delimiter), for every line matching the search specification.

A number of variables can be set on search forms to determine which search will be used, and what fields in the database it will search. Here is a simple search form:

<FORM ACTION="[process-search]" METHOD=POST>
<INPUT TYPE="text" SIZE="30" NAME="mv_searchspec">
<INPUT TYPE="submit" NAME="mv_todo" VALUE="Search">
</FORM>

When the "Search" submit button is pressed (or <ENTER> is pressed) MiniVend will search the products.asc file for the string entered into the text field mv_searchspec, and return the product code pertaining to that line.

The same search for a fixed string, say "shirt", could be performed with the use of a hot link, using the special scan URL:

[page scan/se=search]See our shirt collection![/page]

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:

<INPUT TYPE="hidden" NAME="mv_search_field" VALUE="description">

If you want to let the user decide on the search parameters, you can use checkboxes or radiobox fields to set the fields:

Search by author
   <INPUT TYPE="checkbox" NAME="mv_search_field" VALUE="author">
Search by title
    <INPUT TYPE="checkbox" NAME="mv_search_field" VALUE="title">

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).

To use the Glimpse search, you must build the Glimpse index based on files in your ProductDir, or wherever the files to be searched will be located. If you installed MiniVend in the default /usr/local/lib/minivend, the command line to build the index for the products file would be:

glimpseindex -b -H /usr/local/lib/minivend/products products.asc

There are several ways to improve search speed for large catalogs.

One method that works well for large products.asc files is to split the products.asc file into small index files (in the example, 100 lines) with the split(1) UNIX command, then index it with glimpse:

split -100 products.asc index.asc.
glimpseindex -H /usr/local/lib/minivend/products index.asc.*

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.

If the Glimpse executable is not found at MiniVend startup, the Glimpse search will be disabled and the regular text-based search used instead.

Fast binary searching 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 mv_dict_look, mv_dict_end, mv_dict_limit, mv_dict_fold, and mv_dict_order variables.

See the documentation for Vend::Search for more information. (From the MiniVend root directory, you can see it by using "perldoc Vend::Search".)

The sample nf_srch.html, nf_sel.html and fr_comb.html 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. The special form variables are:

mv_base_directory

In the text search, set to the directory to base file searches from. File names without leading / characters will be based from there. In the Glimpse search, passed to Glimpse with the -H option, and Glimpse will look for its indices there. Default is ProductDir.

mv_case

If this item is set to yes, the search will return items without regard to upper or lower case. This is the default -- set to yes if case should be matched. Implement with a checkbox <INPUT TYPE=CHECKBOX> field.

mv_coordinate

If this item is set to yes, and the number of search fields equals the number of search specs, the search will return only items that match field to spec.

mv_dict_fold

Make dictionary matching case-insensitive. Ignored without mv_dict_look. NOTE: This is the reverse sense from mv_case.

mv_dict_end

Set to the string to end matching at in a dictionary-based search. If the string at the beginning of a line lexically exceeds this value, matching will stop. Ignored without mv_dict_look.

mv_dict_limit

Automatically set the limiting string (mv_dict_end) to be one character greater than the mv_dict_look variable, at the character position specified. A value of 1, for instance, will set the limiting string to "fprsythe" if the value of mv_dict_look is "forsythe". A 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.

The order of this and the mv_dict_end variable is significant -- each will overwrite the other.

mv_dict_look

Set to the string 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.

mv_dict_order

Make dictionary matching follow dictionary order, where only word characters and whitespace matter. Ignored without mv_dict_look.

mv_doit

This must be set to 'search' to make this a search page.

mv_exact_match

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.

mv_matchlimit

The page size for matches that are returned. If more matches than mv_matchlimit are found, the search paging mechanism will be employed if the proper [more_list] is present. Can be implemented as a scrolling list (INPUT TYPE=SELECT) or radiobox (INPUT TYPE=RADIO) field.

mv_max_matches

The maximum number of records that will be returned in a search. Default is 2000.

mv_orsearch

If this item is set to yes, the search will return items matching any of the words in searchspec. The default is no.

mv_profile

Selects one of the pre-defined search specifications set by the SearchProfile directive. If the special variable within that file, mv_last, is defined, it will prevent the scanning of the form input for further search modifications. The values of mv_searchspec and mv_dict_look 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.

mv_return_fields

The fields that should be returned by the match. You should not normally set this, as the default of field 0 only works well with MiniVend's key-based database method of displaying search pages.

mv_search_field

The search field(s) to be searched, specified in one of two ways. If the field is in the products database, it can be specified by field name. If in an arbitrary database, it must be specified by row number (code cannot be specified).

If the number of instances matches the number of fields specified in the mv_searchspec variable, and mv_coordinate is set to true, each search field (in order specified on the form) will be matched with each search spec (again in that order).

mv_search_file

In the text search, set to the files 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 search all the files. One file name per instance.

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.

mv_search_match_count

Set by the search to indicate the total number of matches found.

mv_search_over_msg

The message that should be displayed if there is an overflow condition (max_matches is exceeded). Overrides the SearchOverMsg directive -- it is cleared by MiniVend if there is no overflow. Somewhat deprecated by match paging.

mv_search_page

The MiniVend-style name of the page that should display the search results. Overrides the FrameSearchPage directive, and the default value of 'search'.

mv_searchspec

The actual search string that is typed in by the customer. It is a text INPUT TYPE=TEXT 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.

The user can place quotes around words to specify that they match as a string. To enable this by default, use the mv_exact_match variable.

If mv_dict_look has a value, and mv_searchspec does not, then mv_searchspec will be set to the value of mv_dict_look.

If the number of instances matches the number of fields specified in the mv_search_field variable, and mv_coordinate is set to true, each search field (in order specified on the form) will be matched with each search spec (again in that order).

mv_searchtype

If set to glimpse, selects the Glimpse search (if Glimpse is defined). If set to text, selects the text-based search. Defaults to text if Glimpse 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.

mv_spelling_errors

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.

mv_substring_match

If mv_substring_match is set to yes, matches on substrings as well as whole words. You would typically want to set this for dictionary-based searches.

The sample search page also has a link to a help file (pages/help.html) which has rudimentary end-user help for the search engine.

The Search Page

Once a search has been done, there need be a way of presenting the output. By default, the special page search.html is used -- but any number of search pages can be specified by passing the value in the search form, specified in the variable mv_search_page.

On the search page, some special MiniVend tags are used to format the otherwise standard HTML. 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 [item-code] tag is set to whatever the first field (separated by whitespace) is, at least when the default of yes is in the UseCode directive.

NOTE: The special item tags (item-price, item-data, item-accessory, etc.) still refer to fields in the product database. To access arbitrary databases, you will need to use the idiom [data database field [item-code]].

[search_list]

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.

In particular, all of the item tags described under order page are active. The most useful one might be [item_link], which if properly used, can allow the user to search the catalog for an item, then click a link to go to detailed catalog page for the item. See the sample search.html page for an example.

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.

[/search_list]

Ends the search list.

[matches]

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 [more_list] and [/more_list] element pair.

[more_list]

Starts the section of the search page which only is output if there are more matches than specified in mv_matchlimit. If there are less matches than the number in mv_matchlimit, all text/html between the [more_list] and [/more_list] elements is stripped.

Use in conjunction with the [more] element to place pointers to additional pages of matches.

[/more_list]

Companion to [more_list].

[more]

Inserts a series of hyperlinks that will call up the next matches in a series. They look like this:

Previous 1 2 3 4 5 6 Next

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 Next or Previous page, that link will not be shown.

See the fr_resul.html or search.html files for examples. Make sure you insert this item between a [more_list] and [/more_list] element pair.

[item_link code] Expands into a hyperlink which will jump the user to a page under the ItemLinkDir (default is the pages directory), with anchor text as set in ItemLinkValue (default is "More Details"). If the page is not present, then flypage.html will be used to build a page from the entry in the database. If that doesn't work (perhaps due to a missing flypage.html) then the error page notfound.html will be displayed. Only active in the search list.
[process_search] Calls the search with the proper URL, including MiniVend session tags. Used as the ACTION value for the search form.
[process_target frame] Calls the search with the proper URL, including MiniVend session tags. Used as the ACTION 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).

On the order (or shopping basket) page, by default order.html, you will have a number of input fields allowing 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:

<input type="text" name="town" value="[value town]" size=30>

Choose a name for this input field such as "email" for an email address. Set the name attribute to the name you have chosen.

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 [value] element, which returns the last value of an input field. Thus,

value="[value name]"

will evaluate to the name entered on the previous order screen, such as:

value="Jane Smith"

which will be displayed by the browser.

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.

Special Fields

MiniVend treats some form fields specially, to link to the search engine and provide more control over user presentation.

These special fields all begin with mv_, and include:

mv_background       Explained in Controlling Page Appearance
mv_base_directory   Explained in Search Engine
mv_bgcolor          Explained in Controlling Page Appearance
mv_case             Explained in Search Engine
mv_checkout         Explained in The Order Page
mv_coordinate       Explained in Search Engine
mv_credit_card*     Discussed in order security
mv_customcolors     Explained in Controlling Page Appearance
mv_dict_end         Explained in Search Engine
mv_dict_fold        Explained in Search Engine
mv_dict_limit       Explained in Search Engine
mv_dict_look        Explained in Search Engine
mv_dict_order       Explained in Search Engine
mv_doit             Common to all forms, sets default action
mv_exact_match      Explained in Search Engine
mv_helpon           Turns on the help feature if defined
mv_helpoff          Turns off the help feature if defined
mv_linkcolor        Explained in Controlling Page Appearance
mv_matchlimit       Explained in Search Engine
mv_max_matches      Explained in Search Engine
mv_nextpage         Sets next page user will go to after submission
mv_order_item       Explained in The Order Page
mv_order_number     Explained in The Order Page
mv_orderpage        Explained in The Order Page
mv_orsearch         Explained in Search Engine
mv_profile          Explained in Search Engine
mv_resetcolors      Explained in Controlling Page Appearance
mv_return_fields    Explained in Search Engine
mv_search_field     Explained in Search Engine
mv_search_file      Explained in Search Engine
mv_search_over_msg  Explained in Search Engine
mv_search_page      Explained in Search Engine
mv_searchspec       Explained in Search Engine
mv_searchtype       Explained in Search Engine
mv_shipmode         Explained in The Order Page
mv_spelling_errors  Explained in Search Engine
mv_substring_match  Explained in Search Engine
mv_textcolor        Explained in Controlling Page Appearance
mv_todo             Common to all forms, sets form action
mv_todo.map         Contains form imagemap
mv_todo.x           Set by form imagemap
mv_todo.y           Set by form imagemap
mv_vlinkcolor       Explained in Controlling Page Appearance

Simple Order Report File

The simple order report file, "report", defines the layout of the order report which gets mailed on the completion of the order. For example,

      Order Date: $date

            Name: $name
   Email address: $email

Shipping address: $addr
Town, State, Zip: $town, $state $zip
         Country: $country

Any input field from the order page can be included using the dollar sign notation.

To prevent a value from being included in the order report, just add it to the ReportIgnore configuration directive.

MiniVend defines some values for use in the search form -- they begin with 'mv_' and are automatically ignored.

Fully-configurable Order Reports

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.

You could if you wish include HTML in the file, which will be interpreted by many mailers, but you can choose to use standard ASCII format. An example report is provided in <report.html>.

Order Receipts

If you specify a legal MiniVend page name in the ReceiptPage directive, the user will be sent this page instead of the default "confirmation.html" 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.

Sales Tax

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 SalesTax is initialized with the name of a field (or fields) on the order form. Commonly, this is zipcode and/or state:

SalesTax    zip,state

This being done, MiniVend assumes the presence of a file salestax.asc, which contains a database with the percentages. Each line of salestax.asc should be a code (again, usually a five-digit zip or a two letter state) followed by a tab, then a percentage. Example:

default 0
45056   .0525
61821   .0725
61801   .075
IL      .0625
OH      .0525
WA      .08

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 SUBTOTAL 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 TaxShipping directive. It will add the percentage, then make that available with the [salestax] 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.

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 ASCII file format based on zip code.

If some items are not taxable, then you must set up a field in your database which indicates that. You then place the name of that field in the NonTaxableField directive. If the field for that item evaluates true on a yes-no basis (i.e. is set to 'yes', 'y', 1, or the like), sales tax will not be applied to the item. If it evaluates false, it will be taxed.

If your state taxes shipping, use the TaxShipping directive. Utah and Nevada are known to tax shipping -- there may be others.

Custom Shipping

MiniVend allows custom shipping charges to be added to an order based on the value of an entry in the database. To enable custom shipping, enter the field that will be calculated in the CustomShipping directive:

CustomShipping  weight

The shipping cost database is a tab-separated ASCII 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.

code        The unique identifier for that shipping method
description Text to describe the method, accessed with the
            I<[shipping_description]> element
criteria    Whether it is for weight, quantity, country, or whatever
            (information only, not used in program)
minimum     The low bound of quantity/weight this entry applies to
maximum     The high bound of quantity/weight this entry applies to
cost        The total cost (formula if begins with 'f', or multiplier,
            if begins with 'x')

The cost is calculated like this:

1. The base code is selected. If there is more than one entry per
code, numbers are appended.
2. The criterion field is found -- if it is quantity, then it
is in the quantity field of each item on the order form
3. The quantity is determined, and if the quantity falls
with in the minimum and maximum, the cost is then applied.
4. If the cost is fixed, it is simply added.  If the cost
field begins with an 'x', the cost is multiplied by the quantity.
5. If no match is found, the 'default' entry is used.

An example would be this (the columns are lined up for your reading convenience, the actual entries should have ONE tab between fields!):

default Slow Boat   quantity    1   99999999    3.00
upsg1   UPS Ground  quantity    1   5           7.00
upsg2   UPS Ground  quantity    6   10          10.00
upsg3   UPS Ground  quantity    11  99999999    x .95
upsb1   UPS Blue    quantity    1   5           12.00
upsb2   UPS Blue    quantity    6   10          17.00
upsb3   UPS Blue    quantity    11  99999999    x 1.60
upsr1   UPS Red     quantity    1   5           17.00
upsr2   UPS Red     quantity    6   10          22.00
upsr3   UPS Red     quantity    11  99999999    x 2.10

If the user selected UPS Blue (code UPSB), and the quantity on the order was 3, the cost of 12.00 from upsb1 would be applied. If the quantity were 7, the next entry from upsb2 would be selected, for a cost of 17.00. If the quantity were 15, upsb3 would be selected, and the quantity of 15 multiplied by 1.60, for a total cost of 24.00.

If a default shipping mode other than 'default' is desired, enter it into the DefaultShipping directive:

DefaultShipping     UPSG

This will make the <INPUT TYPE=RADIO NAME=mv_shipmode VALUE=upsg> entry on the order form checked by default when the user starts the order process.

Tracking and Backend Order Entry

MiniVend has a tracking option, enabled with the configuration directive Tracking. Entered orders and page popularity are tracked. The tracking database is also used to hold encrypted data such as credit card numbers, expiration dates, and the encrypted MiniVend password.

The Tracking directive must be a non-blank value to enable tracking. In addition, if the tracking database is not yet initialized, the Tracking directive is used to initialize the first order number to be placed in the tracking database. After that initialization, the value of the next order number is kept in the database (under the key mv_next_order) and incremented when an order is placed. The incrementation is alpha-numeric, so it is important to have leading zeros in any string value -- i.e., an initial value of Order00009 will be incremented to Order00010, while an initial value of Order9 will be incremented to Ordes0. Also, any non-alphanumeric characters will be stripped -- Order_00000 becomes Order00000.

The tracking is done by entering information in the DBM database tracking in the product directory (ProductDir). Orders are tracked under two keys, the actual key (started by the Tracking Directive) and a key that prepends the string "Backend" to the actual key. The entry in the actual key is a facsimile of the emailed order report -- the Backend key is the values selected in the BackendOrder directive, combined with the actual ordered item codes and quantities, separated by NUL characters (ASCII code 0).

To illustrate, take a MiniVend system that has tracking enabled with these two configuration directives in the minivend.cfg file:

Tracking        Order00001
BackendOrder    name,address,city,state,zip,account,mv_shipmode

When the user places an order for quantity 2 of item number P-133, the tracking database will have two keys/values added:

Key               Value
----------------  ----------------------------
Order00001        (The order report, filled in -- see "Order Report File")
BackendOrder00001 Joe J. User<NUL>123 Any St.<NUL>Main Street<NUL>OH<NUL>
                  12345<NUL>Acct#123<NUL>P-133<NUL>2

If the customer left a credit card number with the SSL account information form (see "Order Security"), the credit card number and its associated expiration date will be placed in two additional fields:

Key               Value
----------------  ----------------------------
CcOrder00001      (encrypted data)
ExpOrder00001     (encrypted data)

The scheme allows a history of orders to be kept (the Order00001 key) and a list of unentered orders (the BackendOrder00001 key, along with the CcOrder00001 and ExpOrder00001 keys). An external program can read the tracking database and submit the orders to an order-entry system, removing (or undefining) the BackendOrder, CcOrder, and ExpOrder keys when finished. An rudimentary example script which displays the tracking database is supplied as 'trackrpt' in the bin/ directory. This script could be easily modified to actually perform batch order entry.

Page popularity is simply tracked by storing a count of accesses, with the page name as the key. No additional information is stored. It is designed to give the catalog designer an idea of which features, pages, and menus are popular, and which are rarely used. Since individual page accesses are tracked, it might also give marketing or sales an idea of problems with product perception -- if an item were frequently looked at, but rarely bought, it might be appropriate to re-write the catalog page.

Easy ASCII Tracking

Instead of the DBM-based tracking, you can choose to track only orders and not pages with the AsciiBackend and AsciiTrack directives.

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.

If you set AsciiBackend to a legal file name (based in VendRoot unless it has a leading "/"), it will save the backend fields along with the item-code and quantity of items being ordered.

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.

The Order Counter

An order counter can be enabled if the OrderCounter 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.

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.

Order Security

MiniVend has several features that enable secure ordering via SSL (Secure Sockets Layer). Despite their mystique, SSL servers are actually quite easy to operate. The difference between the standard HTTP server and the SSL HTTPS server, from the standpoint of the user, is only in the encryption and the specification of the URL -- https: is used for the URL protocol specification instead of the usual http: designation.

IMPORTANT NOTE: 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 MD5 or PGP, of minivend.pl, minivend.cfg, and all modules included in minivend.pl (standard ones are Vend/Server.pm, Vend/Imagemap.pm, Vend/Http.pm, Vend/lock.pm, and possibly Des). Check them on a regular basis to ensure they have not been changed.

MiniVend uses the SecureURL directive to set the base URL for secure transactions, and the VendURL directive for normal non-secure transactions. Secure URLs can be enabled for forms through the [process_target action secure] element, pages through the [pagetarget page frame__secure] element, and access to the secure account information form is available through the [secure_order] element.

MiniVend incorporates additional security for credit card numbers. Any field on the order form which has credit_card in its name will not be written to disk unless it is encrypted. Either an external encryption program, such as crypt(1) or des(1), can be used, or for internal encryption, the Perl Des module can be used. The Des module can be defined at program configuration time, or can be inserted in the minivend.pl configuration section as the line:

use Des;

The Des module is available at the same sites as "Perl Version 5". It also requires a functional libdes library, which will be harder to obtain.

To accept credit_card fields, you need to define several things in minivend.cfg (or with MAT). First, the directive CreditCards needs to be set to yes. Also, Tracking needs to be enabled, to provide a place to store the credit card numbers as well as a place to store your access password. EncryptProgram also needs to be defined with at least some value. If using the internal Des support, the entries should look something like:

CreditCards      Yes
Tracking         Order00001
EncryptProgram   internal

If you wish to use an external encryption program, recognize that this is not nearly as secure as using the internal Des option, for the design of most encryption programs prevents secure transmission of the password. The password has to be sent on the command line, and though MiniVend tries to hide it, not all operating systems will prevent access to the password through the ps(1) command. If you decide this is acceptable, here is an example EncryptProgram definition that will work for many des(1) implementations:

EncryptProgram   /usr/bin/des -e -k %p < %f

The %p parameter indicates the location where the password will be placed in the command line, and %f is the placeholder for the input file name. Consult your des(1) manual page for details on how the command line should be constructed.

If your encryption program allows the password to be placed on the first line of the text to be encrypted, omit the %p specification. MiniVend will send the password, followed by a newline, before sending the text to be encrypted. This is much more secure than a command line password, but your encryption program may not allow this mode of operation.

If the CreditCards, EncryptProgram and Tracking directives are defined at program startup, MiniVend will prompt for a password before starting the server. This password is checked against a password previously stored in the tracking database (if it exists), otherwise MiniVend prompts for a second entry to verify a new password, which is then stored in the tracking database. Three tries can be made before MiniVend gives up.

If encryption is not enabled, MiniVend will silently overwrite any fields in the order form(s) with X characters. This prevents non-authorized startups from saving any sensitive information to disk.

Using Frames

MiniVend fully supports frames, the proposed extension to HTML 3.0. (Currently only Netscape 2.0 and above browsers support frames.) Frames significantly enhance the electronic catalog experience, since the user can maintain a context -- with a search frame, a product details frame, a table-of-contents frame, etc. The demo included with MiniVend is based on frames, though if you access it with a non-frame browser it will operate perfectly well.

Frames are accessed by adding a TARGET element to a HREF, naming the frame that the referenced URL should be placed in. MiniVend produces targets with the pagetarget and areatarget elements, which send target tags if frames are enabled (by a [frames_on] element. Any frame name can be used, including the special frames of _top, _blank, _parent, and _self.

As shown in the demo pages, the best way to accommodate both types of browsers is by having an index.html page that sets the beginning frame set. The <FRAMESET> and <FRAME> tags will be ignored by standard browsers, which will read the HTML between the <NOFRAMES> and </NOFRAMES> tags below.

The format of the first set of URLs passed to the frames is important - only ONE MiniVend link must be called. That sets the session ID for the user. If two URLs were called, MiniVend would assign two session IDs to the user, scrambling the context of their navigation. From this single access, all further references to MiniVend are made, though after the first access multiple frame targets can be referenced.

This first MiniVend page that is accessed (with a frame browser) should contain a [frames_on] element. It is the only page that need (or should) contain a [frames_on], which is persistent throughout the session. This page should never be seen by a non-frame browser.

Subsequent accesses to MiniVend URLs will now contain the proper session information, and as long as pagetarget or page elements are used to pass the URLs, context will be maintained.

The [pagetarget page frame] element is used to pass target tags in hyperlinks. The [areatarget page frame] element is used to pass target tags in imagemaps. The [frames_on] and [frames_off] elements enable and disable frame operation. The [framebase frame] element sets a base target for a page.

See the demo pages:

fr_greet.html   Starting frame for frames-based browsers - has [frames_on]
nf_greet.html   Turns off frames -- has [frames_off]
reframe.html    Re-enables frames after they have been turned off

Controlling Page Appearance

MiniVend provides centralized page color and imagemap control through use of the [body n] and [buttonbar n] elements. It also can place a random message from a series of messages with the [random] element, and embed help messages with the [help item] element.

The [body n] 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 BEGIN. Here is an example:

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

The above sequence (set in the minivend.cfg file, or through MAT) defines three color schemes, accessed with [body 1], [body 2], and [body 3] elements in MiniVend pages. The first scheme uses the file /images/blue_pap.gif as the background pattern, and keeps the user's default colors for everything else. It is called by a [body 1] element, which when expanded becomes <BODY BACKGROUND="/images/blue_pap.gif>.

The second scheme defines no background pattern (there is only one file in the Mv_Background directive), but defines a background color of 'steelblue', with a text color of white, a link color of light green, and a visited link color of orange. It is accessed by the [body 2] element, which when expanded becomes <BODY BGCOLOR="steelblue" TEXT="white" LINK="ltgreen" VLINK="orange">.

The third color scheme is similar to the second, except defines white-black-blue-purple for the four colors. It is accessed with a [body 3] element.

If there is no defined scheme for a body element (as there wouldn't be if you put [body 4] in a page with the above schemes defined) MiniVend simply outputs a standard <BODY> tag.

The user can also define their own colors if the Mv_customcolors variable is set (upon a form submission). See the supplied control.html page for an example of how to set custom colors.

Image maps can be supplied and similarly controlled with the [buttonbar n] series of tags. They are defined with the ButtonBars directive (also set in minivend.cfg or with MAT), 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 IMG directive set with the USEMAP element and an associated client-side image map (defined with <MAP> </MAP>. The [areatarget] or [area] tags are used to set the URLs. An example:

<IMG SRC="/sample/images/artbar0.gif" USEMAP="#ARTBAR0">
<MAP NAME=ARTBAR0>
<AREA COORDS="198,0,278,20" HREF="[areatarget fr_sel search]">
<AREA COORDS="303,0,363,20" HREF="[areatarget fr_search search]">
<AREA COORDS="388,0,442,20" HREF="[areatarget fr_greet main]">
<AREA COORDS="473,0,537,20" HREF="[areatarget control main]">
<AREA COORDS="0,0,560,20" NOHREF>
</MAP>

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 [buttonbar 0] tag, at least after MiniVend read this line in the configuration file:

ButtonBars  bars/artbar0 bars/artbar1 bars/artbar2

The above entry allows you to define three imagemaps and access them in your pages simply as [buttonbar 0], [buttonbar 1], and [buttonbar 2]. 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.)

Imagemaps can also be defined on forms, with the special form variable mv_todo.map. A series of map actions can be defined -- the action specified in the default entry will be applied if none of the other coordinates match. The image is specified with a standard HTML 2.0 form field of type IMAGE. Here is an example:

<INPUT TYPE="HIDDEN" NAME="mv_todo.map" VALUE="rect submit 0,0 100,20">
<INPUT TYPE="HIDDEN" NAME="mv_todo.map" VALUE="rect cancel 290,2 342,18">
<INPUT TYPE="HIDDEN" NAME="mv_todo.map" VALUE="default refresh">
<INPUT TYPE="IMAGE" NAME="mv_todo" SRC="url_of_image">

All of the actions will be combined together into one image map with NCSA-style functionality -- see the NCSA imagemap documentation for details -- except that MiniVend form actions are defined instead of URLs. The standard actions are:

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

The [random] element, in conjunction with the Random directive in the minivend.cfg file (or set with MAT), 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 HTML construct. It cannot contain MiniVend elements.

The [help tag] element, in conjunction with the Help directive in the minivend.cfg file (or, of course, set with MAT), 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 control.html file for an example.

MINIVEND CONFIGURATION FILE

The VendRoot directory, specified in vend.pl, is the default location of all of the MiniVend files. Unless changed in minivend.pl, the MiniVend configuration file will be minivend.cfg in the VendRoot directory.

In the configuration file, these directives are required:

VendURL Specifies the base URL that will run svend as a cgi-bin program.
VendURL  http://machine.company.com/cgi-bin/vlink
MailOrderTo Specifies the email address to mail completed orders to.
MailOrderTo  orders@xyzcorp.com

Optional Configuration Directives

These directives all have default values and are optional.

AlwaysSecure 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.
AlwaysSecure    checkout
AsciiBackend A 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.
AsciiBackend  |/usr/order/scripts/place_order
AsciiTrack

A file name to log formatted orders in. Unless preceded by a leading '/', will be placed relative to VendRoot. Disabled by default.

AsciiTrack     etc/orders.txt
ButtonBars The ButtonBars directive allows you to define several preset button bars that reside in files. The button bar file will usually contain an IMG link, along with its associated client-side image map. This allows you to insert a [buttonbar 1] or [buttonbar 2] directive instead of the equivalent HTML, 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 minivend.cfg file takes the form of the directive, followed by any number of vend-style file names (relative to the PageDir, with no .html suffix).
ButtonBars  bars/button0 bars/button1 bars/button2 bars/button3
CheckoutFrame The frame name where the checkout page will go, if frames are enabled. Default is "_top".
CheckoutFrame  _blank
Cookies         Yes
CreditCards If set to Yes, enables the encryption and saving of fields on the order form that contain credit_card in their name. See "Order Security". Default is no, or not enabled.
CreditCards     Yes
CustomShipping If not blank, enables the addition of shipping charges based on quantity or weight of items ordered. See "Custom Shipping".
CustomShipping      quantity
DataDir 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.
DataDir             /user/data
Database Definition of an arbitrary database, in the form "Database database file type", where "file" is the name of an ASCII file in the same format as the products database. The file is relative to VendRoot, and is put in DataDir if no path is provided. Records can be accessed with the [data database field key] tag. The type is an integer from one to six, and specifies the format. There can be an unlimited number of databases defined. See "Arbitrary Databases".
Database      BookReviews  reviews.txt   3
DefaultShipping This sets the default shipping mode by initializing the variable mv_ship_mode. If not set in minivend.cfg, it is default.
DefaultShipping     UPS
Delimiter One of TAB, PIPE, CSV, or your own custom delimiter. (It is not suggested that you use a custom delimiter). TAB means a tab-delimited database (the default if not set), PIPE a pipe-delimited one, and CSV a quote-comma format.
Delimiter           CSV
DescriptionField The field that will be accessed with the [item-description] element.
DescriptionField    ProductDescription
DescriptionTrim This sets the text string after which no more of the product description will be displayed in the search area. This is useful to clip long descriptions, while still having them available to search. The default is no trimming.
DescriptionTrim     DESCRIPTION:
DisplayErrors 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.
DisplayErrors       Yes
EncryptProgram Enables the encryption of fields containing the string credit_card in their name. If the Des module is not included, should contain a program command line specification that indicates how an external encryption program will work. Two placeholders, %p and %f, are defined, which are replaced at encryption time with the password and temporary file name respectively. See "Order Security".
EncryptProgram      /usr/local/bin/des -E -k %p < %f
FinishOrder A text string or image tag which is substituted for the [finish_order] tag.
FinishOrder <IMG SRC="/icons/fin_ord.gif" ALT="FINISH ORDER">
FrameOrderPage The MiniVend-style page name (i.e. no .html extension, relative to PageDir) which contains the special order page for when frames are in use. If not set (the default), the standard order page will be used.
FrameOrderPage      fr_order
FrameSearchPage The MiniVend-style page name (i.e. no .html extension, relative to PageDir) which contains the special search page for when frames are in use. If not set (the default), the standard search page will be used.
FrameSearchPage     fr_resul
Glimpse The pathname for the glimpse command, used if glimpse searches are to be enabled. If you wish to use glimpseserver, you must include the -C, -J, and -K tags if they are needed.
Glimpse  /usr/local/bin/glimpse -C -J srch_engine -K2345
HammerLock 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.
HammerLock      60
Help 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 [help item] tag, where item is the first line of a help file entry which looks like:
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.

If the file (or the entry) does not exist at program configuration time, the tag is simply stripped. The line in the minivend.cfg 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.

Help  help/hintfile
ItemLinkDir     partno/
ItemLinkValue   <IMG SRC="/images/gopage.gif" ALT="GO TO PAGE">
MixMatch Sets whether quantity price breaks will be on TOTAL quantity or per-item quantity. Default is no mix and match, pricing is on a per-item basis. A yes or no field.
MixMatch        yes
MultiServer If defined to be non-zero, then multiple servers can share the socket and serve users. Not usable on SGI or Sun/Solaris 2 systems.
MultiServer     yes
Mv_Background Sets the background patterns to be used in the color schemes. The line must begin with 'BEGIN', 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.
Mv_Background BEGIN /images/blue_pap.gif 0 /images/temple.jpg
Mv_BgColor Sets the background colors to be used in the color schemes. The line must begin with 'BEGIN', then is followed by up to 15 RGB color specifications for background color. The specification can be in #RRGGBB 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 'none' to disable a color (use the browser default) for a particular scheme. Remember, the schemes are numbered in the order that they occur.
Mv_BgColor BEGIN  steelblue none white
Mv_LinkColor BEGIN  ltgreen none red
Mv_TextColor Sets the text colors to be used in the color schemes. The colors are accessed with the [body n] tag, where n is the color scheme number. The line must begin with 'BEGIN', then is followed by up to 15 RGB color specifications for text color. The specification can be in #RRGGBB 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 'none' 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.
Mv_TextColor BEGIN  white none black
Mv_VlinkColor BEGIN  orange none blue
NonTaxableField 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.
NonTaxableField    wholesale
OrderCounter The name of the file (relative to VendRoot if no leading /) that maintains the order number.
OrderCounter       etc/order.number
OrderFrame 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.
OrderFrame          _blank
OrderReport The location of the simple order report file. Defaults to report.
OrderReport          /data/order-form
PageDir Location of catalog pages. Defaults to the pages subdirectory in the VendRoot directory.
PageDir             /data/catalog/pages
PriceBreaks 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.
PriceBreaks         10 25 50 100 1000
PriceCommas If you desire no commas in your price numbers (for the [item_price] tag) set this to 'no'. The default is to put commas in.
PriceCommas         no
PriceDivide 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.
PriceDivide         100
PriceField The field in the product database that will be accessed with the [item-price] element. Default is "price".
PriceField          ProductPrice
ProductDir Location of the product files. Defaults to the products subdirectory of the VendRoot directory.
ProductDir          /data/catalog/for-sale
Random 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 [random] tag. You don't know which one will show up! Even I don't, it is random. If the file does not exist at program configuration time, the tag is simply stripped. The line in the minivend.cfg file takes the form of the directive, followed by any number of vend-style file names (relative to the PageDir, with no .html suffix).
Random  rand/message1 rand/message2 rand/message3 rand/message4
ReadPermission and WritePermission By default, only the user account that MiniVend runs under (as set by the setuid permission on svend) can read and write files created by MiniVend. WritePermission and ReadPermission can be set to 'user', 'group', or 'world'.
WritePermission     group
ReadPermission      group
ReceiptPage The page to be displayed as a receipt after the user has submitted an order. Replaces the standard 'confirmation' page. Blank by default, showing no receipt page to the user.
ReceiptPage         receipt
ReportIgnore A comma-separated list of items you don't want to have sent by email on the order report. Default is blank, or none. Fields beginning with 'mv_', the MiniVend special variables, are automatically ignored.
ReportIgnore        credit_card_no
RequiredFields A 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 needfield.html will be displayed to request that they enter the information. No default.
RequiredFields      name,company,email,address,city,state,zip
SalesTax 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.
SalesTax            zip,state
ScratchDir The directory where scratch files will be written, notably cached searches. Defaults to VendRoot/etc.
ScratchDir          /tmp
SearchOverMsg A string that is substituted for a [search_over_msg] tag, used to indicate that the search engine returned more than the number of items it was limited to.
SearchOverMsg       You had more than
SearchFrame 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'.
SearchFrame         main
SearchProfile Allows an unlimited number of search profiles to be set up, specifying complex searches based on a single click. Takes a series of MiniVend variable specifications.

As an added measure of control, the specification is evaluated with the special MiniVend [if area value ....]value[else]other value[/else][/if] syntax to provide conditional setting of search parameters.

The following file specifies a dictionary-based search in the file 'dict.product':

mv_search_file=dict.product
mv_return_fields=1
[if value fast_search]
    mv_dict_limit=-1
    mv_last=1
[/if]

The search profiles are specified in the same manner as the ButtonBars directive, with files to be located in the MiniVend page tree and read at program startup. If you change a search profile, you must stop and start MiniVend to have the changes take effect.

SearchProfile    srch/search0 srch/search1 srch/search2

They are accessed by setting the mv_profile variable to the number of the search profile.

SecureURL The base URL for secure forms/page transmissions. Normally it is the same as VendURL except for the https: protocol definition. Default is blank, disabling secure access.
SecureURL   https://machine.com/xyzcorp/cgi-bin/vlink
SendMailProgram 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.
SendMailProgram     /bin/mailer
SessionDatabase When storing sessions in a DBM database, specify the base name of the DBM file to use. The file extensions of .pag, .dir, or .gdbm (depending on the DBM implementation used) will be appended.
SessionDatabase     session-data
SessionExpire A customer can exit their browser or leave the catalog pages at any time, and no indication is given to the HTTPD 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.
SessionExpire       4 hours
Shipping 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 [shipping] element in the order page. Defaults to 0. Overridden by the CustomShipping directive.
Shipping            5.00
TaxShipping A comma or space separated list of states or jurisdictions that tax shipping cost, i.e. UT. Blank by default, never taxing shipping.
TaxShipping         UT,NV,94024
Tracking Enables order and popularity tracking when entered, as well as enabling password and credit card encryption for order security (in combination with the EncryptProgram directive). Its value is the initial order number that will be used as the beginning key for orders in the tracking database. See "Tracking and Backend Order Entry" and "Order Security".
Tracking            Order100001
UseCode             yes

Required Pages

A number of HTML 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.

As of MiniVend 1.03, the names of these pages can be set with the SpecialPage directive. The standard pages and their default locations:

badsearch (pages/badsearch.html) The error page displayed if there is a system or user error with the search engine.
canceled.html (pages/badsearch.html) The page displayed by MiniVend when an order has been canceled by the user.
catalog (pages/catalog.html) The main catalog page presented by MiniVend when another page is not specified.
checkout (pages/order.html) The page the customer is sent to when checking out (the location pointed to by a [finish_order] tag.
confirmation.html (pages/badsearch.html) After the order is completed, the confirmation page is displayed.
failed (pages/failed.html) 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).
flypage (pages/flypage.html) If the catalog page for an item was not found when its [item_link] is clicked, this page is used as a template to build an on-the-fly page. See On-the-fly Catalog Pages.
interact (pages/interact.html) 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.
missing (pages/missing.html) This page is displayed if the URL 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.
needfield (pages/needfield.html) Displayed if the user did not fill in a required field in the order form. See "REQUIRED FIELDS".
nomatch (pages/nomatch.html) This page is displayed if the search engine is used, but there is no match for the search specification.
noproduct (pages/noproduct.html) This page is displayed if the URL from the browser specifies the ordering of a product code which is not in the products file.
order (pages/order.html) 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 configured with the directive FrameOrderPage.
violation (pages/violation.html) 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.

ADMINISTERING MINIVEND

There is a supplied administration utility, MAT, the MiniVend Administration Tool, which has its own documentation. It allows you to perform most of the following operations via a web browser.

Starting, Stopping, and Re-starting the Servers

When running in server mode, MiniVend operates much faster. Since it is loaded once, and keeps some of the database files open continuously, it merely needs to field the CGI request (via vlink) and perform the appropriate function. But because it is running, some of the databases are locked -- and you will need to unlock them to perform administrative functions. MAT or the supplied scripts will do that for you.

Several utilities are supplied in the VendRoot/bin directory:

stop       Stops the server(s)
start      Starts the server(s)
restart    Re-starts the server (simply stops and starts)
testpages  Tests the MiniVend page tree for syntax and database 
           errors

The following commands assume that you made /usr/local/lib/minivend your MiniVend base directory.

To start the server:

/usr/local/lib/minivend/bin/start [n]

If the optional n, an integer from 1 to 9, is supplied, that number of servers will be started (assuming you have the MultiServer directive set to yes.

Assuming the server starts correctly, you will see a message stating the process ID it is running under -- that information is also sent to /usr/local/lib/minivend/error.log.

To re-start the server:

/usr/local/lib/minivend/bin/restart [n]

This is typically done to force MiniVend to re-read its configuration. You will see a message stating that a TERM signal has been sent to the process ID the servers are running under -- that information is also sent to /usr/local/lib/minivend/error.log. Check the error.log file for confirmation that the server has restarted properly.

To stop the server(s):

/usr/local/lib/minivend/bin/stop

You will see a message stating that a TERM signal has been sent to the process ID the server is running under -- that information is also sent to /usr/local/lib/minivend/error.log.

Because processes waiting for lock in MultiServer mode are blocking signals, they may have to be killed more than once to die. This is normal and is of no concern.

Checking Page Syntax

Any time you change the pages or the database, you should run the testpages command. It iterates through the MiniVend page tree, checking form values (if you have HTML::Parse and its associated modules), page links, and some configuration values. It is run with:

/usr/local/lib/minivend/testpages [pages to test]

The [pages to test] are in MiniVend path name format, relative to PageDir. If you don't enter any, all pages will be tested -- this can take a long time if you have a large page tree.

Forms are checked if you have the HTML::Parse module, available at any CPAN archive (where you obtained Perl).

Making the Product Database

As of MiniVend 1.02, the product database is made automatically upon server startup, and no special command is required. You must not use the old makedbm command from V1.01.

Expiring Sessions

You should periodically expire old sessions to keep the session database file from growing too large. Either manually do this with MAT, or directly execute minivend.pl to do this:

/usr/local/lib/minivend/minivend.pl -expire

You could add a crontab entry such as the following:

# once a day at 4:40 am
40 4 * * *    perl /usr/local/lib/minivend/minivend.pl -expire

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 cache files for the affected session (kept in ScratchDir) will be removed as well.

NOTE: DB_File users may have to stop the server before running expire when on a BSD system.

INDEX OF ITEMS

[accessories code]

AlwaysSecure

[area pg]

[areatarget pg frame]

AsciiBackend

AsciiTrack

[body n]

[buttonbar n]

ButtonBars

cgi-bin

CGIUSER

CheckoutFrame

[col width=nn wrap=yes|no gutter=n align=left|right|input spacing=n]

Cookies

CreditCards

CustomShipping

[data area field key]

Database

DataDir

DefaultShipping

Delimiter

[description code]

DescriptionField

DescriptionTrim

DisplayErrors

EncryptProgram

[field name code]

[finish_order page*]

FinishOrder

FrameOrderPage

[frames_off]

[frames_on]

FrameSearchPage

Glimpse

HammerLock

Help

[if_field fieldname]

[if type field op* compare*]

[item_accessories]

[item_code]

[item_data database fieldname]

[item_description]

[item_field fieldname]

[item_increment]

[item_link code]

[item_list]

[item_price]

[item_quantity]

[item_quantity]

ItemLinkDir

ItemLinkValue

LINK_FILE

LINK_TIMEOUT

machine.company.com

MailOrderTo

[matches]

MixMatch

[more]

[more_list]

MultiServer

Mv_Background

mv_base_directory

Mv_BgColor

mv_case

mv_coordinate

mv_dict_end

mv_dict_fold

mv_dict_limit

mv_dict_look

mv_dict_order

mv_doit

mv_exact_match

Mv_LinkColor

mv_matchlimit

mv_max_matches

mv_orsearch

mv_profile

mv_return_fields

mv_search_field

mv_search_file

mv_search_over_msg

mv_search_page

mv_searchspec

mv_searchtype

mv_spelling_errors

mv_substring_match

Mv_TextColor

Mv_VlinkColor

NET_START

[nitems]

NonTaxableField

[order code page*]

OrderCounter

OrderFrame

OrderReport

PageDir

[page pg]

[pagetarget pg frame]

PERL

PERL

PriceBreaks

[price code]

PriceCommas

PriceDivide

PriceField

[process_search]

[process_target frame]

ProductDir

[quantity_name]

[random]

Random

ReadPermission and WritePermission

ReceiptPage

ReportIgnore

RequiredFields

[row nn]

[salestax]

SalesTax

ScratchDir

[search_list]

SearchFrame

SearchOverMsg

SearchProfile

SecureURL

SendMailProgram

SessionDatabase

SessionExpire

Shipping

[shipping_description]

[subtotal]

TaxShipping

[total_cost]

Tracking

UseCode

[value field]

VEND

VEND

VendURL

vlink

AUTHORS

Original author of Vend is Andrew Wilcox, F<awilcox@world.std.com>
MiniVend is based on Vend 0.2, with portions from Vend 0.3,
and is enhanced and modified extensively by Mike Heins, F<mikeh@iac.net>

5 POD Errors

The following errors were encountered while parsing the POD:

Around line 1054:

You forgot a '=back' before '=head2'

Around line 1066:

'=item' outside of any '=over'

Around line 1233:

=over should be: '=over' or '=over positive_number'

Around line 1280:

You forgot a '=back' before '=head2'

Around line 1664:

=back doesn't take any parameters, but you said =back =head2 Customer Input Fields