.\" Automatically generated by Pod::Man version 1.15
.\" Wed May 5 11:53:22 2004
.\"
.\" Standard preamble:
.\" ======================================================================
.de Sh \" Subsection heading
.br
.if t .Sp
.ne 5
.PP
\fB\\$1\fR
.PP
..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Ip \" List item
.br
.ie \\n(.$>=3 .ne \\$3
.el .ne 3
.IP "\\$1" \\$2
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. | will give a
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used
.\" to do unbreakable dashes and therefore won't be available. \*(C` and
.\" \*(C' expand to `' in nroff, nothing in troff, for use with C<>
.tr \(*W-|\(bv\*(Tr
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
'br\}
.\"
.\" If the F register is turned on, we'll generate index entries on stderr
.\" for titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and
.\" index entries marked with X<> in POD. Of course, you'll have to process
.\" the output yourself in some meaningful fashion.
.if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
.\"
.\" For nroff, turn off justification. Always turn off hyphenation; it
.\" makes way too many mistakes in technical documents.
.hy 0
.if n .na
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
.bd B 3
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ======================================================================
.\"
.IX Title "icfull 8"
.TH icfull 8 "Interchange 5.2.0" "2004-05-05" "Interchange"
.UC
.SH "NAME"
icfull \- Interchange Documentation (Full)
.PP
This is the documentation for Interchange, all in one large file.
.PP
.Vb 12
\& Interchange Advanced Topics
\& Interchange Catalog-Building Tutorial
\& Interchange Configuration
\& Interchange Database
\& Interchange Ecommerce Functions
\& Interchange Foundation Store
\& Interchange I18N Features
\& Interchange Templates
\& Interchange Tags Reference
\& Interchange Frequently Asked Questions
\& Interchange Upgrade Guide
\& Interchange Programmer Variables Reference
.Ve
line:
.PP
Interchange Ecommerce Functions
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
.SH "THE ORDER PROCESS"
.IX Header "THE ORDER PROCESS"
Interchange has a completely flexible order basket and checkout
scheme. The foundation demo presents a common use of this process,
in the directory pages/ord \*(-- the files are:
.PP
.Vb 3
\& basket.html The order basket displayed by default
\& checkout.html The form where the customer enters their billing
\& and shipping info
.Ve
.RS 4
.RS 8
.Ip "" 12
and in the directory etc:
.Sp
.Vb 1
\& receipt.html The receipt displayed to the customer
.Ve
.RE
.RS 8
.RE
.RE
.RS 4
.RE
.PP
It is not strictly necessary to display an order basket when an item
is ordered. If you specify a different page to be displayed that is
fine, but most customers will be confused if you don't give them an
indication that the order operation has succeeded.
.PP
Any order basket is an \s-1HTML\s0 \s-1FORM\s0. It will have a number of
variables on it. At the minimum it must have an [item-list] to loop
through the items, and the quantity of each item must be set in
some place on that form. Any valid Interchange tags may be used on the
page, and you may use multiple item lists if necessary.
.Sh "How to order an item"
.IX Subsection "How to order an item"
Interchange can either use a form-based order or a link-based order to
place an item in the shopping cart. The link-based order uses the
special [order item-code] tag:
.Ip "[order code]" 4
.IX Item "[order code]"
named attributes:
.Sp
.Vb 2
\& [order code="sku" quantity="n"* href="page"* cart="cartname"* base="table"*]
\& * = optional parameters
.Ve
Expands into a hypertext link which will include the specified code in
the list of products to order and display the order page. \fBcode\fR
should be a product \s-1SKU\s0 listed in one of the \*(L"products\*(R" tables, and is
the only required parameter. \fBquantity\fR may be specified if more than
one (the default) of the item should be placed in the cart. \fBhref\fR
allows some page other than the default order page to be displayed
once the item has been added to the cart. \fBcart\fR selects the shopping
cart the item will be placed in. The optional argument \fBbase\fR
constrains the order to a particular products file \*(-- if not
specified, all tables defined as products files will be searched in
sequence for the item.
.Sp
Example:
.Sp
.Vb 1
\& Order a [order TK112]Toaster today.
.Ve
Note that this is the same as:
.Sp
.Vb 1
\& Order a [page order TK112]Toaster today.
.Ve
You can change frames for the order with:
.Sp
.Vb 1
\& Order a Toaster today.
.Ve
.Ip "[/order]" 4
.IX Item "[/order]"
Expands into . May be used to give the order tag the appearance of
being a container tag, but neither necessary nor recommended.
.PP
To order with a form, you set the form variable mv_order_item to
the item-code/SKU and use the refresh action:
.PP
.Vb 3
\&
.Ve
You may batch select whole groups of items:
.PP
.Vb 2
\&
.Ve
Items that have a quantity of zero (or blank) will be skipped, and
only items with a positive quantity will be placed in the basket.
.PP
You may also specify attributes like size or color at time of order
(see \fIHow to set up an order button\fR).
.Sh "How to set up an order link"
.IX Subsection "How to set up an order link"
On a product display page, use:
.PP
.Vb 1
\& [order 00-0011]Order the Mona Lisa
.Ve
If coming from a search results or on-the-fly page, you may use the
generated [item-code] thusly:
.PP
.Vb 1
\& [order [item-code]]Order [item-field name]
.Ve
Bear in mind that if you have not reached the page via a search or
on-the-fly operation, [item-code] means nothing and will cause an
error.
.Sh "How to set up an order button"
.IX Subsection "How to set up an order button"
Interchange can order via form submission as well. This allows you to
order a product (or group of products) via a form button. In its
simplest form, it is:
.PP
.Vb 5
\&
.Ve
The default quantity is one. An initial quantity may be set by the
user by adding an mv_order_quantity variable:
.PP
.Vb 1
\& Number to order:
.Ve
You can order multiple items by stacking the variables:
.PP
.Vb 6
\&
.Ve
Initial size or color may be set as well, provided \fIUseModifier\fR is
set up properly:
.PP
.Vb 1
\&
.Ve
If the order is coming from a generated flypage, loop list, or search
results page, you can get a canned select box from the
[item-accessories size] or [item-accessories size] tag. See
\&\fIItem Attributes\fR.
.Sh "How to set up an on-the-fly item"
.IX Subsection "How to set up an on-the-fly item"
If you enable the catalog directive \fIOnFly\fR, setting it to the name
of a subroutine (or possibly a UserTag) that can handle its calls,
then Interchange will add items to the basket that are not in the
product database. Interchange supplies an internal onfly
subroutine, which will work according to the examples given below.
.PP
In catalog.cfg:
.PP
.Vb 1
\& OnFly onfly
.Ve
If your item code is not to be named mv_order_item then you must
perform a rename in the Autoload routine.
.PP
A basic link can be generated like:
.PP
.Vb 5
\& Order item 000101
.Ve
The form parameter value mv_order_fly can contain any number of
fields which will set corresponding parameters in the item attributes.
The fields are separated by the pipe (|) character and contain
value-parameter pairs separated by an = sign. (These are URL-encoded
by the [area ...] or [page ...] tag, of course.) You can set a
size, color, or any other parameter.
.PP
The special attribute mv_price can be used in conjunction with the
CommonAdjust atom $ to set the price for checkout and display.
.PP
The [item-list] sub-tag [item-description], when used with an
item-list, will use the item attribute description to display in
the basket. Note that [item-field description] or [item-data
products description] will \s-1NOT\s0 work, as both of these tags reference
an actual field value for a record in the products table \- not
applicable for on-the-fly items. Similarly, an attempt to generate a
flypage for an on-the-fly item ([page 000101], for example) will
fail, resulting in the display of the SpecialPage \fBmissing\fR.
.PP
If you wish to set up a UserTag to process on-the-fly items, it should
accept a call of
.PP
.Vb 1
\& usertag(mv_item_code, mv_item_quantity, mv_order_fly)
.Ve
The mv_item_code and mv_order_fly parameters are required to
trigger Interchange's add_item routine (along with mv_todo=refresh
to set the action).
.PP
The item will always act as if SeparateItems or
mv_separate_items is set.
.PP
Multiple items can be ordered at once by stacking the variables. If
there is only one mv_order_item instance, however, you can stack
the mv_order_fly variable so that all are concatenated together as
with the | symbol. So the above example could be done as:
.PP
.Vb 6
\& [area form="
\& mv_todo=refresh
\& mv_order_item=000101
\& mv_order_fly=description=An on-the-fly item
\& mv_order_fly=price=100.00
\& "]
.Ve
Multiple items would need multiple instances of mv_order_item with
a corresponding mv_order_fly for each mv_order_item. You can
order both 000101 and 000101 as follows:
.PP
.Vb 2
\& [area form="
\& mv_todo=refresh
.Ve
.Vb 2
\& mv_order_item=000101
\& mv_order_fly=description=An on-the-fly item|price=100.00
.Ve
.Vb 3
\& mv_order_item=000102
\& mv_order_fly=description=Another on-the-fly item|price=200.00
\& "]
.Ve
The following two forms correspond to the above two examples, in
order, with the slight refinement of adding a quantity:
.PP
.Vb 8
\&
.Ve
.Vb 12
\&
.Ve
.Sh "Order Groups"
.IX Subsection "Order Groups"
Interchange allows you to group items together, making a master item
and sub-items. This can be used to delete accessories or options when
the master item is deleted. In its simplest form, you order just one
master item and all subsequent items are sub-items.
.PP
.Vb 7
\&
.Ve
If you wish to stack more than one master item, then you must define
mv_order_group for \fBall\fR items, with either a 1 value (master) or 0
value (sub-item). A master owns all subsequent sub-items until the
next master is defined.
.PP
.Vb 12
\&
.Ve
When the master item 00\-0011 is deleted from the basket,
00\-0011a will be deleted as well. And when 19\-202 is deleted, then
99\-102 will be deleted from the basket.
.PP
\&\s-1NOTE:\s0 Use of checkboxes for this type of thing can be hazardous, as
they do not pass a value when unchecked. It is preferable to use
radio groups or select/drop-down widgets. If you must use checkboxes,
be sure to explicitly clear mv_order_group and mv_order_item
somewhere on the page which contains the form:
.PP
.Vb 2
\& [value name=mv_order_group set='']
\& [value name=mv_order_item set='']
.Ve
The attributes mv_mi and mv_si are set to the group and sub-item
status of each item. The group, contained in the attribute mv_mi,
is a meaningless yet unique integer. All items in a group will have
the same value of mv_mi. The attribute mv_si is set to 0 if the
item is a master item, and 1 if it is a sub-item.
.Sh "Basket display"
.IX Subsection "Basket display"
The basket \fIpage\fR\|(s) are where the items are tracked and adjusted by the
customer. It is possible to have an unlimited number of basket pages.
It is also possible to have multiple shopping carts, as in buy or
sell. This allows a basket/checkout type of ordering scheme, with
custom order pages for items which have many accessories.
.PP
The name of the page to display can be configured in several ways:
.Ip "1." 4
Set the SpecialPage order to the page to display when an item is
ordered.
.Ip "2." 4
Use the \f(CW\*(C`[order code=item page=page_name] Order it! \*(C'\fR form of
order tag to specify an arbitrary order page for an item.
.Ip "3." 4
If already on an order page, set the mv_orderpage, mv_nextpage,
mv_successpage, or mv_failpage variables.
.PP
The following variables can be used to control cart selection and page
display:
.Ip "mv_cartname" 4
.IX Item "mv_cartname"
The shopping cart (default is main) to be used for this order
operation.
.Ip "mv_failpage" 4
.IX Item "mv_failpage"
Page to be displayed on a failed order check (see \fIAdvanced
Multi-level Order Pages\fR)
.Ip "mv_nextpage" 4
.IX Item "mv_nextpage"
Page to display on a return operation.
.Ip "mv_orderpage" 4
.IX Item "mv_orderpage"
Page to be displayed on a refresh.
.Ip "mv_successpage" 4
.IX Item "mv_successpage"
Page to be displayed on a successful order check (see \fIAdvanced
Multi-level Order Pages\fR).
.Ip "mv_order_profile" 4
.IX Item "mv_order_profile"
Order profile to be used if the form action is \fIsubmit\fR (see
\&\fIAdvanced Multi-level Order Pages\fR).
.Sh "Multiple Shopping Carts"
.IX Subsection "Multiple Shopping Carts"
Interchange allows you to define and maintain multiple shopping carts.
One shopping cart \*(-- main, by name \*(-- is defined when the user session
starts. If the user orders item M1212 with the following tag:
.PP
.Vb 1
\& [order code=M1212 cart=layaway] Order this item!
.Ve
the order will be placed in the cart named \fIlayaway\fR. However, by
default you won't see the just-ordered item on the basket page. That
is because the default shopping basket displays the contents of the
\&'main' cart only. So copy the default basket page
(pages/ord/basket.html in the demo) to a new file, insert a [cart
layaway] tag, and specify it as the target page in your [order]
tag:
.PP
.Vb 1
\& [order code=M1212 cart=layaway page=ord/lay_basket] Order this item!
.Ve
Now the contents of the \fIlayaway\fR cart will be displayed. Most of the
\&\s-1ITL\s0 tags that are fundamental to cart display accept a 'cartname'
option, allowing you to specify which cart to be used:
.Ip "[cart cartname]" 4
.IX Item "[cart cartname]"
A 'sticky' setting of the default cart name to use for all subsequent
cart-related tags. Convenient, but you must remember to use [cart
main] to get back to the primary cart! As an alternative, you can
specify the desired cart as a parameter of the other tags. These are
not sticky, referencing the specified cart only for the instance in
which they are called:
.Ip "[item-list cartname]...[/item-list]" 4
.IX Item "[item-list cartname]...[/item-list]"
Iterates over the items in the specified cart \- tags like
[item-quantity] and [item-price] will be evaluated accordingly;
.Ip "[nitems cartname]" 4
.IX Item "[nitems cartname]"
Returns the total number of items in the specified cart;
.Ip "[subtotal cartname]" 4
.IX Item "[subtotal cartname]"
Returns the monetary subtotal for the contents of specified cart;
.Ip "[shipping cartname], [handling cartname], [salestax cartname], [total-cost cartname]" 4
.IX Item "[shipping cartname], [handling cartname], [salestax cartname], [total-cost cartname]"
You get the idea. It is worth noting that tags which summarize cart
contents do not need to be in used concert, or in conjunction with an
[item-list]. For instance, you can display just the grand total for
a cart on the sidebar or bottom of each page, using [total-cost] by
itself, if you wish.
.PP
You can also order items from a form, using the mv_order_item,
mv_cartname, and optional mv_order_quantity variables.
.PP
.Vb 7
\&
.Ve
If you need to utilize an alternative item price in conjunction with
the use of a custom cart, see the section on \fI\s-1PRODUCT\s0 \s-1PRICING\s0\fR for
pricing methods and strategies.
.SH "PRODUCT PRICING"
.IX Header "PRODUCT PRICING"
Interchange maintains a price in its database for every product. The
price field is the one required field in the product database \*(-- it is
necessary to build the price routines.
.PP
For speed, Interchange builds the code that is used to determine a
product's price at catalog configuration time. If you choose to change
a directive that affects product pricing you must reconfigure the
catalog.
.Sh "Simple pricing"
.IX Subsection "Simple pricing"
The simplest method is flat pricing based on a fixed value in the
products database. If you put that price in a field named price,
you don't need to do more. If you want to change pricing based on
quantity, size, color or other factors read on.
.Sh "Price Maintenance with CommonAdjust"
.IX Subsection "Price Maintenance with CommonAdjust"
A flexible chained pricing scheme is available when the
\&\fICommonAdjust\fR directive is set.
.PP
We talk below about a \fICommonAdjust string\fR; it will be defined in
due time.
.PP
A few rules about CommonAdjust, all assuming the \fIPriceField\fR
directive is set to price:
.Ip "1" 4
.IX Item "1"
.PP
If CommonAdjust is set to any value, a valid \fICommonAdjust string\fR
or not, extended price adjustments are enabled. It may also hold the
default pricing scheme.
.Ip "2" 4
.IX Item "2"
.PP
The price field may also hold a \fICommonAdjust string\fR. It takes
precedence over the default.
.Ip "3" 4
.IX Item "3"
.PP
If the value of the CommonAdjust directive is set to a CommonAdjust
string, and the price field is empty or specifically \fI0\fR, then it
will be used to set the price of the items.
.Ip "4" 4
.IX Item "4"
.PP
If no CommonAdjust strings are found, then the price will be 0,
subject to any later application of discounts.
.Ip "5" 4
.IX Item "5"
.PP
If another CommonAdjust string is found as the result of an operation,
it will be re-parsed and the result applied. Chaining is retained; a
fallback may be passed and will take effect.
.PP
Prices may be adjusted in several ways, and the individual actions are
referred to below as \fIatoms\fR. Price atoms may be \fIfinal\fR,
\&\fIchained\fR, or \fIfallback\fR. A final price atom is always applied if it
does not evaluate to zero. A chained price atom is subject to further
adjustment. A fallback price atom is skipped if a previous chained
price was not zero.
.PP
Atoms are separated by whitespace, and may be quoted (although there
should not normally be whitespace in a setting). A chained item ends
with a comma. A fallback item has a leading semi-colon. Final atoms
have no comma appended or semi-colon prepended.
.PP
A \fIsettor\fR is the means by which the price is set. There are eight
different types of price settors. All settors can then yield another
CommonAdjust string.
.PP
It is quite possible to create endless loops, so the maximum number of
initial CommonAdjust strings is set to 16, and there may be only 32
iterations by default before the price will return zero on an error.
(The maximum iterations is specified with the \fILimit\fR directive.)
.PP
\&\fB\s-1NOTE\s0\fR: Common needs are easily shown but not so easily explained;
skip to the examples in the reference below if your vision starts to
blur when reading the next section. 8\-)
.PP
\&\s-1USAGE:\s0 Optional items below have asterisks appended. The asterisk
should not be used in the actual string. Optional \fBbase\fR or \fBtable\fR
always defaults to the active products database table. The
optional \fBkey\fR defaults to the item code except in a special case for
the attribute-based lookup. The \fBfield\fR name is not optional except
in the case of an attribute lookup.
.Ip "N.NN or \-N.NN" 4
.IX Item "N.NN or -N.NN"
where N is a digit. A number which is applied directly; for instance
10 will yield a price of 10. May be a positive or negative number.
.Ip "N.NN%" 4
.IX Item "N.NN%"
where N is a digit. A number which is applied as a percentage of the
\&\fIcurrent\fR price value. May be a positive or negative number. For
example, if the price is 10 and \-8% is applied, the next price value
will be 9.20.
.Ip "table*:column:key*" 4
.IX Item "table*:column:key*"
Causes a straight lookup in a database table. The optional \fBtable\fR
defaults to the main products database table for the item (subject of
course to multiple product files). The \fBcolumn\fR must always be
present. The optional \fBkey\fR defaults to the item code except in a
special case for the attribute-based lookup. The return value is then
re-parsed as another price settor.
.Ip "table*:col1..col5,col10:key*" 4
.IX Item "table*:col1..col5,col10:key*"
Causes a quantity lookup in database table \fBtable\fR (which defaults to
the products database), with a set of comma-separated fields, looked
up by the optional \fBkey\fR. (Key defaults to the item code, of course).
If ranges are specified with .., each column in the sequence will be
used; Therefore
.Sp
.Vb 1
\& pricing:p1,p2,p3,p4,p5,p10:
.Ve
is the same as
.Sp
.Vb 1
\& pricing:p1..p5,p10:
.Ve
Leading non-digits are stripped, and the item quantity is compared
with the numerical portion of the column name. The price is set to the
value of the database column (numeric portion) that is at least equal
to it but doesn't yet reach the next break.
.Sp
\&\s-1WARNING:\s0 If the field at the appropriate quantity level is blank, a
zero cost will be returned from the atom. It is important to have all
columns populated.
.Ip "==attribute:table*:column*:key*" 4
.IX Item "==attribute:table*:column*:key*"
Does an attribute-based adjustment. The attribute is looked up in the
database \fBtable\fR, with the optional \fBcolumn\fR defaulting to the same
name as the \fIvalue\fR of the \fBattribute\fR. If the column is not left
blank, the \fIkey\fR is set to the \fIvalue\fR of the \fBattribute\fR if blank.
.Ip "& \s-1CODE\s0" 4
.IX Item "& CODE"
The leading & sign is stripped and the code is passed to the
equivalent of a [calc] tag. No Interchange tags can be used, but
the &tag_data routine is available, the current value of the price and
quantity are available as \f(CW$s\fR, and the current item (code, quantity,
price, and any attributes) are available as \f(CW$item\fR, all forced to
the package Vend::Interpolate. That means that in a UserTag:
.Sp
.Vb 4
\& $Vend::Interpolate::item is the current item
\& $Vend::Interpolate::item->{code} gives key for current item
\& $Vend::Interpolate::item->{size} gives size for current item (if there)
\& $Vend::Interpolate::item->{mv_ib} gives database ordered from
.Ve
.Ip "[valid Interchange tags]" 4
.IX Item "[valid Interchange tags]"
If the settor begins with a square bracket ([) or underscore, it is
parsed for Interchange tags with variable substitution (but no Locale
substitution). You may define a price in a \fIVariable\fR in this
fashion. The string is re-submitted as an atom, so it may yield yet
another settor.
.Ip "$" 4
Tells Interchange to look in the mv_price attribute of the shopping
cart, and apply that price as the final price, if it exists. The
attribute must be a numerical value.
.Ip ">>word" 4
.IX Item ">>word"
Tells the routine to return word directly as the result. This is
not useful in pricing, as it will evaluate to zero. But when
CommonAdjust is used for shipping, it is a way of re-directing
shipping modes.
.Ip "word" 4
.IX Item "word"
The value of word, which must not match any of the other settors,
is available as a key for the next lookup (only). If the next settor
is a database lookup, and it contains a dollar sign ($) the word
will be substituted; i.e. table:column:$ becomes
table:column:word.
.Ip "( settor )" 4
.IX Item "( settor )"
The value returned by settor will be used as a key for the next
lookup, as above.
.Sh "CommonAdjust Examples"
.IX Subsection "CommonAdjust Examples"
Most examples below use an outboard database table named \fBpricing\fR,
but any valid table including the \fBproducts\fR table can be used. We
will refer to this \fBpricing\fR table:
.PP
.Vb 4
\& code common q1 q5 q10 XL S red
\& 99-102 10 9 8 1 -0.50 0.75
\& 00-343 2
\& red 0.75
.Ve
The simplest case is a straight lookup on an attribute; \fIsize\fR in
this case.
.PP
.Vb 1
\& 10.00, ==size:pricing
.Ve
With this value in the price field, a base price of 10.00 will be
adjusted with the value of the \fIsize\fR attribute. If size for the item
99\-102 is set to \s-1XL\s0 then 1.00 will be added for a total price of
11.00; if it is S then .50 will be subtracted for a total price of
9.50; for any other value of \fIsize\fR no further adjustment would be
made. 00\-343 would be adjusted up 2.00 only for \fI\s-1XL\s0\fR.
.PP
.Vb 1
\& 10.00, ==size:pricing, ==color:pricing
.Ve
This is the same as above, except both size and color are adjusted
for. A color value of red for item code 99\-102 would add 0.75 to the
price. For 00\-343 it would have no effect.
.PP
.Vb 1
\& 10.00, ==size:pricing, ==color:pricing:common
.Ve
Here price is set based on a common column, keyed by the value of the
color attribute. Any item with a color value of red would have 0.75
added to the base price.
.PP
.Vb 1
\& pricing:q1,q5,q10:, ;10.00, ==size:pricing, ==color:pricing:common
.Ve
Here is a quantity price lookup, with a fallback price setting. If
there is a valid price found at the quantity of 1, 5, or 10, depending
on item quantity, then it will be used. The fallback of 10.00 only
applies if no non-zero/non-blank price was found at the quantity
lookup. In either case, size/color adjustment is applied.
.PP
.Vb 1
\& pricing:q1,q5,q10:, ;10.00 ==size:pricing, ==color:pricing:common
.Ve
Removing the comma from the end of the fallback string stops
color/size lookup if it reaches that point. If a quantity price was
found, then size and color are chained.
.PP
.Vb 1
\& pricing:q1,q5,q10:, ;products:list_price, ==size:pricing, ==color:pricing
.Ve
The value of the database column list_price is used as a fallback
instead of the fixed 10.00 value. The above value might be a nice one
to use as the default for a typical retail catalog that has items with
colors and sizes.
.Sh "PriceBreaks, discounts, and PriceAdjustment"
.IX Subsection "PriceBreaks, discounts, and PriceAdjustment"
There are several ways that Interchange can modify the price of a
product during normal catalog operation. Several of them require that
the \fIpricing.asc\fR file be present, and that you define a pricing
database. You do that by placing the following directive in
\&\fIcatalog.cfg\fR:
.PP
.Vb 1
\& Database pricing pricing.asc 1
.Ve
\&\s-1NOTE:\s0 PriceAdjustment is slightly deprecated by CommonAdjust, but will
remain in use at least through the end of Version 3 of Interchange.
.PP
Configurable directives and tags with regard to pricing:
.Ip "\(bu" 4
Quantity price breaks are configured by means of the \fIPriceBreaks\fR
and \fIMixMatch\fR directives. They require a field named specifically
price in the pricing database. The \fBprice\fR field contains a
space-separated list of prices that correspond to the quantity levels
defined in the \fIPriceBreaks\fR directive. If quantity is to be applied
to all items in the shopping cart (as opposed to quantity of just that
item) then the \fIMixMatch\fR directive should be set to \fBYes\fR.
.Ip "\(bu" 4
Individual line-item prices can be adjusted according to the value of
their attributes. See \fIPriceAdjustment\fR and \fICommonAdjust\fR. The
pricing database \fBmust\fR be defined unless you define the
\&\fICommonAdjust\fR behavior.
.Ip "\(bu" 4
Product discounts for individual products, specific product codes, all
products, or the entire order can be configured with the [discount
\&...] tag. Discounts are applied on a per-user basis \*(-- you can gate
the discount based on membership in a club or other arbitrary means.
See \fIProduct Discounts\fR.
.PP
For example, if you decided to adjust the price of T-shirt part number
99\-102 up 1.00 when the size is extra large and down 1.00 when the
size is small, you would have the following directives defined in
:
.PP
.Vb 3
\& Database pricing pricing.asc 1
\& UseModifier size
\& PriceAdjustment size
.Ve
To enable automatic modifier handling, you define a size field in
products.txt:
.PP
.Vb 2
\& code description price size
\& 99-102 T-Shirt 10.00 S=Small, M=Medium, L=Large*, XL=Extra Large
.Ve
You would place the proper tag within your [item-list] on the
shopping-basket or order page:
.PP
.Vb 1
\& [item-accessories size]
.Ve
In the pricing.asc database source, you would need:
.PP
.Vb 2
\& code S XL
\& 99-102 -1.00 1.00
.Ve
If you want to assign a price based on the option, precede the number
with an equals sign:
.PP
.Vb 2
\& code S M L XL
\& 99-102 =9.00 =10 =10 =11
.Ve
\&\s-1IMPORTANT\s0 \s-1NOTE:\s0 Price adjustments occur \s-1AFTER\s0 quantity price breaks,
so the above would negate anything set with the \fIPriceBreaks\fR
directive/option.
.PP
Numbers that begin with an equals sign (=) are used as absolute
prices and are \fIinterpolated for Interchange tags first\fR, so you can
use subroutines to set the price. To facilitate coordination with the
subroutine, the session variables item_code and item_quantity
are set to the code and quantity of the item being evaluated. They
would be accessed in a global subroutine with
\&\f(CW$Vend::Session\fR->{item_code} and
\&\f(CW$Vend::Session\fR->{item_quantity}.
.PP
The pricing information must always come from a database because of
security.
.Sh "Item Attributes"
.IX Subsection "Item Attributes"
Interchange allows item attributes to be set for each ordered item.
This allows a size, color, or other modifier to be attached to a
common part number. If multiple attributes are set, then they should
be separated by commas. Previous attribute values can be saved by
means of a hidden field on a form, and multiple attributes for each
item can be \fIstacked\fR on top of each other.
.PP
The configuration file directive \fIUseModifier\fR is used to set the
name of the modifier or modifiers. For example
.PP
.Vb 1
\& UseModifier size,color
.Ve
will attach both a size and color attribute to each item code that is
ordered.
.PP
\&\fB\s-1IMPORTANT\s0 \s-1NOTE:\s0\fR You may not use the following names for attributes:
.PP
.Vb 1
\& item group quantity code mv_ib mv_mi mv_si
.Ve
You can also set it in scratch with the mv_UseModifier scratch
variable \*(-- [set mv_UseModifier]size color[/set] has the same
effect as above. This allows multiple options to be set for products.
Whichever one is in effect at order time will be used. Be careful, you
cannot set it more than once on the same page. Setting the
mv_separate_items or global directive \fISeparateItems\fR places each
ordered item on a separate line, simplifying attribute handling. The
scratch setting for mv_separate_items has the same effect.
.PP
The modifier value is accessed in the [item-list] loop with the
[item-modifier attribute] tag, and form input fields are placed
with the [modifier-name attribute] tag. This is similar to the way
that quantity is handled, except that attributes can be \*(L"stacked\*(R" by
setting multiple values in an input form.
.PP
You cannot define a modifier name of \fIcode\fR or \fIquantity\fR, as they
are already used. You must be sure that no fields in your forms have
digits appended to their names if the variable is the same name as the
attribute name you select, as the [modifier-name size] variables
will be placed in the user session as the form variables size0, size1,
size2, etc.
.PP
You can use the [loop arg=\*(L"item item item\*(R"] list to reference
multiple display or selection fields for modifiers, or you can use the
built-in [PREFIX-accessories ...] tags available in most
Interchange list operations. The modifier value can then be used to
select data from an arbitrary database for attribute selection and
display.
.PP
Below is a fragment from a shopping basket display form which shows a
selectable size with \*(L"sticky\*(R" setting. Note that this would always be
contained within the [item_list] [/item-list] pair.
.PP
.Vb 6
\&
\& S
\& M
\& L
\& XL
\&
.Ve
It could just as easily be done with a radio button group combined
with the [checked ...] tag.
.PP
Interchange will automatically generate the above select box when the
[accessories size] or [item-accessories size] tags are
called. They have the syntax:
.PP
.Vb 1
\& [item_accessories attribute*, type*, field*, database*, name*, outboard*]
.Ve
.Vb 1
\& [accessories code attribute*, type*, field*, database*, name*, outboard*]
.Ve
.Ip "code" 4
.IX Item "code"
Not needed for item-accessories, this is the product code of the item
to reference.
.Ip "attribute" 4
.IX Item "attribute"
The item attribute as specified in the UseModifier configuration
directive. Typical are size or color.
.Ip "type" 4
.IX Item "type"
The action to be taken. One of:
.Sp
.Vb 2
\& select Builds a dropdown menu for the attribute.
\& NOTE: This is the default.
.Ve
.Vb 3
\& multiple Builds a multiple dropdown menu for the
\& attribute. The size is equal to the number of
\& option choices.
.Ve
.Vb 1
\& display Shows the label text for *only the selected option*.
.Ve
.Vb 1
\& show Shows the option choices (no labels) for the option.
.Ve
.Vb 2
\& radio Builds a radio box group for the item, with spaces
\& separating the elements.
.Ve
.Vb 2
\& radio nbsp Builds a radio box group for the item, with
\& separating the elements.
.Ve
.Vb 4
\& radio left n Builds a radio box group for the item, inside a
\& table, with the checkbox on the left side. If "n"
\& is present and is a digit from 2 to 9, it will align
\& the options in that many columns.
.Ve
.Vb 4
\& radio right n Builds a radio box group for the item, inside a
\& table, with the checkbox on the right side. If "n"
\& is present and is a digit from 2 to 9, it will align
\& the options in that many columns.
.Ve
.Vb 2
\& check Builds a checkbox group for the item, with spaces
\& separating the elements.
.Ve
.Vb 2
\& check nbsp Builds a checkbox group for the item, with
\& separating the elements.
.Ve
.Vb 4
\& check left n Builds a checkbox group for the item, inside a
\& table, with the checkbox on the left side. If "n"
\& is present and is a digit from 2 to 9, it will align
\& the options in that many columns.
.Ve
.Vb 4
\& check right n Builds a checkbox group for the item, inside a
\& table, with the checkbox on the right side. If "n"
\& is present and is a digit from 2 to 9, it will align
\& the options in that many columns.
.Ve
The default is 'select', which builds an \s-1HTML\s0 select form entry for
the attribute. Also recognized is 'multiple', which generates a
multiple-selection drop down list, 'show', which shows the list of
possible attributes, and 'display', which shows the label text for the
selected option only.
.Ip "field" 4
.IX Item "field"
The database field name to be used to build the entry (usually a field
in the products database). Defaults to a field named the same as the
attribute.
.Ip "database" 4
.IX Item "database"
The database to find \fBfield\fR in, defaults to the first products file
where the item code is found.
.Ip "name" 4
.IX Item "name"
Name of the form variable to use if a form is being built. Defaults to
mv_order_\fBattribute\fR \*(-- i.e. if the attribute is \fBsize\fR, the form
variable will be named \fBmv_order_size\fR.
.Ip "outboard" 4
.IX Item "outboard"
If calling the item-accessories tag, and you wish to select from an
outboard database, you can pass the key to use to find the accessory
data.
.PP
When called with an attribute, the database is consulted and looks for
a comma-separated list of attribute options. They take the form:
.PP
.Vb 1
\& name=Label Text, name=Label Text*
.Ve
The label text is optional \*(-- if none is given, the \fBname\fR will be
used.
.PP
If an asterisk is the last character of the label text, the item is
the default selection. If no default is specified, the first will be
the default. An example:
.PP
.Vb 1
\& [item_accessories color]
.Ve
This will search the product database for a field named \*(L"color\*(R". If an
entry \*(L"beige=Almond, gold=Harvest Gold, White*, green=Avocado\*(R" is
found, a select box like this will be built:
.PP
.Vb 6
\&
\& Almond
\& Harvest Gold
\& White
\& Avocado
\&
.Ve
In combination with the mv_order_item and mv_order_quantity
variables this can be used to allow entry of an attribute at time of
order.
.PP
If used in an item list, and the user has changed the value, the
generated select box will automatically retain the current value the
user has selected.
.PP
The value can then be displayed with [item-modifier size] on the
order report, order receipt, or any other page containing an
[item-list].
.Sh "Product Discounts"
.IX Subsection "Product Discounts"
Product discounts can be set upon display of any page. The discounts
apply only to the customer receiving them, and are of one of three
types:
.PP
.Vb 6
\& 1. A discount for one particular item code (key is the item-code)
\& 2. A discount applying to all item codes (key is ALL_ITEMS)
\& 3. A discount for an individual line item (set the mv_discount attribute
\& with embedded Perl)
\& 4. A discount applied after all items are totaled
\& (key is ENTIRE_ORDER)
.Ve
The discounts are specified via a formula. The formula is scanned for
the variables \f(CW$q\fR and \f(CW$s\fR, which are substituted for with the item
\&\fIquantity\fR and \fIsubtotal\fR respectively. The variable \f(CW$s\fR is saved
between iterations, so the discounts are cumulative. In the case of
the item and all items discount, the formula must evaluate to a new
subtotal for all items \fIof that code\fR that are ordered. The discount
for the entire order is applied to the entire order, and would
normally be a monetary amount to subtract or a flat percentage
discount.
.PP
Discounts are applied to the effective price of the product, including
any quantity discounts or price adjustments.
.PP
To apply a straight 20% discount to all items:
.PP
.Vb 1
\& [discount ALL_ITEMS] $s * .8 [/discount]
.Ve
or with named attributes:
.PP
.Vb 1
\& [discount code=ALL_ITEMS] $s * .8 [/discount]
.Ve
To take 25% off of only item 00\-342:
.PP
.Vb 1
\& [discount 00-342] $s * .75 [/discount]
.Ve
To subtract \f(CW$5\fR.00 from the customer's order:
.PP
.Vb 1
\& [discount ENTIRE_ORDER] $s - 5 [/discount]
.Ve
To reset a discount, set it to the empty string:
.PP
.Vb 1
\& [discount ALL_ITEMS][/discount]
.Ve
Perl code can be used to apply the discounts, and variables are saved
between items and are shared with the [calc] tag. This example
gives 10% off if two items are ordered, with 5% more for each
additional up to a maximum of 30% discount:
.PP
.Vb 6
\& [calc]
\& [item-list]
\& $totalq{"[item-code]"} += [item-quantity];
\& [/item-list]
\& return '';
\& [/calc]
.Ve
.Vb 7
\& [item-list]
\& [discount code="[item-code]"]
\& return ($s) if $totalq{"[item-code]"} == 1;
\& return ($s * .70) if $totalq{"[item-code]"} > 6;
\& return ($s * ( 1 - 0.05 * $totalq{"[item-code]"} ));
\& [/discount]
\& [/item-list]
.Ve
Here is an example of a special discount for item code 00\-343 which
prices the \fIsecond\fR one ordered at 1 cent:
.PP
.Vb 7
\& [discount 00-343]
\& return $s if $q == 1;
\& my $p = $s/$q;
\& my $t = ($q - 1) * $p;
\& $t .= 0.01;
\& return $t;
\& [/discount]
.Ve
If you want to display the discount amount, use the [item-discount]
tag.
.PP
.Vb 3
\& [item-list]
\& Discount for [item-code]: [item-discount]
\& [/item-list]
.Ve
Finally, if you want to display the discounted subtotal, you need to
use the [calc] capability:
.PP
.Vb 5
\& [item-list]
\& Discounted subtotal for [item-code]: [currency][calc]
\& [item-price] * [item-quantity]
\& [/calc][/currency]
\& [/item-list]
.Ve
.SH "Taxing"
.IX Header "Taxing"
Interchange allows taxing in a number of ways.
.Ip "Simple salestax.asc table" 4
.IX Item "Simple salestax.asc table"
.PP
The \fISalesTax\fR directive is set to a form field or fields for user
input, and those form fields are used look up the tax rate in
salestax.asc.
.Ip "Fly tax" 4
.IX Item "Fly tax"
.PP
Another simple tax method. A series of Interchange Variable settings
are read to develop a salestax rate for one or a few localities,
usually a state in the \s-1US\s0.
.Ip "Salestax multi \*(-- \s-1VAT\s0 taxing" 4
.IX Item "Salestax multi VAT taxing"
.PP
The \fIcountry\fR and \fIstate\fR tables are used to develop complex \s-1VAT\s0 or
salestax rate calculations based on country and state, possibly with
different rates based on product type.
.Ip "Levies \*(-- multiple levels of tax" 4
.IX Item "Levies multiple levels of tax"
.PP
Using the \fILevies\fR setting and the \fILevy\fR structure, any or all of
the above methods is used to implement one or more taxes.
.Sh "Sales Tax \*(-- simple salestax.asc table"
.IX Subsection "Sales Tax simple salestax.asc table"
Interchange allows calculation of sales tax on a straight percentage
basis, with certain items allowed to be tax-exempt. To enable this
feature, the directive \fISalesTax\fR is initialized with the name of a
field (or fields) on the order form. Commonly, this is zipcode and/or
state:
.PP
.Vb 1
\& SalesTax zip,state
.Ve
This being done, Interchange assumes the presence of a file
\&\fIsalestax.asc\fR, which contains a database with the percentages. Each
line of \fIsalestax.asc\fR should be a code (again, usually a five-digit
zip or a two letter state) followed by a tab, then a percentage.
Example:
.PP
.Vb 8
\& DEFAULT 0.0
\& 45056 .0525
\& 61821 .0725
\& 61801 .075
\& IL .0625
\& OH .0525
\& VAT .15
\& WA .08
.Ve
Based on the user's entry of information in the order form,
Interchange will look up (for our example SalesTax directive) first
the zip, then the state, and apply the percentage to the \s-1SUBTOTAL\s0 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
\&\fITaxShipping\fR 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 \s-1DEFAULT\s0 is applied \*(-- it is normally
zero.
.PP
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
Interchange format \*(-- but some systems are rather convoluted, and it
will be well to check and see if the program can export to a flat
\&\s-1ASCII\s0 file format based on zip code.
.PP
If some items are not taxable, then you must set up a field in your
database which indicates that. You then place the \fBname\fR of that
field in the \fINonTaxableField\fR 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.
.PP
If your state taxes shipping, use the \fITaxShipping\fR directive. Utah
and Nevada are known to tax shipping \*(-- there may be others.
.PP
If you want to set a fixed tax for all orders, as might occur for \s-1VAT\s0
in some countries, just set the \fISalesTax\fR directive to a value like
tax_code, and define a variable in the user session to reflect the
proper entry in the salestax.asc file. To set it to 15% with the
above salestax.asc file, you would put in a form:
.PP
.Vb 1
\&
.Ve
or to do it without submitting a form:
.PP
.Vb 1
\& [perl] $Values->{tax_code} = 'VAT'; return; [/perl]
.Ve
.Sh "Fly tax"
.IX Subsection "Fly tax"
The \fI[fly-tax]\fR tag is placed in the \s-1DEFAULT\s0 setting of salestax.asc,
and the variables \s-1TAXAREA\s0, \s-1TAXRATE\s0, and \s-1TAXSHIPPING\s0 are used
to build the rates.
.Ip "\s-1TAXAREA\s0" 4
.IX Item "TAXAREA"
.PP
A space-separated or comma-seperated list of states to apply tax to.
Not needed for anything in the calculation, it is used to build the \s-1UI\s0
list of states to tax.
.Ip "\s-1TAXRATE\s0" 4
.IX Item "TAXRATE"
.PP
An Interchange accessory-list style of value, with the format
.PP
.Vb 1
\& XX=N.NN, XX=N.NN
.Ve
where \s-1XX\s0 is the two-letter state code and N.NN is the tax rate in
percent. To apply a tax of 7.25% for Illinois and 5.5% for Nevada, you
would use:
.PP
IL=7.25, NV=5.5
.Ip "\s-1TAXSHIPPING\s0" 4
.IX Item "TAXSHIPPING"
.PP
A space- or comma-separated list of states where shipping is taxed.
For the above example, if Nevada taxed shipping and Illinois did not,
you would make \s-1TAXSHIPPING\s0 equal to \*(L"\s-1NV\s0\*(R".
.Ip "The Salestax Directive" 4
.IX Item "The Salestax Directive"
.PP
To set the field that is used for the state code, you use the standard
Interchange \fISalesTax\fR directive. It would almost always be set to
state.
.if n .Sh "Salestax ""multi"" \*(-- \s-1VAT\s0 taxing"
.el .Sh "Salestax ``multi'' \*(-- \s-1VAT\s0 taxing"
.IX Subsection "Salestax "multi VAT taxing"
If the SalesTax directive is set to \*(L"multi\*(R", then the type of tax is
read from the \fIcountry\fR table. To see the tax type in force for the
\&\s-1UK\s0, you can place in a page:
.PP
.Vb 1
\& [data table=country col=tax key="UK"].
.Ve
.Ip "" 4
\&\s-1NOTE:\s0 We mention the \*(L"country\*(R" table above. In actual practice, most
everything is configurable for variable name and field name via
different Variable settings. They are:
.Sp
.Vb 1
\& MV_COUNTRY_TABLE Table for country info (default "country")
.Ve
.PP
Below, we refer to the tables, columns, and fields by their default
names.
.PP
The first lookup is done in table country based on the user input
of country (i.e. [value country]). The tax field is read and
one of the following is done:
.PP
1. If no string is found, tax returns 0.
.PP
2. If string \*(L"simple:XX\*(R" is found, uses [fly-tax] with the area
specifed in \s-1XX\s0.
.PP
3. If string \*(L"state\*(R" is found, does a re-lookup with
.PP
.Vb 1
\& select tax from state where country = country and state = state
.Ve
and value is applied as below.
.PP
4. If just digits are found, rate applied directly \*(-- i.e. \*(L"0.05\*(R"
.PP
5. If N.NN% is found, applied as percentage.
.PP
6. If category = N.NN%, default = N.NN% is found, the
tax_category field in the \fIproducts\fR table is used to determine
tax basis. If no tax_category is found for the product, default
rate is used.
.PP
This product data
.PP
.Vb 3
\& sku price tax_category
\& os28003 10.00 tools
\& os28004 20.00 food
.Ve
with this country and state data:
.PP
.Vb 3
\& code name tax
\& US U.S.A. state
\& JP Japan tools=10%, default=15%
.Ve
.Vb 4
\& code country state name tax
\& 0001 US IL Illinois 6.5%
\& 0002 US OH Ohio default = 5.5%, food = 1%
\& 0003 US AZ Arizona
.Ve
Will yield tax for one each of os28003 and os28004 of:
.PP
.Vb 4
\& Japan $4.00
\& US/IL $1.95
\& US/OH $0.75
\& US/AZ $0.00
.Ve
.SH "THE CHECKOUT PROCESS"
.IX Header "THE CHECKOUT PROCESS"
.Sh "Advanced Multi-level Order Pages"
.IX Subsection "Advanced Multi-level Order Pages"
An unlimited number of order checking profiles can be defined with the
\&\fIOrderProfile\fR directive, or by defining order profiles in scratch
variables. This allows a multi-level ordering process, with checking
for format and validity at every stage.
.PP
To custom-configure the error message, place it after the format check
requirement.
.PP
Specifications take the form of an order page variable (like name or
address), followed by an equals sign and one of five check types:
.Ip "required" 4
.IX Item "required"
A non-blank value is required
.Ip "mandatory" 4
.IX Item "mandatory"
Must be non-blank, and must have been specified on this form, not a
saved value from a previous form
.Ip "phone" 4
.IX Item "phone"
The field must look like a phone number, by a very loose specification
allowing numbers from all countries
.Ip "phone_us" 4
.IX Item "phone_us"
Must have \s-1US\s0 phone number formatting, with area code
.Ip "state" 4
.IX Item "state"
Must be a \s-1US\s0 state, including \s-1DC\s0 and Puerto Rico.
.Ip "province" 4
.IX Item "province"
Must be a Canadian province or pre-1997 territory.
.Ip "state_province" 4
.IX Item "state_province"
Must be a \s-1US\s0 state or Canadian province.
.Ip "zip" 4
.IX Item "zip"
Must have \s-1US\s0 postal code formatting, with optional \s-1ZIP+4\s0. Also called
by the alias us_postcode.
.Ip "ca_postcode" 4
.IX Item "ca_postcode"
Must have Canadian postal code formatting. Checks for a valid first
letter.
.Ip "postcode" 4
.IX Item "postcode"
Must have Canadian or \s-1US\s0 postal code formatting.
.Ip "true" 4
.IX Item "true"
Field begins with \fBy\fR, \fB1\fR, or \fBt\fR (Yes, 1, or True) \- not case
sensitive
.Ip "false" 4
.IX Item "false"
Field begins with \fBn\fR, \fB0\fR, or \fBf\fR (No, 0, or False) \- not case
sensitive
.Ip "email" 4
.IX Item "email"
Rudimentary email address check, must have an '@' sign, a name, and a
minimal domain
.Ip "regex" 4
.IX Item "regex"
One or more regular expressions (space-separated) to check against. To
check that all submissions of the \*(L"foo\*(R" variable have \*(L"bar\*(R" at the
beginning, do:
.Sp
.Vb 1
\& foo=regex ^bar
.Ve
You can add an error message by putting it in quotes at the end:
.Sp
.Vb 1
\& foo=regex ^bar "You must have bar at the beginning of this"
.Ve
You can require that the value \fBnot\fR match the regex by preceding the
regex with a \fB!\fR character (and no space afterwards):
.Sp
.Vb 1
\& foo=regex !^bar "You may not have bar at the beginning!"
.Ve
.Ip "length" 4
.IX Item "length"
A range of lengths you want the input to be:
.Sp
.Vb 1
\& foo=length 4-10
.Ve
That will require foo be from 4 to 10 characters long.
.Ip "unique" 4
.IX Item "unique"
Tests to see that the value would be a unique key in a table:
.Sp
.Vb 1
\& foo=unique userdb Sorry, that username is already taken
.Ve
.Ip "filter" 4
.IX Item "filter"
Runs the value through an Interchange filter and checks that the
returned value is equal to the original value.
.Sp
.Vb 1
\& foo=filter entities Sorry, no HTML allowed
.Ve
To check for all lower-case characters:
.Sp
.Vb 1
\& foo=filter lower Sorry, no uppercase characters
.Ve
.PP
Also, there are pragmas that can be used to change behavior:
.Ip "&charge" 4
.IX Item "&charge"
Perform a real-time charge operation. If set to any value but
\&\*(L"custom\*(R", it will use Interchange's CyberCash routines. To set to
something else, use the value \*(L"custom \s-1ROUTINE\s0\*(R". The \s-1ROUTINE\s0 should be
a GlobalSub which will cause the charge operation to occur \*(-- if it
returns non-blank, non-zero the profile will have succeeded. If it
returns 0 or undef or blank, the profile will return failure.
.Ip "&credit_card" 4
.IX Item "&credit_card"
Checks the mv_credit_card_* variables for validity. If set to
\&\*(L"standard\*(R", it will use Interchange's encrypt_standard_cc routines.
This destroys the \s-1CGI\s0 value of mv_credit_card_number \*(-- if you don't
want that to happen (perhaps to save it for sending to CyberCash) then
add the word keep on the end.
.Sp
Example:
.Sp
.Vb 2
\& # Checks credit card number and destroys number after encryption
\& # The charge operation can never work
.Ve
.Vb 2
\& &credit_card=standard
\& &charge=custom authorizenet
.Ve
.Vb 2
\& # Checks credit card number and keeps number after encryption
\& # The charge operation can now work
.Ve
.Vb 2
\& &credit_card=standard keep
\& &charge=custom authorizenet
.Ve
You can supply your own check routine with a GlobalSub:
.Sp
.Vb 1
\& &credit_card=check_cc
.Ve
The GlobalSub check_cc will be used to check and encrypt the credit
card number, and its return value will be used to determine profile
success.
.Ip "&fail" 4
.IX Item "&fail"
Sets the mv_failpage value.
.Sp
.Vb 1
\& &fail=page4
.Ve
If the submit process succeeds, the user will be sent to the page
page4.
.Ip "&fatal" 4
.IX Item "&fatal"
Set to '&fatal=yes' if an error should generate the error page.
.Ip "&final" 4
.IX Item "&final"
Set to '&final=yes' if a successful check should cause the order to be
placed.
.Ip "&update" 4
.IX Item "&update"
Set to '&update=yes' if a successful check should cause the variable
to be copied from the \s-1CGI\s0 space to the Values space. This is like
[update values] except only for that variable.
.Sp
This is typically used when using a mv_form_profile check so that a
failing check will not cause all values to be reset to their former
state upon returning to the form.
.Ip "&return" 4
.IX Item "&return"
Causes profile processing to terminate with either a success or
failure depending on what follows. If it is non-blank and non-zero,
the profile succeeds.
.Sp
.Vb 2
\& # Success :)
\& &return 1
.Ve
.Vb 2
\& # Failure :\e
\& &return 0
.Ve
Will ignore the &fatal pragma, but &final is still in effect if set.
.Ip "&set" 4
.IX Item "&set"
Set a user session variable to a value, i.e. &set=mv_email [value
email]. This will not cause failure if blank or zero.
.Ip "&setcheck" 4
.IX Item "&setcheck"
Set a user session variable to a value, i.e. &set=mv_email [value
email]. This \fBwill\fR cause failure if set to a blank or zero. It is
usually placed at the end after a &fatal pragma would have caused the
process to stop if there was an error \*(-- can also be used to determine
pass/fail based on a derived value, as it will cause failure if it
evaluates to zero or a blank value.
.Ip "&success" 4
.IX Item "&success"
Sets the mv_successpage value. Example:
.Sp
.Vb 1
\& &success=page5
.Ve
If the submit process succeeds, the user will be sent to the page
page5.
.PP
As an added measure of control, the specification is evaluated for the
special Interchange tags to provide conditional setting of order
parameters. With the [perl] [/perl] capability, quite complex
checks can be done. Also, the name of the page to be displayed on an
error can be set in the mv_failpage variable.
.PP
The following file specifies a simple check of formatted parameters:
.PP
.Vb 11
\& name=required You must give us your name.
\& address=required Oops! No address.
\& city=required
\& state=required
\& zip=required
\& email=required
\& phone_day=phone_us XXX-XXX-XXXX phone-number for US or Canada
\& &fatal=yes
\& email=email Email address missing the domain?
\& &set=mv_email [value email]
\& &set=mv_successpage ord/shipping
.Ve
The profile above only performs the &set directives if all of the
previous checks have passed \*(-- the &fatal=yes will stop processing
after the check of the email address if any of the previous checks
failed.
.PP
If you want to place multiple order profiles in the same file,
separate them with _\|_END_\|_, which must be on a line by itself.
.PP
User-defined check routines can be defined in a GlobalSub:
.PP
.Vb 9
\& GlobalSub <{'values'} hash
\& # $var is the passed name of the variable
\& # $val is current value of checked variable
\& my($ref, $var, $val) = @_;
.Ve
.Vb 11
\& if ($ref->{country} =~ /^(PT|portugal)$/i) {
\& return $val =~ /^\ed\ed\ed\ed$/ ?
\& (1, $var, '') : (undef, $var, "not a Portugese postal code");
\& }
\& else {
\& return (1, $var, '');
\& }
\& }
\& }
\& }
\& EOF
.Ve
Now you can specify in an order profile:
.PP
.Vb 1
\& postcode=pt_postcode
.Ve
Very elaborate checks are possible. There must be an underscore
preceding the routine name. The return value of the subroutine should
be a three-element array, consisting of:
.Ip "1." 4
the pass/fail ('1' or 'undef') status of the check;
.Ip "2." 4
the name of the variable which was checked;
.Ip "3." 4
a standard error message for the failure, in case a custom one has not
been specified in the order profile.
.PP
The latter two elements are used by the [error] tag for on-screen
display of form errors. The checkout page of the Foundation demo
includes examples of this.
.Sh "Simple Order Report File"
.IX Subsection "Simple Order Report File"
The simple order report file, \*(L"report\*(R", defines the layout of the
order report which gets mailed on the completion of the order. For
example,
.PP
.Vb 1
\& Order Date: $date
.Ve
.Vb 2
\& Name: $name
\& Email address: $email
.Ve
.Vb 3
\& Shipping address: $addr
\& Town, State, Zip: $town, $state $zip
\& Country: $country
.Ve
Any input field from the order page can be included using the dollar
sign notation.
.PP
Interchange defines some values for use in the search form \*(-- they
begin with mv_ and are automatically ignored.
.Sh "Fully-configurable Order Reports"
.IX Subsection "Fully-configurable Order Reports"
You can specify a fully-configurable order report by setting the
hidden field \*(L"mv_order_report\*(R" to a legal Interchange page. This page
will be interpolated with all Interchange 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.
.PP
You could if you wish include \s-1HTML\s0 in the file, which will be
interpreted by many mailers, but you can choose to use standard \s-1ASCII\s0
format. An example report is provided in the demo file
.
.Sh "Order Receipts"
.IX Subsection "Order Receipts"
The file can of course be configured with all Interchange tags, and
will be interpolated for the ordered items before they are deleted
from the user session. You can set the default receipt with the
receipt key in SpecialPage. If using order \fIRoute\fRs, as in the
foundation demo, you set it with the receipt key to Route.
.Sh "The Order Counter"
.IX Subsection "The Order Counter"
An order counter can be enabled if the \fIOrderCounter\fR 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.
.PP
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 Interchange. It is included with the distribution.
.Sh "Customer Input Fields"
.IX Subsection "Customer Input Fields"
On the order (or shopping basket) page, by default order.html, you
will have a number of input fields allowing the customer to enter
information such as their name and address. You can add more fields
simply by putting more input elements on the order.html page, and the
information will automatically be included in the order report. Input
elements should be written in this way:
.PP
.Vb 1
\&
.Ve
Choose a name for this input field such as \*(L"email\*(R" for an email
address. Set the name attribute to the name you have chosen.
.PP
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 var] element, which returns the last value
of an input field. Thus,
.PP
.Vb 1
\& value="[value name]"
.Ve
will evaluate to the name entered on the previous order screen, such
as:
.PP
.Vb 1
\& value="Jane Smith"
.Ve
which will be displayed by the browser.
.PP
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.
.PP
.Vb 1
\& ________________________________________
.Ve
Copyright 2002\-2004 Interchange Development Group. Copyright 2001\-2002
Red Hat, Inc. Freely redistributable under terms of the \s-1GNU\s0 General
Public License. line:
.PP
Interchange + \s-1CVS\s0 \s-1HOWTO\s0
.SH "Introduction"
.IX Header "Introduction"
.Sh "Preamble"
.IX Subsection "Preamble"
Copyright 2001\-2003 Dan Browning . This
document is freely redistributable under terms of the \s-1GNU\s0 General
Public License.
.Sh "Purpose"
.IX Subsection "Purpose"
The purpose of this document is to help others take advantage of \s-1CVS\s0
and Interchange together to increase the quality of their programming,
whether they are sole developers or part of a large team of
programmers, graphic artists, and \s-1HTML\s0 design gurus. Portions of it
apply to general \s-1CVS\s0 setup and use, but it is geared toward the
average developer using Interchange to implement an e-commerce
website.
.Sh "Audience"
.IX Subsection "Audience"
I intend for this document to be useful to those who are not yet
familiar with \s-1CVS\s0 as well as those who are. If you already know how
to setup a pserver then you might just skim chapter 2 (\*(L"Setup \s-1CVS\s0\*(R"),
or skip it all together.
.PP
In addition, I have tried to write at a technical level that would be
on par with what I perceive to be the average Interchange user that
participates on the interchange-users mailing list. It is assumed
that the reader can and already has setup Interchange and the template
catalog (e.g. Foundation) is working correctly.
.Sh "Contact the author"
.IX Subsection "Contact the author"
If you find any spelling errors, technical slip-ups, mistakes,
subliminal messages, or if you wish to send feedback, critique,
remarks, comments, or if you wish to contribute examples, instructions
for alternative platforms, chapters, or other material, please do so.
.PP
The preferred method of submitting changes is in the form of a context
diff against the \s-1SDF\s0 source file (ic_cvs.sdf). Please address your
correspondence to:
.PP
Dan Browning \fIdan.browning@kavod.com\fR
.Sh "The advantages of using \s-1CVS\s0"
.IX Subsection "The advantages of using CVS"
\&\s-1CVS\s0 is a very useful tool and can help you in your development, no
matter if you are an independant developer or are part of a team of
developers.
.Ip "\(bu" 4
What is \s-1CVS\s0 all about?
.Ip "\(bu" 4
What are its advantages?
.PP
The official \s-1CVS\s0 website (http://www.cvshome.org/new_users.html)
has more detailed answers to these questions, but here are some brief
points of interest.
.Ip "\(bu" 4
Checkout \*(L"historic\*(R" points in time or milestones in a project, for
example when an e-commerce site went \*(L"live\*(R" or before a major branch
in the code.
.Ip "\(bu" 4
Revert to older versions of a file, directory, or an entire website.
.Ip "\(bu" 4
Branching releases. Concurrently develop an unstable development
version as well as fix bugs in the stable production version.
.Ip "\(bu" 4
Multiple developers can work on the same catalog and even the same
file at the same time. (For more information about how multiple
simultaneous writes are merged and conflicts resolved, see the \s-1CVS\s0
docs in the \fIResources\fR Appendix).
.Ip "\(bu" 4
\&\s-1CVS\s0 is better than ftp for file transfer, because it automatically
downloads only changed files, and even then, only the portion of the
file that has changed (using patches).
.Ip "\(bu" 4
\&\s-1CVS\s0 can automatically merge two simultaneous writes to the same file
by different developers.
.Ip "\(bu" 4
Allows one to keep track of the changes that have been made over time
(many release managers repackage \s-1CVS\s0 commit logs into \s-1WHATSNEW\s0,
\&\s-1HISTORY\s0, and/or \s-1NEWS\s0 files).
.Sh "How to use this document"
.IX Subsection "How to use this document"
There are many potential uses of \s-1CVS\s0 as it applies to Interchange. In
fact, there are as many unique ways to use \s-1CVS\s0 as there are unique
developers. This document only covers some of the ways, including
basic and useful techniques to get started using \s-1CVS\s0. For the intents
of the average web developer using \s-1IC\s0 for a B2C e-commerce site, I've
identified a few of the possible uses:
.PP
Simple
.Ip "\(bu" 4
One server
.Ip "\(bu" 4
One catalog
.Ip "\(bu" 4
One \s-1CVS\s0 module
.Ip "\(bu" 4
One branch
.PP
Medium
.Ip "\(bu" 4
One server
.Ip "\(bu" 4
Two catalogs (e.g., one is live, one is development)
.Ip "\(bu" 4
Two \s-1CVS\s0 modules
.Ip "\(bu" 4
Separate development and live branches
.PP
Complex/Custom
.Ip "\(bu" 4
Multiple servers (e.g., developers' servers, staging servers, and live
servers)
.Ip "\(bu" 4
Multiple catalogs
.Ip "\(bu" 4
Multiple \s-1CVS\s0 modules
.Ip "\(bu" 4
Multiple branches
.Ip "\(bu" 4
Custom setup
.PP
This document attempts to cover the simple well, explain many aspects
of the medium, and hopefully give you the background you need if you
decide to setup your own complex development environment.
.SH "Setup CVS"
.IX Header "Setup CVS"
.Sh "Assumptions"
.IX Subsection "Assumptions"
Here are some of the assumptions that I make that apply to various
parts of the rest of this document:
.Ip "\(bu" 4
Red Hat Linux 7.x
.Ip "\(bu" 4
Interchange installed (\s-1RPM\s0 or tarball)
.Ip "\(bu" 4
Default Interchange tarball installation directory paths (adjust for
your environment)
.Ip "\(bu" 4
Template catalog setup and working
.PP
\&\fBNote: \fRI will assume \*(L"foundation\*(R" for the catalog name and directory
paths, but it should be just as easy to use this document with your
own catalog by mentally transposing the names and paths.
.PP
There shouldn't be any reason why you could not do everything I
mention here on other Linux distributions, Unices or Windows (using
cygwin). However, my statements will reflect Red Hat Linux 7.x.
Additionally, Red Hat Linux 6.x is for the most part the same as 7.x,
except for the difference of using inetd instead of xinetd to setup
pserver.
.Sh "Install \s-1CVS\s0"
.IX Subsection "Install CVS"
This is the easy part. For Red Hat Linux systems, download the \s-1CVS\s0
rpms and install them. You can search for rpms for your system using
http://www.rpmfind.net.
.PP
Create the user and group that will administrate the Interchange
repository. For this document, it will be the interch user, (which was
setup during the installation of Interchange). But if you understand
the mechanics of Unix users/groups, then you can use whatever username
and group scheme you prefer. For example, some create a cvs user and
add it to the same group that interchange uses (e.g. interch), or add
the Interchange user and catalog owner to its group or vice-versa.
The integration of Interchange and \s-1CVS\s0 in the latter portion of this
document will require that the \s-1CVS\s0 user can write to the catalog
directory.
.Sh "Create the \s-1CVS\s0 repository directory"
.IX Subsection "Create the CVS repository directory"
You will need to create a repository directory such as
\&\fI/home/interch/rep\fR, which is used here and in the rest of the
document, but it can be any directory you desire, and must be owned by
the cvs user.
.PP
.Vb 1
\& mkdir /home/interch/rep
.Ve
.Sh "Setup environment variables"
.IX Subsection "Setup environment variables"
The \s-1CVSROOT\s0 environment variable can be setup for your user (in
\&\fI~/.bashrc\fR or \fI~/.profile\fR, or for all users in \fI/etc/profile\fR.
.PP
.Vb 1
\& ~/.profile:
.Ve
export CVSROOT=${\s-1HOME\s0}/rep
.PP
\&.cvsrc
.PP
We recommend these default options for \s-1CVS\s0.
.PP
.Vb 1
\& ~/.cvsrc:
.Ve
cvs \-q
diff \-u
update \-Pd
checkout \-P
.PP
This directs \s-1CVS\s0 to (1) automatically compress all data communicated
between you and our server (saving bandwidth), and be quieter; (2)
show context-sensitive diffs; (3) prune empty directories and create
any new directories added to the repository since your checkout; and
(4) prune empty directories during your checkouts.
.PP
\&\fBNote: \fRYou will need to logout/login for the profile changes to take
effect.
.Sh "Initialize the repository"
.IX Subsection "Initialize the repository"
Initialize the repository as the \s-1CVS\s0 user, which is interch for
this document.
.PP
.Vb 1
\& cvs -d /home/interch/rep init
.Ve
.Sh "\s-1CVS\s0 Authentication"
.IX Subsection "CVS Authentication"
Background
.PP
Authentication is done in \s-1CVS\s0 through the \fI$CVSROOT/CVSROOT/passwd\fR
file. It can be easily manipulated through some of the \s-1CVS\s0
administration tools that are available. An alternate authentication
method is ssh, which requires no extra setup on the server side.
.PP
\&\s-1CVS\s0 administration tools
.Ip "\(bu" 4
http://freshmeat.net/projects/cvsadmin/
.Ip "\(bu" 4
http://freshmeat.net/projects/cvspadm/
.PP
I recommend cvsadmin, but there are also a variety of manual methods
that can be used in the absence of such tools, one of which involves
copying the system shadow file and modifying it for use by \s-1CVS\s0. For
more information on this manual method, see the Red Hat \s-1CVS\s0 pserver
setup guide by Michael Amorose
(http://www.michael-amorose.com/cvs/).
.PP
Setup authentication using the cvsadmin tool
.PP
You can find a tarball to install on your system using the above
address, but here is the address of a recent \s-1RPM\s0 package of the
version. This package is intended for Mandrake systems, but is
compatible with Red Hat Linux 7.1:
.Ip "\(bu" 4
ftp://rpmfind.net/linux/Mandrake/9.0/contrib/RPMS/cvsadmin-1.0.2-1mdk.i586.rpm
.PP
After installing, create a password file (\fItouch
\&\f(CI$CVSROOT\fI/CVSROOT/passwd, touch \f(CI$CVSROOT\fI/CVSROOT/users\fR), and execute
\&\f(CW\*(C`cvsadmin add \*(C'\fR.
.Sh "Setup \s-1CVS\s0 modules"
.IX Subsection "Setup CVS modules"
\&\fBNote: \fRFrom this point on, assume that all commands are executed as
the \s-1CVS\s0 user (e.g. interch), unless otherwise specified.
.PP
A module is \s-1CVS\s0 is like the concept of a \*(L"project\*(R", where each module
has its own branches, trees, and other features.
.PP
Add your project to the \fImodules\fR configuration file
.PP
The format of the modules file is explained in detail in the \s-1CVS\s0
documentation, here is the simplest way to use it. First you will
need to checkout your \s-1CVSROOT\s0 directory, then modify and commit the
\&'modules' file.
.PP
cvs co \s-1CVSROOT\s0
cd \s-1CVSROOT\s0
.PP
modules:
.PP
<\s-1TAB\s0>
.PP
The module name can be whatever you want, and the module directory is
what we will create later under /rep. We'll want a module for the
template catalog (foundation). For example:
.PP
.Vb 1
\& foundation foundation
.Ve
Create the module directory
.PP
This is the directory that is referred to in the \fICVSROOT/modules\fR
file we just modified.
.PP
.Vb 1
\& mkdir /rep/foundation
.Ve
.Sh "Setup binary file types"
.IX Subsection "Setup binary file types"
This isn't necessary if you aren't going to manage any binary files
(e.g. if you plan on excluding your images/ directory). But I
recommend including it. The following is an example including many
binary file types (by extension) used in web development.
.PP
.Vb 1
\& /rep/CVSROOT/cvswrappers:
.Ve
*.avi \-k 'b' \-m '\s-1COPY\s0'
*.doc \-k 'b' \-m '\s-1COPY\s0'
*.exe \-k 'b' \-m '\s-1COPY\s0'
*.gif \-k 'b' \-m '\s-1COPY\s0'
*.gz \-k 'b' \-m '\s-1COPY\s0'
*.hqx \-k 'b' \-m '\s-1COPY\s0'
*.jar \-k 'b' \-m '\s-1COPY\s0'
*.jpeg \-k 'b' \-m '\s-1COPY\s0'
*.jpg \-k 'b' \-m '\s-1COPY\s0'
*.mov \-k 'b' \-m '\s-1COPY\s0'
*.mpg \-k 'b' \-m '\s-1COPY\s0'
*.pdf \-k 'b' \-m '\s-1COPY\s0'
*.png \-k 'b' \-m '\s-1COPY\s0'
*.ppt \-k 'b' \-m '\s-1COPY\s0'
*.sit \-k 'b' \-m '\s-1COPY\s0'
*.swf \-k 'b' \-m '\s-1COPY\s0'
*.tar \-k 'b' \-m '\s-1COPY\s0'
*.tgz \-k 'b' \-m '\s-1COPY\s0'
*.tif \-k 'b' \-m '\s-1COPY\s0'
*.tiff \-k 'b' \-m '\s-1COPY\s0'
*.xbm \-k 'b' \-m '\s-1COPY\s0'
*.xls \-k 'b' \-m '\s-1COPY\s0'
*.zip \-k 'b' \-m '\s-1COPY\s0'
.PP
Commit changes
.PP
Remember to commit the changes you made to 'modules' and
\&'cvswrappers'.
.PP
.Vb 1
\& cvs commit -m "Update modules and binary types" modules cvswrappers
.Ve
.Sh "Setup the \s-1CVS\s0 pserver"
.IX Subsection "Setup the CVS pserver"
You will likely need to be root to do this, and there are lots of
guides on the Internet for setting up a \s-1CVS\s0 pserver, hopefully you
wont have any trouble doing it on your particular operating system.
See the \fIResources\fR Appendix for more information.
.PP
Setup pserver in Red Hat Linux 7.x using xinetd.
.PP
For Red Hat Linux 7.x, edit \fI/etc/xinetd.d/cvspserver\fR (create a new
one if none exists). The following works for me, but customization
may be required for your environment (see the next section below for
an inetd-based system example). This also must be done as root.
Remember to substitue /home/interch/rep with your repository directory
below.
.PP
.Vb 2
\& su - root
\&/etc/xinetd.d/cvspserver:
.Ve
service cvspserver
{
disable = no
socket_type = stream
protocol = tcp
wait = no
user = root
server = /usr/bin/cvs
server_args = \-f \-\-allow-root=/home/interch/rep pserver
}
.PP
Now, restart xinetd for the changes to take effect.
.PP
.Vb 1
\& service xinetd restart
.Ve
Setup pserver in inetd-based systems.
.PP
For inetd-based systems such as Red Hat Linux 6.2, make sure that the
following files are setup accordingly.
.PP
.Vb 1
\& /etc/services:
.Ve
cvspserver 2401/tcp
N:/etc/inetd.conf:
.PP
cvspserver stream tcp nowait \e
root /usr/sbin/tcpd /usr/bin/cvs \e
\-\-allow-root=/home/interch/rep pserver
.PP
Testing your pserver
.PP
At this point, you should be able to use a \s-1CVS\s0 client to use your
pserver and execute all the same commands that you can locally (which
we tested before). You may wish to take advantage of a graphical \s-1CVS\s0
client, which can be particularly helpful in leveling the learning
curve.
.PP
Your pserver connection string will something along the lines of:
.PP
.Vb 1
\& :pserver:@:/home/interch/rep
.Ve
See the \fIResources\fR Appendix for links to some graphical \s-1CVS\s0 tools.
.SH "Import your Interchange catalog into CVS"
.IX Header "Import your Interchange catalog into CVS"
.Sh "Configuring your catalog"
.IX Subsection "Configuring your catalog"
Eventually, we will import your catalog into the \s-1CVS\s0 repository, but
first we need to do some work with a temporary copy of the catalog so
we can get it into shape for importing.
.PP
\&\fBNote: \fRFrom here on, assume the use of the Interchange user, such as
interch, unless otherwise noted.
.PP
.Vb 1
\& su - interch
.Ve
If you installed via \s-1RPM:\s0
.PP
.Vb 1
\& service interchange stop
.Ve
If you installed via tarball (default path):
.PP
.Vb 1
\& /usr/local/interchange/bin/interchange --stop
.Ve
.Sh "Remove old \s-1CVS\s0 folders"
.IX Subsection "Remove old CVS folders"
If, for any reason, you already have \s-1CVS/\s0 directories in your
catalog, they must be removed because they might interfere with the
new \s-1CVS\s0 setup. You might use the following find command, which will
find any folders named \s-1CVS\s0 in the current directory and remove
them.
.PP
sNote:You should make a backup of the catalog directory before you do
this.
.PP
#backup catalog folder first
tar czf ~/foundation_backup.tgz /var/lib/interchange/foundation
.PP
#get rid of any old \s-1CVS\s0 folders \*(-- (\s-1BE\s0 \s-1CAREFUL\s0!)
cd /var/lib/interchange/foundation
find . \-name \s-1CVS\s0 \-exec rm \-Rf {} \e;
.Sh "Create a working copy of your catalog"
.IX Subsection "Create a working copy of your catalog"
A working copy of your catalog is necessary to get it into shape for
use with \s-1CVS\s0. The following command creates a copy in the /tmp
directory.
.PP
.Vb 2
\& cp -a /var/lib/interchange/foundation /tmp/import_foundation
\&cd /tmp/import_foundation
.Ve
.Sh "Streamline your catalog for \s-1CVS\s0"
.IX Subsection "Streamline your catalog for CVS"
Considerations about what to import into \s-1CVS\s0
.PP
From your working directory (/tmp/import_foundation), decide which
files will be in the \s-1CVS\s0 repository, and which will not. While it is
entirely possible to import the entire catalog into the repository
unchanged, I usually prefer to doctor my directories up before letting
them into my repository because of several reasons:
.Ip "\(bu" 4
Will the file be modified by another source?
.PP
For example, /etc/order.number is modified by Interchange when run.
It is recommended that the \s-1CVSIGNORE\s0 features be used to handle these
types of files. See \fI\s-1CVSIGNORE\s0\fR.
.Ip "\(bu" 4
The likelihood that you will modify the file.
.PP
For example, if I am certain that I wont every want to modify the
session/ files directly, then I probably wouldn't need to manage that
through \s-1CVS\s0, but I do import the empty session/ directory to make it
easier when setting up new catalogs.
.Ip "\(bu" 4
Speed.
.PP
Managing less files in the repository takes away from the amount of
time required for \s-1CVS\s0 checkout, update, branching, and other \s-1CVS\s0
actions. For most, this amount of time is small already, but it is a
consideration for some. If you have a very large image directory, it
may be benificial to leave it out at first. Note that you can add or
remove anything later on.
.PP
Remove files that aren't needed in \s-1CVS\s0
.PP
Here is an example of some things to remove from your catalog. If you
do move more directories, be sure to move them to a directory that you
can later use to re-unite with a checked-out copy for a working
catalog. But here I chose just to move files that are not needed for
a template \*(L"skeleton\*(R" catalog.
.PP
If you want to add images to your repository, the images directory is
typically symlinked to /var/www/html/foundation/images, so I remove
this symlink from the working copy, and replace it with an exact copy
which will go into the \s-1CVS\s0 repository.
.PP
.Vb 3
\& #Setup images directory
\&rm images
\&cp -a /var/www/html/foundation/images .
.Ve
#Remove
rm \-Rf \e
error.log \e
*.structure \e
orders/* \e
logs/* \e
session/* \e
tmp/* \e
upload/* \e
backup/* \e
logs/* \e
#done.
.PP
# The \*(L".empty\*(R" files make it so that \s-1CVS\s0 will still checkout the
# directory, even though it is empty.
touch \e
orders/.empty \e
logs/.empty \e
session/.empty \e
tmp/.empty \e
upload/.empty \e
backup/.empty \e
#done.
.Sh "Import the streamlined catalog"
.IX Subsection "Import the streamlined catalog"
Import the remaining portion of the catalog using the cvs import
command, with \*(L"foundation\*(R" as the module name and repository directory
name. See the \s-1CVS\s0 documentation resources mentioned in Appendix
\&\fIResources\fR for more information.
.PP
When you run the import command, it will launch \f(CW$EDITOR\fR (set to
\&'vi' earlier), and ask for a message to go along with the import
action. Whatever you see fit to write (e.g. \*(L"starting new \s-1CVS\s0 module
with my foundation catalog...\*(R") is fine.
.PP
This example import command includes renaming the foundation
\&\*(L"working\*(R" directory back to \*(L"foundation\*(R" for the import.
.PP
.Vb 1
\& cvs import foundation foundation start
.Ve
.Sh "Testing the new \s-1CVS\s0 module"
.IX Subsection "Testing the new CVS module"
Now you should be able to do another test checkout or update using any
\&\s-1CVS\s0 client, which should now download all the files that you have just
imported into \s-1CVS\s0. Additionally, you might test your newly imported
code by making a change to one of your checked-out source files,
saving it, then committing it.
.PP
.Vb 2
\& index.html:
\&
.Ve
Now commit the change
.PP
cvs commit index.html
.PP
Your changed version will now be resident in the repository. There
are a lot of good \s-1CVS\s0 documentation and resources for discovering more
about the checkout/update/commit cycle and other \s-1CVS\s0 aspects in the
\&\fIResources\fR Appendix
.PP
You'll also notice that even if you start your interchange server, the
change you made did not take effect. The next section will detail the
process of tying \s-1CVS\s0 and Interchange together in a way that this will
happen automatically.
.SH "Integrate CVS and Interchange"
.IX Header "Integrate CVS and Interchange"
The next step is to allow \s-1CVS\s0 to update the directory that Interchange
uses to serve pages.
.Sh "\s-1CVS\s0 checkout into the catalog directory"
.IX Subsection "CVS checkout into the catalog directory"
Now it is the time to replace the directories in your catalog that
have counterparts in \s-1CVS\s0 with fresh checkouts from \s-1CVS\s0 (this is a
preliminary action to allow \s-1CVS\s0 to update your catalog directory when
a change is made to \s-1CVS\s0).
.PP
\&\fBNote: \fRMake sure interchange daemon is stopped and you have a good
backup before continuing.
.PP
tar czf ~/foundation.backup2.tgz /var/lib/interchange/foundation
.PP
Checkout a copy from \s-1CVS\s0 into a different directory (such as
\&\fIfoundation_CVS\fR).
.PP
.Vb 2
\& cd /var/lib/interchange/
\&cvs co -d foundation_CVS foundation
.Ve
This should create the \fIfoundation_CVS/\fR directory for you, so that
it wont conflict with your existing \fIfoundation/\fR directory.
.PP
Add any needed files to checked-out catalog
.PP
Note that empty directories are pruned, so they will need something in
them for them to show up with a \-P checkout. Often a zero-byte file
called '.empty' is used.
.PP
If you removed any directories during the streamlining step, we must
first add those back so that the catalog is usable to Interchange. In
this document, we only removed unneeded files and left empty
directories.
.PP
This can also be the time to copy any \*(L"data\*(R" files such as orders/
logs/, etc. that might be needed if it is a live catalog.
.PP
.Vb 3
\& cd /var/lib/interchange/foundation
\&cp -a \e
\& /var/lib/interchange/foundation_CVS
.Ve
Install and test the new catalog
.PP
Now lets move the old \fIfoundation\fR out of the way and put the new
\&\fIfoundation_CVS\fR in its place.
.PP
.Vb 3
\& cd /var/lib/interchange/
\&mv foundation foundation_old
\&mv foundation_CVS foundation
.Ve
Now, link up the \s-1CVS\s0 images for use by Apache.
.PP
.Vb 3
\& cd /var/www/html/foundation/
\&mv images images_old
\&ln -s /var/lib/interchange/foundation/images images
.Ve
Now, you should have a working catalog again. To make sure, start up
Interchange and test the site with your browser.
.Sh "Testing manual \s-1CVS\s0 updates on Interchange catalogs"
.IX Subsection "Testing manual CVS updates on Interchange catalogs"
Next, lets again update the checkout we made a while back before
importing our catalog. (Alternatively, one could use a visual \s-1CVS\s0
client detailed above).
.PP
.Vb 2
\& cd ~/src
\&cvs -q up -d foundation # -q for quiet, -d for directory prune/update
.Ve
Additionally, you might test making a change to one of your
checked-out source files, saving it, then committing it.
.PP
.Vb 2
\& index.html:
\&
.Ve
Now commit the change
.PP
.Vb 1
\& cvs commit index.html
.Ve
Your changed version will now be resident in the repository. Again,
\&\s-1CVS\s0 documentation is in the \fIResources\fR Appendix.
.PP
This time, we can allow the changes to take effect on the code being
used by Interchange to serve pages. To do so, one must run a cvs
update on the catalog directory:
.PP
.Vb 2
\& cd /var/lib/interchange/foundation
\&cvs -q up -d #up is the shortened version of "update"
.Ve
That should notify you of the new version it downloaded with something
like:
.PP
U pages/index.html
.PP
You may also get something like the following:
.PP
.Vb 5
\& M catalog.cfg
\&M etc/status.foundation
\&M ...
\&? orders/000001
\&? ...
.Ve
The ? lines in the above example mean that the \s-1CVS\s0 server has never
heard of the listed directories or files (they are in your local
source dir but not in the \s-1CVS\s0 source dir). It is harmless, but
sometimes annoying, and can be taken care of with \s-1CVSIGNORE\s0.
.PP
The M means that the file has been modified on your local copy, and
is out of sync with the remote \s-1CVS\s0 version (e.g. when Interchange runs
it updates \fIetc/status.foundation\fR). Normally this is corrected by
uploading your \*(L"modified\*(R" version to the server, but in this case, the
modification was done by Interchange instead of the programmer, and
wasn't meant to be committed back to the \s-1CVS\s0 repository. See
\&\fI\s-1CVSIGNORE\s0\fR.
.PP
Now, check to make sure that your change has taken effect by
refreshing the homepage on the site. To see the comment, use
View->Page Source or whatever the relevant command for your
browser is.
.PP
At this point, its obvious that it would be time consuming to manually
run 'cvs up' every time you make a change to the source code, so the
next step is to setup \s-1CVS\s0 to automatically update the catalog whenever
you commit something to \s-1CVS\s0.
.Sh "Automatic updates on commit"
.IX Subsection "Automatic updates on commit"
Start by modifying \f(CW$CVSROOT\fR/CVSROOT/loginfo
.PP
.Vb 3
\& ^foundation (date; cat; ( \e
\& sleep 1; cd /var/lib/interchange/foundation; cvs -q update -d \e
\& ) &) >> $CVSROOT/CVSROOT/updatelog 2>&1
.Ve
The first line tells \s-1CVS\s0 that for every commit on modules that start
with \*(L"foundation\*(R" (notice the regular expression \*(L"^foundation\*(R"), it
will run cvs update on the given catalog directory in the
background. It is important that it is executed in a forked shell
(notice the \*(L"&\*(R") after sleep'ing for 1 second, because otherwise
you may run into contention issues that can cause file locking
problems. The 1 second timing used above works fine for me, but a
longer pause may be necessary for slower computers (you'll know if you
get errors about \*(L"file locked by user\*(R"). See the \s-1CVS\s0 documentation in
the \fIResources\fR Appendix for more details.
.Sh "Automatic e-mail on commit"
.IX Subsection "Automatic e-mail on commit"
Often it is very helpful to have a commit mailing list that keeps
developers up-to-date on every commit happening to the \s-1CVS\s0. Perform
these steps:
.Ip "\(bu" 4
Download syncmail
.Sp
mkdir ~/src; cd ~/src
.PP
As root, you must setup the \*(L"cvs-log\*(R" alias to go to the correct
e-mail address(es).
.PP
.Vb 2
\& echo 'cvs-log: email_one@yahoo.com,email_two@yahoo.com' >> /etc/aliases
\&newaliases
.Ve
See \fIMailserver for \s-1CVS\s0 updates\fR.
.PP
Here is what a sample e-mail looks like:
.PP
.Vb 5
\& User: danb
\&Date: 2003-01-16 23:40:47 GMT
\&Modified: pages index.html
\&Log:
\&Testing...
.Ve
Revision Changes Path
1.10 +1 \-8 hoopstore/pages/index.html
.PP
rev 1.10, prev_rev 1.9
Index: index.html
\&\&===================================================================
\&\s-1RCS\s0 file: /home/interch/rep/hoopstore/pages/index.html,v
retrieving revision 1.9
retrieving revision 1.10
diff \-u \-r1.9 \-r1.10
\&\-\-\- index.html 16 Jan 2003 22:47:55 \-0000 1.9
+++ index.html 16 Jan 2003 23:40:47 \-0000 1.10
@@ \-31,7 +31,7 @@
[control-set]
[component]none[/component]
[/control-set]
\&\-
+
.PP
.Vb 1
\& [control reset=1]
.Ve
@@ \-51,10 +51,3 @@
.PP
.Vb 3
\& @_LEFTRIGHT_BOTTOM_@
\&-
\&-
.Ve
Now you have a working \s-1CVS\s0 development system. At this point it may
be valuable to learn more about \s-1CVS\s0 the client tools that you are
using.
.SH "The two track model: development and live catalogs"
.IX Header "The two track model: development and live catalogs"
It is often very valuable to have a two-track development model that
separates the classes of work into separate timing and decision
categories. Some use \*(L"staging\*(R" and \*(L"production\*(R" terminology, others
prefer \*(L"unstable\*(R" and \*(L"stable\*(R", \*(L"beta\*(R" and \*(L"release\*(R", or \*(L"development\*(R"
and \*(L"live\*(R".
.PP
The easiest starting point for two-track development is to just use
two completely separate \s-1CVS\s0 modules and catalogs. This can make a lot
of sense for many situations, for example when the next revision of
the site will be so different that it is for all practical purposes
starting from ground zero.
.PP
A slightly more complicated solution is to use the \s-1CVS\s0 branches
feature. It is more difficult to set up, but can be rewarding when
used correctly.
.Sh "When to branch"
.IX Subsection "When to branch"
The first decision is when to branch the source code. For websites,
this can sometimes be an easy decision like \*(L"first went live\*(R", or
\&\*(L"site-wide overhaul\*(R", etc.
.Sh "Which way to branch"
.IX Subsection "Which way to branch"
There are many different ways to branch source code. What seems to be
the most common method is to use the \*(L"trunk\*(R", which is the \s-1HEAD\s0 tag to
\&\s-1CVS\s0 as the development version, and then make a branch when a stable
release is to be made.
.PP
That model doesn't fit my development style at the current time, so I
use the \s-1HEAD\s0 default branch as my stable live version, and use other
tags (like \s-1DEV1\s0 and \s-1DEV_REALLY_UNSTABLE\s0) for my development branch.
.PP
You may find that you are merging (or \*(L"folding\*(R") most or all of your
development ranch back into your stable branch frequently. This is
because unlike traditional programming where products are launched
every two or three years with new features, web sites often have
little fixes and new features added every day or every few weeks, with
new \*(L"releases\*(R" happening more often than traditional software
development (though not all web sites follow that trend). The
flexibility is there to branch the source for quite some time to work
on a very complex feature or complete redesign before bringing it to
the live site, as well as the flexibility for day-to-day updates.
.Sh "Performing the branch"
.IX Subsection "Performing the branch"
To perform the branch use the \f(CW\*(C`cvs tag \-b \*(C'\fR command.
For example:
.PP
.Vb 1
\& cvs tag -b DEV1
.Ve
Remember that this does not change your locally checked out working
directory to the new tag automatically, it only creates the branch
within the \s-1CVS\s0 repository.
.Sh "Setup the development catalog"
.IX Subsection "Setup the development catalog"
Now we have a branch in \s-1CVS\s0, but we need to tie it to something in the
real world, namely, an Interchange catalog.
.PP
Importing the catalog
.PP
Like we did in \fIIntegrating \s-1CVS\s0 with Interchange\fR, you must make
another copy of your catalog for use as the development version. Some
would like to keep the orders/, logs/, and other directories the same,
but I prefer to start with a clean slate, especially since I don't
plan on having any customers visit the development site. (In fact,
you can restrict who can access the development \s-1URL\s0 using the Apache
\&\f(CW\*(C` allow from...\*(C'\fR directive).
.PP
Checkout source code
.PP
.Vb 2
\& cd /var/lib/interchange
\&cvs co -d foundation_dev foundation
.Ve
Copy any other needed directories to complete the catalog
.PP
Depending on how complete your catalog is in \s-1CVS\s0, you may need to
create or copy directories/files.
.PP
.Vb 3
\& cd /var/lib/interchange/foundation
\&cp -a catalog.cfg orders/* \e
\& /var/lib/interchange/foundation_dev
.Ve
\&\fBNote: \fRA lot of the following steps are performed by the
/usr/local/interchange/bin/makecat script, but here is how to do it
manually:
.PP
Setting up a separate database
.PP
Most often, I find it profitable to make use of a second database for
the development catalog, rather than having both catalogs reference
the same database (especially if the first catalog is live).
.PP
Create a second database
.PP
Use the means of your database platform to create a separate database.
For example, PostgreSQL users might do something like:
.PP
createdb foundation_dev
.PP
Populate the database
.PP
You can rely on the catalogs internal products/*.txt data to generate
the database tables and populate them, or you can export another
catalog's database and import it for the development catalog, like the
example below for PostgreSQL users.
.PP
.Vb 2
\& pg_dump foundation > ~/foundation.dump
\&psql foundation_dev < ~/foundation.dump
.Ve
Copy the catalog support files
.PP
.Vb 2
\& #Must be root
\&su - root
.Ve
#Copy \s-1HTML\s0
cd /var/www/html/
cp \-a foundation foundation_dev
.PP
#Copy \s-1CGI\s0
cd /var/www/cgi-bin
cp \-a foundation foundation_dev
.PP
Configure the Interchange daemon
.PP
Perform the necessary modifications to \fIinterchange.cfg\fR. For
example:
.PP
.Vb 3
\& /usr/local/interchange/interchange.cfg:
\&Catalog found /var/lib/interchange/foundation /cgi-bin/foundation
\&Catalog found_dev /var/lib/interchange/foundation_dev /cgi-bin/foundation_dev
.Ve
Configure the catalog specifics
.PP
The development catalog will differ at least a little bit from the
standard catalog, such as in the \s-1CGI_URL\s0 and database parameters. I
recommend using a separate \*(L"local\*(R" configuration file to hold the
separate values, such as \fIconfig/local.cfg\fR, and then include it from
catalog.cfg.
.PP
.Vb 3
\& /var/lib/interchange/config/local.cfg:
\&Variable CGI_URL /cgi-bin/foundation_dev
\&Variable IMAGE_DIR /foundation_dev/images
.Ve
Now you can restart Interchange to make your changes take effect.
.Sh "Splitting updates on commit by tag"
.IX Subsection "Splitting updates on commit by tag"
Setup \s-1CVS\s0 so that when you commit to the \s-1DEV1\s0 branch, only the
development (foundation_dev) catalog will be updated. And when you
commit with no tags (\s-1HEAD\s0 branch), the live (foundation) catalog
will be updated. Here is an example \fIloginfo\fR. The \f(CW\*(C`\-r \*(C'\fR
may be used just in case your environment is such that the tags may be
changed by other sources.
.PP
.Vb 7
\& $CVSROOT/CVSROOT/loginfo:
\&foundation \e
\& (date; cat; ( \e
\& sleep 1; cd /var/lib/interchange/foundation_dev; cvs -q up -d; \e
\& cd /var/lib/interchange/foundation; \e
\& cvs -q up -d) &) >> $CVSROOT/CVSROOT/updatelog 2>&1
\&ALL /usr/bin/cvs-log $CVSROOT/CVSROOT/commitlog $USER "%{sVv}"
.Ve
.Sh "Using new branches"
.IX Subsection "Using new branches"
To use your new branch, checkout a working copy of the source with the
correct tag specified. For example:
.PP
.Vb 1
\& cvs co -P -r DEV1
.Ve
Then make change to one of the files, and commit it. The change
should show on your development catalog, but not your live catalog.
.Sh "Merging"
.IX Subsection "Merging"
When you want to merge a change that you have made on your development
branch into your stable branch, there are many ways that you can do
it. One would be to :
.RS 4
.Ip "\(bu" 8
Make a change in the development branch (\s-1DEV1\s0) and commit it.
.Ip "\(bu" 8
Copy the development-tagged file to a temporary name
.Ip "\(bu" 8
Update to the live version (\s-1HEAD\s0)
.Ip "\(bu" 8
Overwrite the live (\s-1HEAD\s0) version of the file with your temporary one
.Ip "\(bu" 8
Commit the result
.Ip "\(bu" 8
Update back to the development version (\s-1DEV1\s0)
.RE
.RS 4
.RE
.PP
I do the above so often that I have written a Tcl script for WinCVS
that will automatically perform the above steps. And similar shell
scripts can probably be easily written to match your development
environment.
.PP
The above seems to be the easiest way, to me. However, there are
other alternatives detailed in the \s-1CVS\s0 manual in chapter 5, \*(L"Branching
and merging\*(R", that I highly recommend for reading. One method
involves specifying the last version that has already been merged into
the live branch using a specific version number, date, relative time,
or special purpose tag.
.SH "Tools of the trade"
.IX Header "Tools of the trade"
This is the productivity tips section, which will hopefully help you
to be able to get more done in less time.
.Sh "Workstation Interchange installation"
.IX Subsection "Workstation Interchange installation"
Not all developers work on Linux workstations, many use Apples
(graphics designers and \s-1HTML\s0 gurus tend to, I've found), and many use
Windows. This means that many developers have the extra step of
uploading their changes to a Unix server where Interchange is running
in order to see their changes.
.PP
The remedy to that is to setup an Interchange server on your
workstation, or any location that has direct access to the \s-1CVS\s0 source
files. I'll explain:
.PP
The Interchange server that runs where the \s-1CVS\s0 server is (that we
setup earlier) can be seen as the gathering point for all the
developers. However, each developer may run as many Interchange
daemons as he/she requires in a local context for the purpose of
seeing the changes made before uploading them via \s-1CVS\s0.
.PP
For example, Bob could setup another Interchange catalog on the same
server as the \s-1CVS\s0, (e.g. foundation-bob). To get direct access to
those files (rather than \s-1FTP\s0), Bob could use \s-1NFS\s0 mounts (if Bob's
workstation is Linux) or \s-1SMB\s0 mounts using Samba if his workstation is
a Windows variant. Any way that Bob can get direct access to the
files will save him some time (by cutting out the \*(L"upload\*(R" from the
\&\*(L"edit->upload->test\*(R" development cycle). One could even use VMware to
run a Linux server on your Windows workstation.
.PP
\&\fBNote: \fRYou can now use the cygwin compatibility confirmed in
Interchange versions 4.7.6 and above to run Interchange right on your
Windows workstation.
.PP
The result will be that you can modify the files with your favorite
text editor and see the results immediately through your local
catalog. Setting up the catalog initially is quite easy. Just follow
the same steps used to setup the \s-1CVS\s0 catalog. Which is:
.Ip "\(bu" 4
Checkout from \s-1CVS\s0 into a new \s-1CVS\s0 catalog directory and link the
images/ directory.
.Ip "\(bu" 4
Make localized configuration modifications. I recommend creating a
\&\fIconfig/local.cfg\fR file and then include it at the top of
catalog.cfg, with the contents of:
.Sp
Variable \s-1CGI_URL\s0 /cgi-bin/foundation
.Ip "\(bu" 4
Restart Interchange.
.PP
You may need to remove all *.sql files from the products directory, to
create all of the database files again. Additionally, you may need to
create the database, username/password for your database again as
well.
.PP
You will need to recreate any symbolic links that previously existed,
such as templates/default \-> templates/foundation
.PP
Another thing that you might have noticed at this point is all the
files that are modified locally by the Interchange daemon will report
? or M when you run an update. To fix this, see \fI\s-1CVSIGNORE\s0\fR.
.Sh "\s-1CVSIGNORE\s0"
.IX Subsection "CVSIGNORE"
On the heals of a workstation installation is the requirement to setup
\&\s-1CVSIGNORE\s0. For all files that change, but you want to ignore (such as
\&\fIetc/foundation.status\fR), create an entry in the .cvsignore file in
that directory. Note that the file must be removed from the cvs
repository before it will work.
.PP
Here is a script that will create some sample files:
.PP
cat >.cvsignore <<\s-1EOF\s0
error.log
*.structure
timed
tmp
\&\s-1EOF\s0
.PP
cat >etc/.cvsignore <<\s-1EOF\s0
status.*
*.counter
*.number
*.recordnumber
\&\s-1EOF\s0
.PP
cat >products/.cvsignore <<\s-1EOF\s0
*.lnk
*.sql
*.autonumber
*.[1\-9]*
*.csv.numeric
*.name
*.sort
*.txt.*
\&\s-1EOF\s0
.PP
echo \*(L"local.cfg\*(R" > config/.cvsignore
echo \*(L"*\*(R" > backup/.cvsignore
echo \*(L"*\*(R" > logs/.cvsignore
echo \*(L"*\*(R" > orders/.cvsignore
echo \*(L"*\*(R" > session/.cvsignore
echo \*(L"*\*(R" > upload/.cvsignore
echo \*(L"*\*(R" > tmp/.cvsignore
.PP
cvs add \e
.cvsignore \e
etc/.cvsignore \e
products/.cvsignore \e
config/.cvsignore \e
backup/.cvsignore \e
logs/.cvsignore \e
orders/.cvsignore \e
session/.cvsignore \e
upload/.cvsignore \e
tmp/.cvsignore \e
#done.
.Sh "Mailserver for \s-1CVS\s0 updates"
.IX Subsection "Mailserver for CVS updates"
An easy alternative to setting up a mailserver is to merely alias the
addresses that you would like updated. If you don't have many users
following your commit list, it is recommended. In \fI/etc/aliases\fR,
merely put:
.PP
.Vb 1
\& cvs-log: address_one@yahoo.com,address_two@yahoo.com,address_three@yahoo.com
.Ve
Then run newaliases and your \*(L"mini\*(R" mailing list will be all
setup.
.PP
To setup a mailserver for \s-1CVS\s0 updates, first download and install
Mailman. For RPM-based systems, check on rpmfind.net for a precompiled
binary package.
.PP
After installing, read the following information about Mailman and
what needs to be done after installation (taken from the \s-1RPM\s0 meta
data):
.PP
"Mailman is software to help manage email discussion lists, much like
Majordomo and Smartmail. Unlike most similar products, Mailman gives
each mailing list a web page, and allows users to subscribe,
unsubscribe, etc. over the web. Even the list manager can administer
his or her list entirely from the web. Mailman also integrates most
things people want to do with mailing lists, including archiving, mail
<\-> news gateways, and so on.
.PP
When the package has finished installing, you will need to:
.Ip "\(bu" 4
Run \fI/var/mailman/bin/mmsitepass\fR to set the Mailman administrator
password.
.Ip "\(bu" 4
Edit \fI/var/mailman/Mailman/mm_cfg.py\fR to customize Mailman's
configuration for your site.
.Ip "\(bu" 4
Modify the sendmail configuration to ensure that it is running and
accepting connections from the outside world (to ensure that it runs,
set \*(L"DAEMON=yes\*(R" in /etc/sysconfig/sendmail, ensuring that it accepts
connections from the outside world may require modifying
/etc/mail/sendmail.mc and regenerating sendmail.cf), and
.Ip "\(bu" 4
Add these lines:
.Sp
.Vb 1
\& ScriptAlias /mailman/ /var/mailman/cgi-bin/
.Ve
.PP
to \fI/etc/httpd/conf/httpd.conf\fR to configure your web server.
.PP
Users upgrading from previous releases of this package may need to
move their data or adjust the configuration files to point to the
locations where their data is."
.PP
Then run /var/mailman/bin/newlist and follow the directions from
there.
.Sh "Locally mapped source code for a network \s-1IC\s0 server"
.IX Subsection "Locally mapped source code for a network IC server"
This is useful mostly to Windows users, since Linux users can just as
easily run \s-1IC\s0 daemons on their own workstation as they can a separate
server.
.PP
The idea is to have the \s-1IC\s0 server use its own files and directories
for things that won't be edited and modified locally, but reference a
Samba directory or \s-1NFS\s0 directory for things that will (such as
\&\fIpages/\fR, \fItemplates/\fR, etc.).
.PP
Mount the Samba or \s-1NFS\s0 directory
.PP
\&\f(CW\*(C`smbmount <...>\*(C'\fR or \f(CW\*(C`mount \-t nfsfs <...>\*(C'\fR
.PP
The following script uses two directories (source and destination) to
create symlinks for the commonly modified source directories of
Interchange.
.PP
.Vb 9
\& export S=/mnt/nfs/foundation
\&export D=/var/lib/interchange/foundation
\&F=db; ln -s $S/$F $D/$F
\&F=dbconf; ln -s $S/$F $D/$F
\&F=etc; ln -s $S/$F $D/$F
\&F=images; ln -s $S/$F $D/$F
\&F=pages; ln -s $S/$F $D/$F
\&F=special_pages; ln -s $S/$F $D/$F
\&F=templates; ln -s $S/$F $D/$F
.Ve
This will leave you with a working catalog that can be quickly
modified (since your editor can access the local copy), while
Interchange has to do the work of going over the \s-1SMB\s0 or \s-1NFS\s0
connection.
.Sh "jEdit \- a good editor with Interchange/HTML/Perl colorization and \s-1CVS\s0"
.IX Subsection "jEdit - a good editor with Interchange/HTML/Perl colorization and CVS"
I have been quite impressed with jEdit (http://www.jedit.org, and
open source editor that is written in Java and runs on most platforms.
.PP
I use the interchange.xml language definition written by Chris
Jesseman \fIchris@sitemajic.net\fR, which is available from
http://www.sitemajic.net/jedit/. With this, jEdit automatically
colors \s-1HTML\s0, Perl, \s-1AND\s0 many Interchange tags very intelligently.
.PP
Further, jEdit has a \s-1CVS\s0 plugin, written by Ben Sarsgard
\&\fIbsarsgard@vmtllc.com\fR, and available at:
http://www.vmtllc.com/~bsarsgard/jedit.html. This plugin allows
you to diff, update, and commit right from the editor.
.Sh "Separate servers for development and live catalogs"
.IX Subsection "Separate servers for development and live catalogs"
If you have the luxury of separate server hardware for the development
and live catalogs, you might find the following utility helpful:
.Ip "\(bu" 4
CVSviaFTP (http://www.cvshome.org/dev/addoncvsftp.html) \- from the
\&\s-1CVS\s0 Add-ons page (http://www.cvshome.org/dev/addons.html).
.PP
It allows one to have a given \s-1CVS\s0 module automatically publish each
update to an \s-1FTP\s0 server, which could serve as the live server. Or one
could could use it if your \s-1CVS\s0 installation is only local and you
could use it to upload your changes to your production server.
.PP
Credits
.Ip "\(bu" 4
\&\fBJon Jensen\fR: Thanks for helping me get going on the \s-1SDF\s0 format
already used by the Interchange documentation, and fixing some \s-1SDF\s0
syntax errors.
.Ip "\(bu" 4
\&\fBMike Heins & all who have contributed to the success of
Interchange\fR: Thanks for following the Way Of The Source, for quality
programming, and for helping to making \s-1IC\s0 something to write about.
.Ip "\(bu" 4
Thanks to the countless others who have written the \s-1CVS\s0 documentation
that is available online, which was my only source for learning \s-1CVS\s0.
.PP
Document history
.Ip "\(bu" 4
May 2001. Conceived and written by Dan Browning.
.Ip "\(bu" 4
July 19, 2001. First draft complete, first public release.
.Ip "\(bu" 4
April 12, 2002. Minor typographical edit.
.Ip "\(bu" 4
June 8, 2002. Minor updates.
.PP
Resources
.PP
\&\s-1CVS\s0 Documentation
.PP
Here are some resources for learning more about \s-1CVS\s0. I have ranked
them by the order of usefulness, which is of course, objective.
.Ip "\(bu" 4
Karl Fogel's \s-1CVS\s0 book http://cvsbook.red-bean.com/
.Ip "\(bu" 4
The official \s-1CVS\s0 manual http://www.cvshome.org/docs/manual/
.Ip "\(bu" 4
The official \s-1CVS\s0 \s-1FAQ\s0 http://faq.cvshome.org/
.Ip "\(bu" 4
The official \s-1CVS\s0 homepage http://www.cvshome.org
.Ip "\(bu" 4
Info-CVS mailing list http://mail.gnu.org/mailman/listinfo/info-cvs
.Ip "\(bu" 4
\&\s-1CVS\s0 \s-1FAQ\s0 2 http://www.cs.utah.edu/dept/old/texinfo/cvs/FAQ.txt
.Ip "\(bu" 4
Sean Dreilinger's \s-1CVS\s0 Version Control for Web Site Projects
http://durak.org/cvswebsites/
.Ip "\(bu" 4
Pascal Molli's \s-1CVS\s0 reference site
http://www.loria.fr/~molli/cvs-index.html
.Ip "\(bu" 4
\&\s-1CVS\s0 Tutorial
http://cellworks.washington.edu/pub/docs/cvs/tutorial/cvs_tutorial_1.html
.Ip "\(bu" 4
\&\s-1CVS\s0 Tutorial 2
http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/cvs/
.Ip "\(bu" 4
Red Hat \s-1CVS\s0 pserver setup guide http://www.michael-amorose.com/cvs/
.Ip "\(bu" 4
\&\s-1CVS\s0 Add-ons http://www.cvshome.org/dev/addons.html
.PP
\&\s-1CVS\s0 Server Software
.Ip "\(bu" 4
\&\s-1CVS\s0 \s-1RPM\s0 download (Red Hat Linux 7.1)
ftp://speakeasy.rpmfind.net/linux/redhat/7.1/en/os/i386/RedHat/RPMS/cvs-1.11-3.i386.rpm
.Ip "\(bu" 4
Links to source tarball links can can be found at cvshome.org.
.PP
\&\s-1CVS\s0 Client Software
.PP
There is a variety of client access methods for using \s-1CVS\s0 on your
development box.
.Ip "\(bu" 4
\&\s-1CVSGUI\s0 is a great project that brings graphical clients to Linux,
Windows, and Mac at http://www.cvsgui.org. These also give you the
same access to all the command line cvs commands.
.Ip "\(bu" 4
jCVS is a great cross-platform graphical \s-1CVS\s0 client available at
http://www.jcvs.org.
.Ip "\(bu" 4
jEdit is a great cross-platform text editor written in java, which not
only has a \s-1CVS\s0 module that allows you to commit (upload) files
directly from the editor, but also has a Interchange Tag Language (and
Perl language) colorizer/parser. It is available from
http://www.jedit.org.
.PP
.Vb 1
\& ________________________________________
.Ve
Copyright 2002\-2004 Interchange Development Group. Copyright 2001\-2002
Dan Browning . Freely redistributable under
terms of the \s-1GNU\s0 General Public License. line:
.PP
Interchange + Forum/Blog \s-1HOWTO\s0
.SH "Introduction"
.IX Header "Introduction"
.Sh "Preamble"
.IX Subsection "Preamble"
Copyright 2002\-2004 Mike Heins and Michael
Wilk . Freely redistributable under terms of
the \s-1GNU\s0 General Public License.
.Sh "Purpose"
.IX Subsection "Purpose"
The purpose of this document is to expose how to use Interchange 5.0's
forum and blog capability, enabled with the [forum ...] tag and a few
ancilliary files.
.Sh "Audience"
.IX Subsection "Audience"
Anyone who is using an Interchange catalog. This is not rocket
science.
.Sh "Contact the authors"
.IX Subsection "Contact the authors"
If you find any spelling errors, technical slip-ups, mistakes,
subliminal messages, or if you wish to send feedback, critique,
remarks, comments, or if you wish to contribute examples, instructions
for alternative platforms, chapters, or other material, please do so.
.PP
The preferred method of submitting changes is in the form of a context
diff against the \s-1SDF\s0 source file (ic_howto_forum.sdf). Please address
your correspondence to:
.PP
Michael Wilk \fImwilk@steppenwolf.com\fR
.PP
Mike Heins \fImike.heins@perusion.net\fR
.Sh "What it does"
.IX Subsection "What it does"
Interchange forums allow your customers to comment on your products,
or allow you to sponsor discussion threads on an interchange catalog.
They maintain their content in a single database table named forum.
.SH "Component files of the forums"
.IX Header "Component files of the forums"
There are two directories to add to your foundation catalog \-\-
include/forum and pages/forum. You must add a database table
definition, as well as a database source file. You should add Variable
support to the variable.txt database, and supporting metadata with
help. Finally, you need to add the forum.tag file which contains
the forum code.
.PP
If you build a foundation catalog from the latest Interchange
source, all of these will be done already.
.PP
The files that are needed in the catalog directory:
.PP
.Vb 9
\& dbconf/default_db/forum.dbm
\& dbconf/mysql/forum.mysql
\& dbconf/pgsql/forum.pgsql
\& include/forum/reply_form
\& include/forum/submit_form
\& pages/forum/reply.html
\& pages/forum/display.html
\& pages/forum/submit.html
\& products/forum.txt
.Ve
The files that are needed in the Interchange software directory:
.PP
.Vb 1
\& code/UserTag/forum.tag
.Ve
Add the following lines to products/variable.txt (change | to \s-1TAB\s0):
.PP
.Vb 3
\& FORUM_ANON_NAME|Anonymous Coward|Forums
\&FORUM_PRODUCTS|1|Forums
\&FORUM_EMAIL_NOTIFY|sales@yourcompany.com|Forums
.Ve
Add the following records to products/mv_metadata.asc (shown in
key: value format, edit file to match with \*(L"te\*(R" or some other tool):
.PP
.Vb 77
\& #
\ This is a temporary file, automatically generated from the
\ database file:
\
\ /tmp/what.txt
\
\ If you change anything in it, it will be converted back into the
\ original format and will replace the original file.
\
\&code:variable::Variable::FORUM_EMAIL_NOTIFY
\&type:text
\&width:50
\&height:
\&field:
\&db:
\&name:
\&outboard:
\&options:
\&attribute:
\&label:Forum notify email
\&help:An email address to send copies of user comments on products.
\&lookup:
\&filter:
\&help_url:
\&pre_filter:
\&lookup_exclude:
\&prepend:
\&append:
\&display_filter:
\&default:
\&extended:
\
\&code:variable::Variable::FORUM_ANON_NAME
\&type:text
\&width:20
\&height:
\&field:
\&db:
\&name:
\&outboard:
\&options:
\&attribute:
\&label:Forum Anonymous Name
\&help:Name to use when a user posts anonymously to a forum
\&lookup:
\&filter:
\&help_url:
\&pre_filter:
\&lookup_exclude:
\&prepend:
\&append:
\&display_filter:
\&default:
\&extended:
\
\&code:variable::Variable::FORUM_PRODUCTS
\&type:yesno
\&width:
\&height:
\&field:
\&db:
\&name:
\&outboard:
\&options:
\&attribute:
\&label:Enable Product Forums
\&help:This enables user comments on products in the flypage.
\&lookup:
\&filter:
\&help_url:
\&pre_filter:
\&lookup_exclude:
\&prepend:
\&append:
\&display_filter:
\&default:
\&extended:
.Ve
Add the following block to pages/flypage.html:
.PP
.Vb 15
\& [if variable FORUM_PRODUCTS]
\&
\&
\& [forum top="[item-code]" display_page="forum/display" /]
\&
\& [page href="forum/reply"
\& form="
\& product=1
\& mv_arg=[item-code]
\& "
\& ]Comment on this product.
\&
\&
\&
\& [/if]
.Ve
This would normally go at the end of the table displaying the product,
but you can place and edit to suit.
.PP
Again, all of this is provided if you have installed from the latest
Interchange 4.9.4 or higher.
.SH "The [forum] ITL Tag"
.IX Header "The [forum] ITL Tag"
The [forum] tag is what provides the capability. It uses the forum
table and follows tree-like threads in that table.
.PP
It has one required parameter, top. That gives the id of the
message that is the top of the thread to display.
.PP
This is a complete forum display for a product:
.PP
.Vb 1
\& [forum top="[item-code]" /]
.Ve
You will see something like that in the snip from
pages/flypage.html above.
.PP
You can pass many more parameters to the [forum] tag. Some of them
are:
.Ip "display-page" 4
.IX Item "display-page"
.PP
By default, the [forum ...] tag uses the current page to link to to
re-display the forum at another level. Normally this works fine, but
on a product flypage it will not work. You must pass in a different
page.
.PP
.Vb 1
\& [forum top="[item-code]" display-page="forum/display" /]
.Ve
.Ip "show-level" 4
.IX Item "show-level"
.PP
By default, [forum] only displays the text of top-level replies to
the current thread. If you want to display more levels, set the
show-level parameter to 1 or higher:
.PP
.Vb 1
\& [forum top="[data session arg]" show-level=3 /]
.Ve
The above will show the first four levels of replies, with links to
any further down the tree.
.Ip "scrub-score" 4
.IX Item "scrub-score"
.PP
If you want to moderate certain comments so that their text won't be
shown, you can set the scrub-score parameter to \-1 and then set the
score field in the message's database record to \-1. By default, it
is linked to with a message:
.PP
.Vb 1
\& One message beneath your threshold
.Ve
If you want to totally disable the appearance of the link and message,
set the scrub-template to something:
.PP
.Vb 4
\& [forum top=THREAD
\& scrub-score="-1"
\& scrub-template=""
\& /]
.Ve
.Ip "show-score" 4
.IX Item "show-score"
.PP
By default, if a message has a score of two or higher, it's text will
be shown no matter what level of display it is on. You can set that
threshold with this paramter.
.Ip "template" 4
.IX Item "template"
.PP
You can set the template that displays replies with this parameter.
You can also pass this as the container text for the [forum] tag,
i.e.:
.PP
.Vb 21
\& [forum top="[data session arg]"]
\&
\&
\&
\& {SUBJECT}
\& by {USERINFO}
\& on {DATE}
\&
\&
\& [
\& Reply
\& ]
\&
\&
\&
\&
\& {COMMENT}
\&
\&
\&
\& [/forum]
.Ve
See pages/forum/display.html for an example.
.Ip "header-template" 4
.IX Item "header-template"
.PP
You can set the header template that displays the top-level message
with this parameter. See pages/forum/display.html for an example.
.Ip "link-template" 4
.IX Item "link-template"
.PP
You can set the template that displays the links to messages that are
not shown with this parameter. See pages/forum/display.html for an
example.
.Ip "scrub-template" 4
.IX Item "scrub-template"
.PP
The template for a message that has a score lower than scrub-score.
See pages/forum/display.html for an example.
.Ip "threshold-message" 4
.IX Item "threshold-message"
.PP
The message displayed in the default scrub-template when a message
is scrubbed. If you set the scrub-template yourself, it is ignored.
.Ip "display-page" 4
.IX Item "display-page"
.PP
The page linked to with {\s-1DISPLAY_URL\s0}. Default is the current page.
See \fBTemplating\fR below.
.Ip "reply-page" 4
.IX Item "reply-page"
.PP
The page linked to with {\s-1REPLY_URL\s0}. Default is forum/reply.html.
See \fBTemplating\fR below.
.Ip "submit-page" 4
.IX Item "submit-page"
.PP
The page linked to with {\s-1SUBMIT_URL\s0}. Default is forum/submit.html.
See \fBTemplating\fR below.
.Ip "date-format" 4
.IX Item "date-format"
.PP
The format for the date provided with {\s-1DATE\s0}. Default is \f(CW%B\fR \f(CW%e\fR, \f(CW%Y\fR
@%H:%M, which provides a date like October 5, 2002 \f(CW@21:19\fR.
.SH "Templating"
.IX Header "Templating"
All of the [forum] display mechanisms are templated. You can pass
four templates \*(-- template, header-template, link-template,
and scrub-template.
.PP
They use the substitution style found in Interchange's attr-list
\&\s-1ITL\s0 tag.
.PP
The following values are available for templating:
.PP
.Vb 16
\& ADDITIONAL Additional text normally only used at the top level
\& COMMENT Text of the message
\& CREATED Created date in ISO format
\& DATE Date the comment was made
\& DISPLAY_URL URL to display the forum with a new starting point
\& FORUM_APPEND End indent tags for item (automatic, don't use)
\& FORUM_PREPEND Begin indent tags for item (automatic, don't use)
\& MOD_TIME Modified date in ISO format
\& PARENT_URL URL to call the parent of the comment
\& REASON Text indicating reason for scoring
\& REPLY_URL URL to reply to the commetn
\& SCORE Score of the article
\& SUBJECT Subject of the message
\& SUBMIT_URL URL to submit a new top-level thread
\& TOP_URL URL to call the top level of the thread (if not at top)
\& USERINFO User information based on login status and anonymity
.Ve
You can see how the above are used by examining the file
pages/forum/display.html and playing around with the provided
templates.
.Sh "Templating rules"
.IX Subsection "Templating rules"
{\s-1KEY\s0}
.PP
Inserts the value of the \s-1KEY\s0 for the reference. In a database query,
this is the column name.
.PP
{KEY|fallback string}
.PP
Displays the value of {\s-1KEY\s0} or if it is zero or blank, the fallback
string (i.e., default).
.PP
{\s-1KEY\s0 true string}
.PP
Displays true string if the value of {\s-1KEY\s0} is non-blank, non-zero,
or displays nothing if the key is false.
.PP
{\s-1KEY\s0?} true text {/KEY?}
.PP
Displays true text if the value of {\s-1KEY\s0} is non-blank, non-zero,
and nothing otherwise.
.PP
{\s-1KEY:\s0} false text {/KEY:}
.PP
Displays false text if the value of {\s-1KEY\s0} is blank or zero, and
nothing otherwise.
.PP
Copyright 2002\-2004 Mike Heins and Michael
Wilk . Freely redistributable under terms of
the \s-1GNU\s0 General Public License. line:
.PP
Interchange + QuickBooks \s-1HOWTO\s0
.SH "Introduction"
.IX Header "Introduction"
.Sh "Summary Description"
.IX Subsection "Summary Description"
Interchange QuickBooks \*(-- QuickBooks support for transactions and
items
.Sh "Audience"
.IX Subsection "Audience"
Users who already have Quickbooks setup and are familiar with it, in
addition to having the foundation (or other) catalog correctly
working.
.Sh "Contact the author"
.IX Subsection "Contact the author"
If you find any spelling errors, technical slip-ups, mistakes,
subliminal messages, or if you wish to send feedback, critique,
remarks, comments, or if you wish to contribute examples, instructions
for alternative platforms, chapters, or other material, please do so.
.PP
The preferred method of submitting changes is in the form of a context
diff against the \s-1SDF\s0 source file (ic_howto_qb.sdf). Please address
your correspondence to:
.PP
Volunteer Maintainer, Dan Browning \fIdb@kavod.com\fR
.PP
or
.PP
Original Author, Mike Heins \fImike@perusion.com\fR
.Sh "Version"
.IX Subsection "Version"
This document describes software based on Interchange 4.5 and later.
.SH "Description"
.IX Header "Description"
Interchange is a business-to-business and business-to-consumer
internet ordering and cataloguing product. It has the ability to take
orders via the World Wide Web, and store transaction data.
.PP
This document describes how to interface Interchange with QuickBooks,
the popular small-business accounting program from Intuit.
.PP
QuickBooks has an import/export format called \s-1IIF\s0, a mnemonic for
Intuit Interchange Format. Fitting, eh?
.PP
The standard capabilities of Interchange allow production of \s-1IIF\s0 files
for transaction passing. With some support from Interchange UserTags,
it can even import and export item listings.
.SH "Contents"
.IX Header "Contents"
The extension files can be found in the Interchange tarball under the
\&'extensions/quickbooks' directory. The following files are used
with this extension:
.PP
.Vb 4
\& usertag/import_quicken_items UserTag for importing items
\& usertag/export_quicken_items UserTag for exporting items
\& pages/admin/quickbooks/* Menu support for Interchange UI
\& qb.catalog.cfg Quickbooks configuration.
.Ve
.SH "Installation"
.IX Header "Installation"
To set up this extension, the basic steps are:
.Ip "\(bu" 4
Create and copy directories and files.
.Ip "\(bu" 4
Add additional database fields.
.Ip "\(bu" 4
Modify catalog.cfg with additions.
.Ip "\(bu" 4
Add \*(L"quickbooks\*(R" order route to checkout pages.
.Ip "\(bu" 4
Restart Interchange.
.Ip "\(bu" 4
Export your items from Interchange catalog (or import your existing
QuickBooks items to Interchange).
.Ip "\(bu" 4
Test.
.Sh "Terms and locations"
.IX Subsection "Terms and locations"
Several terms are used in the examples.
.Ip "Catalog Directory" 4
.IX Item "Catalog Directory"
This is the main directory for the catalog, where catalog.cfg resides.
It will have a \s-1NAME\s0, the name for the catalog. (Some common
Interchange demo names are foundation, construct, barry, and
simple.)
.Sp
Common locations:
.Sp
/var/lib/interchange/NAME /usr/local/interchange/catalogs/NAME
\&\f(CW$HOME\fR/catalogs/NAME
.Sp
We will use the path /var/lib/interchange/foundation in these
examples.
.Ip "Interchange software directory" 4
.IX Item "Interchange software directory"
This is the main directory for your Interchange server, where the file
interchange.cfg resides. Common locations:
.Sp
/usr/lib/interchange /usr/local/interchange \f(CW$HOME\fR/ic
.Sp
We will use the path /usr/lib/interchange in these examples.
.Ip "Interchange tarball directory" 4
.IX Item "Interchange tarball directory"
The quickbooks files are located in the untarred distribution file,
before installation of Interchange is performed.
.Ip "Interchange User" 4
.IX Item "Interchange User"
The Interchange daemon runs as a user \s-1ID\s0 that cannot be root. It will
require write permission on directories it must modify to do its work.
.Sp
We will use the user \s-1ID\s0 interch in these examples.
.Sh "Create and copy directories and files"
.IX Subsection "Create and copy directories and files"
This extension requires you to add some files to your catalog.
.PP
It is assumed you have tools and knowledge to create directories with
the proper permissions. Any directories that will contain varying
files like order transaction logs will require write permission for
the Interchange daemon user; pages and configuration only need have
read permission.
.Sh "Quick Installation Script"
.IX Subsection "Quick Installation Script"
This script will install the necessary files for you, provided that
you modify the variables to your environment. Alternately, you can
follow the more detailed installation instructions that follow it.
.PP
Note that if you are not using a 4.9.8+ version of Interchange, you
will need to manually install the qb_safe.filter by copying it from
the 4.9.8 code/Filter/qb_safe.filter into your Interchange version.
.PP
# Modify these three variables to match your environment.
export QB=/path/to/interchange/extensions/quickbooks
export VENDROOT=/usr/local/interchange
export CATROOT=/home/interch/catalogs/foundation
.PP
mkdir \-p \f(CW$CATROOT\fR/include/menus \f(CW$CATROOT\fR/vars
cp \-r \f(CW$QB\fR/TRANS_QUICKBOOKS \e
\f(CW$CATROOT\fR/vars
cp \-r \f(CW$QB\fR/pages/admin/quickbooks \e
\f(CW$CATROOT\fR/pages/admin
cp \-i \f(CW$QB\fR/usertag/* \e
\f(CW$VENDROOT\fR/code/UI_Tag
.PP
# Alternate usertag installation style:
#
#mkdir \-p \f(CW$CATROOT\fR/usertags/global
#cp \-i \f(CW$QB\fR/usertag/* \e
# \f(CW$CATROOT\fR/usertags/global
#
# Then include the global/*.tag in your interchange.cfg
.PP
# Variables that optionally modify the export process, along with
# their help entries.
cat \f(CW$QB\fR/products/variable.txt.append >> \e
\f(CW$CATROOT\fR/products/variable.txt
cat \f(CW$QB\fR/products/mv_metadata.asc.append >> \e
\f(CW$CATROOT\fR/products/mv_metadata.asc
.PP
# Menu entries: start with the existing menu, then add ours.
cp \-i \f(CW$VENDROOT\fR/lib/UI/pages/include/menus/Admin.txt \e
\f(CW$CATROOT\fR/include/menus
cat \f(CW$QB\fR/menus/Admin.txt.append >> \e
\f(CW$CATROOT\fR/include/menus/Admin.txt
.PP
# Some configuration changes.
cat >> \f(CW$CATROOT\fR/catalog.cfg <<\s-1EOF\s0
# Allows vars/TRANS_QUICKBOOKS
DirConfig vars
# You can remove these requires if you don't want to use the
# Quickbooks \s-1UI\s0 menu items
Require usertag import_quicken_items
Require usertag export_quicken_items
\&\s-1EOF\s0
.Sh "Admin \s-1UI\s0 Usage"
.IX Subsection "Admin UI Usage"
After successful installation, there should be a \*(L"Quickbooks\*(R" menu
item under the \*(L"Admin\*(R" category. From there, you can \*(L"generate \s-1IIF\s0
files\*(R", download them, and perform other Quickbooks-related tasks.
.Ip "Make orders directory" 4
.IX Item "Make orders directory"
Create the directory orders in your Catalog Directory if it doesn't
already exist. (It may be a symbolic link to another location.) It
must have write permission on it.
.Sp
cd /var/lib/interchange/foundation mkdir orders
.Sp
If you are doing this as root, also do:
.Sp
chown interch orders
.Sp
This directory is used to store the QuickBooks \s-1IIF\s0 files produced for
orders. The files are created with the form:
.Sp
qbYYYYMMDD.iif
.Sp
Each day will have a file, and when a day is complete you should
download the orders. (There are other schemes possible.)
.Ip "Copy pages" 4
.IX Item "Copy pages"
You will want the Interchange \s-1UI\s0 support if you are using the \s-1UI\s0. It
provides links for importing/exporting items, downloading and viewing
\&\s-1IIF\s0 files, and possibly other functions over time. At the \s-1UNIX\s0 command
line:
.Sp
cd /usr/lib/interchange/ cp \-r
extensions/quickbooks/pages/admin/quickbooks \e
/var/lib/interchange/foundation/pages
.Ip "Copy report generation file etc/trans_quickbooks" 4
.IX Item "Copy report generation file etc/trans_quickbooks"
This file is used to generate the \s-1IIF\s0 \fIfile\fR\|(s) for transaction import
into QuickBooks.
.Sp
cd /usr/lib/interchange/ cp extensions/quickbooks/etc/trans_quickbooks
\&\e /var/lib/interchange/foundation/etc
.Ip "Copy usertags" 4
.IX Item "Copy usertags"
If you want to use the \s-1UI\s0 item import/export, two usertags are
required. The easiest thing is just to copy them to the Interchange
software directory subdirectory lib/UI/usertag, which is #included
as a part of the \s-1UI\s0 configuration file.
.Sp
cd /usr/lib/interchange cp \-i extensions/quickbooks/usertag/*
lib/UI/usertag
.Sh "Additional database fields \*(-- userdb"
.IX Subsection "Additional database fields userdb"
If your catalog is not based on a 4.6+ version of the foundation
catalog, you may not have some of the additional database fields
necessary. If you want the user to retain their customer number, add
the following field to the \*(L"userdb\*(R" table:
.PP
customer_number
.PP
It can be an integer number field if your database needs that
information. To add the field in MySQL, you can issue the following
queries at the mysql prompt:
.PP
alter table userdb add column customer_number int;
.PP
If you don't add it, it just means that a new customer number will be
assigned every time.
.PP
\&\s-1WARNING\s0 If you are using Interchange \s-1DBM\s0 files and have live data it
is not recommended you add this field unless you are positive you will
not overwrite your data. If you are not a developer, get one to help
you. In any case, back up your userdb.gdbm or userdb.db file first.
.Sh "Additional database fields \*(-- inventory"
.IX Subsection "Additional database fields inventory"
Quicken also needs an account to debit for the split transactions it
uses to track item sales. If you don't create these fields to relate
to each \s-1SKU\s0, the account \*(L"Other Income\*(R" will be used in the exports.
.PP
Add the following fields to the \*(L"inventory\*(R" table:
.PP
account cogs_account
.PP
To add the fields in MySQL, you can issue the following queries at the
mysql prompt:
.PP
alter table inventory add column account char(20); alter table
inventory add column cogs_account char(20);
.PP
Other \s-1SQL\s0 databases will have similar facilities.
.PP
If you are using Interchange \s-1DBM\s0 files, just export the inventory
database, stop the Interchange server (to prevent corruption), add the
fields on the first line by editing the inventory.txt file, then
restart Interchange.
.Sh "Modify catalog.cfg with additions:"
.IX Subsection "Modify catalog.cfg with additions:"
Add the entries in qb.catalog.cfg to catalog.cfg (you can use an
include statement if you wish).
.PP
There are some Require directives to ensure that the needed UserTag
definitions are included in the catalog, as well as the Route which is
used
.Sh "Add quickbooks order route"
.IX Subsection "Add quickbooks order route"
In the Interchange \s-1UI\s0, there is a Preferences area \*(L"\s-1ORDER_ROUTES\s0\*(R". You
should add the quickbooks route. Place it after the transaction
logging step, i.e.
.PP
code \s-1ORDER_ROUTES\s0 Variable log quickbooks main copy_user
.PP
\&\s-1ADVANCED\s0, If you know Interchange Variable settings, you can add it
directly:
.PP
Variable \s-1ORDER_ROUTES\s0 log quickbooks main copy_user
.PP
Also, you can use other methods to set order routes. See the
Interchange reference documentation.
.Sh "Additional Variables"
.IX Subsection "Additional Variables"
Optionally, you may specify some variables that modify the behavior of
the Quickbooks export feature. Documentation for these variables is
provided via item-specific meta data, which can be added to your
mv_metadata.asc file for automatic display by the Admin \s-1UI\s0.
.PP
See the installation script at the top of this document for commands
that will append the empty variables to your variable.txt and the help
information to your mv_metadata.asc files.
.Sh "Restart the catalog"
.IX Subsection "Restart the catalog"
This can be done by restarting the Interchange server or by clicking
Apply Changes in the \s-1UI\s0.
.Sh "Export the items"
.IX Subsection "Export the items"
You can access the Quickbooks \s-1UI\s0 index by making your \s-1URL:\s0
.PP
http://YOURCATALOG_URL/admin/quickbooks/index
.PP
It will provide options for importing and exporting items. This is
necessary so QuickBooks will be able to take orders for your items.
.PP
QuickBooks uses the product \*(L"name\*(R" as an \s-1SKU\s0, along with an integer
reference number. Either you need to make your SKUs match the integer
reference number, or you must ensure your product title is unique.
.Sh "Test"
.IX Subsection "Test"
Place a test order on your Interchange catalog once you have finished
installing. You should find a file in the orders directory with the
name qbYYYYMMDD.iif. (YYYY=year, MM=month, DD=day.) Transfer this
file to your QuickBooks machine and run File/Import and select that
file as the source. This should import the customer and order into the
system. If it doesn't work, it may be due to lack of sales tax or
shipping definitions, discussed below.
.SH "Usage"
.IX Header "Usage"
.Sh "Accessing Admin \s-1UI\s0 Features"
.IX Subsection "Accessing Admin UI Features"
A typical installation will cause the Administrative User Interface
Features to become available via the top level menu:
.Ip "\(bu" 4
Login to the Admin \s-1UI\s0
.Ip "\(bu" 4
Administration
.Ip "\(bu" 4
Quickbooks
.PP
You should then be presented with a menu of the Admin \s-1UI\s0 features.
.Sh "Generating \s-1IIF\s0 Files"
.IX Subsection "Generating IIF Files"
To generate the \s-1IIF\s0 files, access the corresponding page from the
Admin \s-1UI\s0 Quickbooks Menu (Administration \-> Quickbooks \-> Generate \s-1IIF\s0
Files).
.PP
You will be presented with a query tool. Select the query options
that you would like and submit your query. Among the query options,
you have the option to input a \s-1QB\s0 transaction number. This will be
the first number that is used when generating the \s-1IIF\s0 files, and it
will be incremented for each sequential order in the query.
.PP
You will be notified of its success or failure. The resulting page
will:
.Ip "\(bu" 4
Inform you of the success or failure of the query.
.Ip "\(bu" 4
Provide a link to the \*(L"results\*(R" \s-1IIF\s0 file (which includes all of the
orders found by the query). Note that this \*(L"results\*(R" IIf file is
overwritten every time a query is run.
.Ip "\(bu" 4
Provide a link for each \s-1IIF\s0 file (one per order). This can be used as
a backup, or for importing one-by-one instead of all at once.
.SH "Discussion"
.IX Header "Discussion"
The interface provided works for the sample company data distributed
with QuickBooks. There are certain requirements to make sure it works
in your environment.
.PP
Also, you can change the configuration by editing the file
etc/trans_quickbooks to suit your \s-1IIF\s0 file needs.
.Sh "Sales Tax"
.IX Subsection "Sales Tax"
QuickBooks has a taxing system whereby tax rates are defined by
customer location. There is usually also a generic Sales Tax Item,
such as contained in the sample company data. This allows Interchange
to calculate the sales tax. If that item is not present then you will
need to create it, or specify your tax item using the
\&\s-1QB_SALES_TAX_ITEM\s0 variable.
.Sh "Shipping"
.IX Subsection "Shipping"
Interchange will add a generic item Shipping to each order that has
a shipping cost. Its \s-1MEMO\s0 field will contain the text description of
the mode. If that item is not in your QuickBooks item definitions,
then you must create it, or specify your shipping item using the
\&\s-1QB_SHIPPING_ITEM\s0 variable.
.Sh "Customer Imports"
.IX Subsection "Customer Imports"
To generate a QuickBooks transtype of \s-1INVOICE\s0, a \s-1CUSTOMER\s0 is required.
Interchange outputs a \s-1CUST\s0 \s-1IIF\s0 record for each sale with the customer
information. Since QuickBooks uses the customer name or company to
generate the unique listing, we place the Interchange username in
parentheses after the company or name.
.Sh "\s-1IIF\s0 generation at time of order"
.IX Subsection "IIF generation at time of order"
As of 4.9, the \s-1IIF\s0 generation was moved from an order route into the
Admin \s-1UI\s0. This was done so that the \s-1IIF\s0 generation process could be
fine tuned without restarting Interchange and placing an order. If
you need the \s-1IIF\s0 file generated at the time of order, you can still
access the pre-4.9.6 files in extensions/quickbooks/legacy.
.PP
Credits
.Ip "\(bu" 4
\&\fBMike Heins\fR: This document was copied from the original \s-1POD\s0
documentation (extensions/quickbooks/ic_qb.pod) written by Mike
Heins \fImike@perusion.com\fR.
.Ip "\(bu" 4
\&\fBDan Browning\fR: Updated by Dan Browning \fIdb@kavod.com\fR.
.PP
Document history
.Ip "\(bu" 4
July 20, 2002. Initial revision.
.PP
Resources
.PP
Documentation
.Ip "\(bu" 4
What are the \s-1IIF\s0 File Headers?
http://www.quickbooks.com/support/faqs/qbw2000/121756.html
.Ip "\(bu" 4
Also see the Quickbooks Help item, \*(L"Reference guide to import files\*(R"
.PP
Copyright 2002\-2004 Interchange Development Group. Freely
redistributable under terms of the \s-1GNU\s0 General Public License. line:
.PP
Advanced Interchange Topics
.SH "Advanced Interchange Topics"
.IX Header "Advanced Interchange Topics"
.Ip "\(bu" 4
Maintaining production Interchange servers
.Ip "\(bu" 4
Interchange Administration Tool Development
.Ip "\(bu" 4
Making catalog skeletons for use with makecat
.Ip "\(bu" 4
Building custom link programs
.Ip "\(bu" 4
Installation tips and troubleshooting
.Ip "\(bu" 4
Usertracking
.SH "Maintaining Interchange"
.IX Header "Maintaining Interchange"
Some utilities are supplied in the VendRoot/bin directory:
.PP
.Vb 6
\& compile_link Compiles an Interchange vlink or tlink CGI link
\& configdump Dumps the configuration directives for a particular catalog
\& dump Dumps the session file for a particular catalog
\& expire Expires sessions for a particular catalog
\& expireall Expires all catalogs
\& makecat Make catalog
.Ve
Some example scripts for other functions are in the eg/ directory
of the software distribution.
.PP
Some thought should be given to where the databases, error logs, and
session files should be located, especially on an \s-1ISP\s0 that might have
multiple users sharing an Interchange server. In particular, put all
of the session files and logs in a directory that is not writable by
the user. This eliminates the possibility that the catalog may crash
if the directory or file is corrupted.
.PP
To test the format of user catalog configuration files before
restarting the server, set (from VendRoot):
.PP
.Vb 1
\& bin/interchange -test
.Ve
This will check all configuration files for syntax errors, which might
otherwise prevent a catalog from booting. Once a catalog configures
properly, user reconfiguration will not crash it. It will just cause
an error. But, it must come up when the server is started.
.Sh "Starting, Stopping, and Re-starting the Servers"
.IX Subsection "Starting, Stopping, and Re-starting the Servers"
The following commands need to have \s-1VENDROOT\s0 changed to the main
directory where Interchange is installed. If the Interchange base
directory is /home/interchange/, the start command would be
/home/interchange/bin/interchange.
.PP
Do a perldoc VENDROOT/bin/interchange for full documentation.
.PP
To start the server with default settings:
.PP
.Vb 1
\& VENDROOT/bin/interchange
.Ve
Assuming the server starts correctly, the names of catalogs as they
are configured will be displayed, along with a message stating the
process \s-1ID\s0 it is running under.
.PP
It is usually best to issue a restart instead. It doesn't hurt to do a
restart if you're actually starting the first time. And, if a server
is already running (from this \s-1VENDROOT\s0), a new start attempt will
fail. To restart the server:
.PP
.Vb 1
\& VENDROOT/bin/interchange -restart
.Ve
The \-r option is the same as \-restart.
.PP
This is typically done to force Interchange to re-read its
configuration. A message will be displayed stating that a \s-1TERM\s0 signal
has been sent to the process \s-1ID\s0 the servers are running under. This
information is also sent to VENDROOT/error.log. Check the error.log
file for confirmation that the server has restarted properly.
.PP
To stop the server:
.PP
.Vb 1
\& VENDROOT/bin/interchange -stop
.Ve
A message will be displayed stating that a \s-1TERM\s0 signal has been sent
to the process \s-1ID\s0 the server is running under. This information is
also sent to VENDROOT/error.log.
.PP
Because processes waiting for selection on some operating systems
block signals, they may have to wait for HouseKeeping seconds to stop.
The default is 60.
.PP
To terminate the Interchange server with prejudice, in the event it
will not stop:
.PP
.Vb 1
\& VENDROOT/bin/interchange -kill
.Ve
.Sh "\s-1UNIX\s0 and \s-1INET\s0 modes"
.IX Subsection "UNIX and INET modes"
Both UNIX-domain and INET-domain sockets can be used for
communication. \s-1INET\s0 domain sockets are useful when more than one web
server, connected via a local-area network (\s-1LAN\s0), is used for
accessing an Interchange server.
.PP
\&\fBImportant note:\fR When sending sensitive information like credit card
numbers over a network, always ensure that the data is secured by a
firewall, or that the Interchange server runs on the same machine as
any SSL-based server used for encryption.
.PP
Use the \-i and \-u flags if you only want to use one
communication method:
.PP
.Vb 2
\& # Start only in UNIX mode
\& VENDROOT/bin/interchange -r -u
.Ve
.Vb 2
\& # Start only in INET mode
\& VENDROOT/bin/interchange -r -i
.Ve
.Sh "User Reconfiguration"
.IX Subsection "User Reconfiguration"
The individual catalogs can be reconfigured by the user by running the
[reconfig] support tag. This should be protected by one of the several
forms of Interchange authentication, preferably by \s-1HTTP\s0 basic
authorization. See RemoteUser.
.PP
The command line can be reconfigured (as the Interchange user) with:
.PP
.Vb 1
\& VENDROOT/bin/interchange --reconfig=catalog
.Ve
It is easy for the administrator to manually reconfigure a catalog.
Interchange simply looks for a file etc/reconfig (based in the
Interchange software directory) at HouseKeeping time. If it finds a
script name that matches one of the catalogs, it will reconfigure that
catalog.
.Sh "Expiring Sessions"
.IX Subsection "Expiring Sessions"
If Interchange is using \s-1DBM\s0 capability to store the sessions,
periodically expire old sessions to keep the session database file
from growing too large.
.PP
.Vb 1
\& expire -c catalog
.Ve
There is also an expireall script which reads all catalog entries
in interchange.cfg and runs expire on them. The expire script
accepts a \-r option which tells it to recover lost disk space.
.PP
On a \s-1UNIX\s0 server, add a crontab entry such as the following:
.PP
.Vb 2
\& # once a day at 4:40 am
\& 40 4 * * * perl /home/interchange/bin/expireall -r
.Ve
Interchange will wait until the current transaction is finished before
expiring, so this can be done at any time without disabling web
access. Any search paging files for the affected session (kept in
ScratchDir) will be removed as well.
.PP
If not running \s-1DBM\s0 sessions, use a Perl script to delete all files not
modified in the last one or two days. The following will work if given
an argument of a session directory or session files:
.PP
.Vb 2
\& #!perl
\& # expire_sessions.pl -- delete files 2 days old or older
.Ve
.Vb 5
\& my @files;
\& my $dir;
\& foreach $dir (@ARGV) {
\& # just push files on the list
\& if (-f $dir) { push @files, $_; next; }
.Ve
.Vb 1
\& next unless -d $dir;
.Ve
.Vb 4
\& # get all the file names in the directory
\& opendir DIR, $dir or die "opendir $dir: $!\en";
\& push @files, ( map { "$dir/$_" } grep(! /^\e.\e.?$/, readdir DIR));
\& }
.Ve
.Vb 8
\& for (@files) {
\& unless (-f $_) {
\& warn "skipping $_, not a file.\en";
\& next;
\& }
\& next unless -M $_ >= 2;
\& unlink $_ or die "unlink $_: $!\en";
\& }
.Ve
It would be run with a command invocation like:
.PP
.Vb 1
\& perl expire_sessions.pl /home/you/catalogs/simple/session
.Ve
Multiple directory names are acceptable, if there is more than one
catalog.
.PP
This script can be adjusted as necessary. Refinements might include
reading the file to \*(L"eval\*(R" the session reference and expire only
customers who are not members.
.Sh "My session files change to owner root every day!"
.IX Subsection "My session files change to owner root every day!"
You have the expireall \-r entry in the root crontab, and it should
either be in the Interchange user crontab or run as:
.PP
.Vb 1
\& 44 4 * * * su -c "/ICROOT/bin/expireall -r" ICUSERNAME
.Ve
.SH "Interchange Components"
.IX Header "Interchange Components"
Interchange components are merely portions of \s-1HTML/ITL\s0 that are
included into pages within the site depending on options set in the
Admin \s-1UI\s0. The default component set includes the following:
.PP
.Vb 14
\& best_horizontal
\&best_vertical
\&cart
\&cart_display
\&cart_tiny
\&category_vertical
\&cross_horizontal
\&cross_vertical
\&promo_horizontal
\&promo_vertical
\&random_horizontal
\&random_vertical
\&upsell_horizontal
\&upsell_vertical
.Ve
.Sh "Content \-> Page Edit"
.IX Subsection "Content -> Page Edit"
The Interchange Admin \s-1UI\s0 offers a page editor function that allows
component definitions and options to be modified for each page within
the catalog.
.PP
Template
.PP
The choices for the Template drop-down are read from template
definition files located in the CATROOT/template directory. These
files store the name and description of the template, as well as
components and options for the particular template.
.PP
To create a new template for use in the admin, it is best to copy an
existing template definition to a new file name and edit it's contents
to suit. Once the catalog is reconfigured, the new choice will be
visible within the Content Page Editor admin function.
.PP
Each template option is looped through and a scratch is set using its
same name and value.
.PP
\&\s-1ITL\s0 is used near the bottom of this file to set each option to default
values before the page is displayed.
.PP
.Vb 6
\& [set page_title][set]
\&[set page_banner][set]
\&[set members_only][set]
\&[set component_before][set]
\&[set component_after][set]
\&[set bgcolor]#FFFFFF[/set]
.Ve
Page Title
.PP
Sets the title of the page which is synonymous with the html
code.
.PP
The following code within the template definition file is used to
display this option within in the content editor:
.PP
page_title: description: Page title
.PP
This code dynamically adds the title to the page:
.PP
[scratch page_title]
.PP
Page Banner
.PP
Sets a textual title for each page which is called by [either][scratch
page_banner][or][scratch page_title][/either] This results in the Page
Banner being displayed if defined. Otherwise, the Page Title is used.
.PP
Members Only
.PP
The members only function is handled by the following code within each
template file:
.PP
.Vb 7
\& [if scratch members_only]
\& [set members_only][/set]
\& [if !session logged_in]
\& [set mv_successpage]@@MV_PAGE@@[/set]
\& [bounce page=login]
\& [/if]
\&[/if]
.Ve
This code says if members only is set to yes and the visitor is logged
in, display the page. Otherwise, redirect the visitor to the login
page.
.PP
Break 1
.PP
This code causes a separation in the Content Editor between the next
set of options. (A blue line)
.PP
Horizontal Before Component
.PP
This allows the inclusion of a defined component to be displayed
before, or above, the page's content. It is called with the following
code within the \s-1LEFTRIGHT_TOP\s0 template:
.PP
.Vb 4
\& [if scratch component_before]
\&[include file="templates/components/[scratch component_before]"]
\&[set component_before][/set]
\&[/if]
.Ve
Horizontal After Component
.PP
This function allows the inclusion of a defined component to be
displayed after or below the page's content. It's called with the
following code within the \s-1LEFTRIGHT_BOTTOM\s0 template:
.PP
.Vb 4
\& [if scratch component_after]
\&[include file="templates/components/[scratch component_after]"]
\&[set component_after][/set]
\&[/if]
.Ve
Horizontal Item Width
.PP
This setting allows you to choose how many items the horizontal
components display. For example, the horizontal best sellers component
uses this setting to randomly select the best sellers. Notice the
default to 2 if nothing is defined.
.PP
.Vb 1
\& random="[either][scratch component_hsize][or]2[/either]"
.Ve
Special Tag
.PP
This setting is only viable when a promotion is used for a horizontal
component. It tells the promotional component which rows to evaluate
in the merchandising table for display within the component. This
setting normally correlates to the featured column of the
merchandising table as follows:
.PP
.Vb 6
\& [query arrayref=main
\& sql="
\& SELECT sku,timed_promotion,start_date,finish_date
\& FROM merchandising
\& WHERE featured = '[scratch hpromo_type]'
\& "][/query]
.Ve
Before/After Banner
.PP
Allows a title for the horizontal components to be defined to
displayed in a header above the component's items. It is called with
the [scratch hbanner] tag.
.PP
Break 2
.PP
This code causes a separation in the Content Editor between the next
set of options. (A blue line)
.PP
Vertical Component
.PP
Defines a component to be displayed along the right side of the
\&\s-1LEFTRIGHT_BOTTOM\s0 template. It is called from the template with the
following code:
.PP
.Vb 1
\& [include file="templates/components/[scratch component_right]"]
.Ve
Vertical Items Height
.PP
Sets the number of items to display within the vertical component.
Called with the following code:
.PP
.Vb 1
\& random="[either][scratch component_vsize][or]3[/either]"
.Ve
Right Banner
.PP
Allows a title to be set for a vertical component which is displayed
as a header above the items in the vertical component. It's called
with the [scratch vbanner] tag.
.PP
Special Tag
.PP
Essentially the same as the Special Tag setting described in item
number 9 above.
.PP
Background Color
.PP
Allows the background color of the page to be selected. The choices
are stored within the page or template definition as in:
.PP
.Vb 4
\& bgcolor:
\& options: #FFFFFF=White,pink=Pink
\& widget: select
\& description: Background color
.Ve
Content
.PP
Allows the page code to be downloaded, uploaded and viewed/edited.
Only the code between and
is displayed or can be edited here.
.PP
Preview, Save, and Cancel buttons
.PP
Allows the changes to the edited page to be previewed in a pop-up
browser window, or saved. Cancel returns you to the page editor
selection page.
.PP
Save template in page
.PP
Template settings are stored in the template definitions by default.
This allows a common set of choices for template settings for all
pages. If specific setting options are desired for a page, the
template can be saved within the page so that it may have individual
options.
.PP
The in-page template definition must be surrounded by [comment]
[/comment].
.Sh "Custom Admin \s-1UI\s0 Options"
.IX Subsection "Custom Admin UI Options"
Other options may be added to the template by defining them in the
default definition file, or using in-page definitions.
.PP
When the following lines are added to the template definition, the new
option is added to the Admin \s-1UI\s0.
.PP
.Vb 5
\& option_name:
\&options: 1,2*,3
\&widget: select
\&description: Option Description
\&help: Other Details
.Ve
Each time the template is used, an option_name scratch variable is
created. (Called with: [scratch option_name].) This scratch value will
be equal to what's selected here in the admin tool.
.PP
The possible widgets include:
.PP
.Vb 4
\& break - produces the blue line separator.
\&radio - produces radio button type selections.
\&select - standard drop-down selector.
\&move_combo - select drop down with options and text input for new option.
.Ve
.SH "Administrative Pages"
.IX Header "Administrative Pages"
With Interchange's GlobalSub capability, very complex add-on
schemes can be implemented with Perl subroutines. And with the new
writable database, pages that modify the catalog data can be made. See
MasterHost, RemoteUser, and Password.
.PP
In addition, any Interchange page subdirectory can be protected from
access by anyone except the administrator if a file called '.access'
is present and non-zero in size.
.Sh "Controlling Access to Certain Pages"
.IX Subsection "Controlling Access to Certain Pages"
If the directory containing the page has a file .access and that
file's size is zero bytes, access can be gated in one of several ways.
.Ip "1." 4
If the file .access_gate is present, it will be read and scanned
for page-based access. The file has the form:
.Sp
.Vb 1
\& page: condition
.Ve
.Ip "" 4
The page is the file name of the file to be controlled (the .html
extension is optional). The condition is either a literal Yes/No
or Interchange tags which would produce a Yes or No (1/0 work
just fine, as do true/false).
.Sp
The entry for * sets the default action if the page name is not
found. If pages will be allowed by default, set it to 1 or Yes.
If pages are to be denied by default in this directory, leave blank or
set to No. Here is an example, for the directory controlled,
having the following files:
.Sp
.Vb 1
\& -rw-rw-r-- 1 mike mike 0 Jan 8 14:19 .access
.Ve
.Ip "" 4
The contents of .access_gate:
.Sp
.Vb 1
\& foo.html: [if session username eq 'flycat']
.Ve
.Ip "" 4
The page controlled/foo is only allowed for the logged-in user
\&\fBflycat\fR.
.Sp
The page controlled/bar is allowed for the logged-in user
\&\fBflycat\fR, or if the scratch variable allow_bar is set to a
non-blank, non-zero value.
.Sp
The page controlled/baz is always allowed for display.
.Sp
The page controlled/any (or any other page in the directory not
named in .access_gate) will be allowed for any user logged in via
\&\fIUserDB\fR.
.Ip "2." 4
If the Variable \s-1MV_USERDB_REMOTE_USER\s0 is set (non-zero and
non-blank), any user logged in via the UserDB feature will receive
access to all pages in the directory. \s-1NOTE:\s0 If there is a
\&.access_gate file, it overrides this.
.Ip "3." 4
If the variables \s-1MV_USERDB_ACL_TABLE\s0 is set to a valid database
identifier, the UserDB module can control access with simple \s-1ACL\s0
logic. See \s-1USER\s0 \s-1DATABASE\s0. \s-1NOTE:\s0 If there is a .access_gate file, it
overrides this. Also, if \s-1MV_USERDB_REMOTE_USER\s0 is set, this
capability is not available.
.Sh "display tag and mv_metadata"
.IX Subsection "display tag and mv_metadata"
Interchange can store meta information for selected columns of tables
in a site's database. This meta information is used when the user
interacts with the database. For example, the meta information for a
Hide Item field might specify that a checkbox be displayed when the
user edits that field, since the only reasonable values are on and
off. Or, the meta information might specify a filter on data
entered for a Filename field which makes sure that the characters
entered are safe for use in a filename.
.PP
Widget type specifies the \s-1HTML\s0 \s-1INPUT\s0 tag type to use when
displaying the field in, say, the item editor.
.PP
Width and Height only apply to some of the Widget type
options, for instance the Textarea widget.
.PP
Label is displayed instead of the internal column name. For
example, the category column of the products table might have a
label of Product Category.
.PP
Help is displayed below the column label, and helps describe the
purpose of the field to the user.
.PP
Help url can be used to link to a page giving more information on
the field.
.PP
Lookup can be used when a field is acting like a foreign key into
another table. In that case, use some sort of select box as the widget
type, and if referencing multiple rows in the destination table, use a
multi select box, with colons_to_null as the pre_filter, and
:: as the lookup_exclude.
.PP
Filter and pre_filter can be used to filter data destined for
that field or data read from that field, respectively.
.PP
Repeat?: The Interchange back office \s-1UI\s0 uses the mv_metadata table to
discover formatting information for field, table, and view display.
The information is kept in fields in the mv_metadata table, and is
used to select the display, the \s-1HTML\s0 input type, the size (height and
width where appropriate), label, help text, additional help \s-1URL\s0, and
default value display.
.PP
It works in conjunction with the [display ...] usertag defined in the
Interchange \s-1UI\s0 as well as in specific pages in the \s-1UI\s0. The [display]
tag has this syntax:
.PP
[display table=tablename column=fieldname key=key arbitrary=tag
filter=op ...]
.PP
In the simplest use, the formatting information for a table form field
is called with:
.Ip "" 4
[display table=products column=category key=\*(L"os28007\*(R"]
.PP
The mv_metadata table is scanned for the following keys:
.PP
.Vb 2
\& products::category::os28007
\& products::category
.Ve
If a row is found with one of those keys, then the information in the
row is used to set the display widget. If no row is found, an \s-1INPUT\s0
TYPE=TEXT widget is displayed. If the data is all digits, a size of 8
is used, otherwise the size is 60.
.PP
If the following row were found (not all fields shown, would be
tab-separated in the actual data):
.PP
.Vb 2
\& code type width height label options
\& products::category text 20 Category
.Ve
Then this would be output:
.PP
.Vb 1
\&
.Ve
If the following row were found:
.PP
.Vb 2
\& code type width height label options
\& products::category select Category =none, product=Hardware
.Ve
Then the following would be output:
.PP
.Vb 4
\&
\& none
\& Hardware
\&
.Ve
The standard widget types are:
.Ip "text" 4
.IX Item "text"
The default. Uses the fields:
.Sp
.Vb 1
\& width size of input box
.Ve
.Ip "textarea" 4
.IX Item "textarea"
Format a <\s-1TEXTAREA\s0> pair. Uses the fields:
.Sp
.Vb 1
\& width COLS for textarea
.Ve
.Ip "select" 4
.IX Item "select"
Format a <\s-1SELECT\s0> pair with appropriate options. Uses the
fields:
.Sp
.Vb 1
\& height SIZE for select
.Ve
.SH "Usertag Reference"
.IX Header "Usertag Reference"
Admin Tool-specific usertags.
.SH "Admin Tool Database Tables"
.IX Header "Admin Tool Database Tables"
.Sh "mv_metadata.asc"
.IX Subsection "mv_metadata.asc"
.Vb 67
\& code
\& Table::Column to be operated on.
\& Database table
\& type
\& Widget type (Select the basic display type for the field)
\& textarea = Textarea
\& text = Text Entry (default)
\& select = Select Box
\& yesno = Yes/No (Yes=1)
\& noyes = No/Yes (No=1)
\& multiple = Multiple Select
\& combo = Combo Select
\& reverse_combo = Reverse Combo
\& move_combo = Combo move
\& display = Text of option
\& hidden_text = Hidden(show text)
\& radio = Radio box
\& radio_nbsp = Radio (nbsp)
\& checkbox = Checkbox
\& check_nbsp = Checkbox (nbsp)
\& imagedir = Image listing
\& imagehelper = Image upload
\& date = Date selector
\& value = Value
\& option_format = Option formatter
\& show = Show all options
\& width
\& Width (SIZE for TEXT, COLS for TEXTAREA, Label limit for SELECT)
\& height
\& Height (SIZE for SELECT, ROWS for TEXTAREA)
\& field
\& Field for lookup (can be two comma separated fields, in which
\& case second is used as the label text. Both must be in the
\& same table.)
\& db
\& name
\& Variable name (normally left empty, changes variable name to
\& send in form)
\& outboard
\& Select directory for image listing widget
\& options
\& options in the format value=label*
\& attribute
\& Column name (Do not set this.)
\& label
\& help
\& Help (displays at top of page)
\& lookup
\& Lookup select (Whether lookup is performed to get options for a
\& select type. If nothing is in the field, then used as the name
\& of the field to lookup in. Use lookup table if you want to look
\& up in a different table.
\& filter
\& Filters (Filters which can transform or constrain your data.
\& Some widgets require filters.)
\& help_url
\& Help URL (links below help text)
\& A URL which will provide more help
\& pre_filter
\& lookup_exclude
\& ADVANCED: regular expression that excludes certain keys from the lookup
\& prepend
\& append
\& Append HTML (HTML to be appended to the widget. Will substitute
\& in the macros _UI_TABLE_, _UI_COLUMN_, _UI_KEY_, and _UI_VALUE_,
\& and will resolve relative links with absolute links.)
\& display_filter
.Ve
.SH "makecat \- Set Up a Catalog from a Template"
.IX Header "makecat - Set Up a Catalog from a Template"
After Interchange is installed, you need to set up at least one
catalog. Interchange will not function properly until a catalog is
created.
.PP
The supplied makecat script, which is in the Interchange program
directory bin, is designed to set up a catalog based on the user's
server configuration. It interrogates the user for parameters like
which directories to use, a \s-1URL\s0 to base the catalog in, \s-1HTTP\s0 server
definitions, and file ownership. It gives relevant examples of the
entries it expects to receive.
.PP
\&\fBNote: \fRA catalog can only be created once. All further configuration
is done by editing the files within the catalog directory.
.PP
The makecat script requires a catalog skeleton to work from. The
Foundation demo is distributed with Interchange. See the icfoundation
document for information on building the Foundation demo store. Other
demo catalogs are available at http://www.icdevgroup.org/.
.PP
It is not normally necessary for you to understand how to build
catalog skeletons for use with makecat, but the following information
will help you if you should ever need to.
.Sh "Catalog Skeletons"
.IX Subsection "Catalog Skeletons"
A catalog skeleton contains an image of a configured catalog. The best
way to see what the makecat program does is to configure the simple
demo and then run a recursive diff on the template and configured
catalog directories:
.PP
.Vb 2
\& cd /usr/local/interchange
\& diff -r construct catalogs/construct
.Ve
The files are mostly identical, except that certain macro strings have
been replaced with the answers given to the script. For example, if
www.mydomain.com was answered at the prompt for a server name, this
difference would appear in the catalog.cfg file:
.PP
.Vb 2
\& # template
\& Variable SERVER_NAME __MVC_SERVERNAME__
.Ve
.Vb 2
\& # configured catalog
\& Variable SERVER_NAME www.mydomain.com
.Ve
The macro string _\|_MVC_SERVERNAME_\|_ was substituted with the answer to
the question about server name. In the same way, other variables are
substituted, and include:
.PP
.Vb 9
\& MVC_BASEDIR MVC_IMAGEDIR
\& MVC_CATROOT MVC_IMAGEURL
\& MVC_CATUSER MVC_MAILORDERTO
\& MVC_CGIBASE MVC_MINIVENDGROUP
\& MVC_CGIDIR MVC_MINIVENDUSER
\& MVC_CGIURL MVC_SAMPLEHTML
\& MVC_DEMOTYPE MVC_SAMPLEURL
\& MVC_DOCUMENTROOT MVC_VENDROOT
\& MVC_ENCRYPTOR
.Ve
\&\fBNote: \fRNot all of these variables are present in the \*(L"construct\*(R"
template, and more may be defined. In fact, any environment variable
that is set and begins with \s-1MVC_\s0 will be substituted for by the
makecat script. For example, to set up a configurable parameter to
customize the \s-1COMPANY\s0 variable in catalog.cfg, run a pre-qualifying
script that set the environment variable \s-1MVC_COMPANY\s0 and then place in
the catalog.cfg file:
.PP
Variable \s-1COMPANY\s0 _\|_MVC_COMPANY_\|_
.PP
All files within a template directory are substituted for macros, not
just the catalog.cfg file. There are two special directories named
html and images. These will be recursively copied to the
directories defined as SampleHTML and ImageDir.
.PP
\&\fBNote: \fRThe template directory is located in the Interchange software
directory, i.e., where interchange.cfg resides. Avoid editing files
in the template directory. To create a new template, it is recommended
that it should be named something besides 'construct' and a copy of
the construct demo directory be used as a starting point. Templates
are normally placed in the Interchange base directory, but can be
located anywhere. The script will prompt for the location if it cannot
find a template.
.PP
In addition to the standard parameters prompted for by Interchange,
and the standard catalog creation procedure, four other files in the
config directory of the template may be defined:
.PP
.Vb 4
\& additional_fields -- file with more parameters for macro substitution
\& additional_help -- extended description for the additional_fields
\& precopy_commands -- commands passed to the system prior to catalog copy
\& postcopy_commands -- commands passed to the system after catalog copy
.Ve
All files are paragraph-based. In other words, a blank line (with no
spaces) terminates the individual setting.
.PP
Additional fields
.PP
The additional_fields file contains:
.PP
.Vb 3
\& PARAM
\& The prompt. Set PARAM to?
\& The default value of PARAM^IAlternate value of PARAM
.Ve
This would cause a question during makecat:
.PP
.Vb 1
\& The prompt. Set PARAM to?.....[The default value of PARAM]
.Ve
The default value line can contain alternate values, separated by tabs
from the default value. (The default value may not contain a \s-1TAB\s0
character.) This will allow command-line editing to cycle between the
different values \*(-- usually with the \s-1UP\s0 and \s-1DOWN\s0 arrow keys.
.PP
If you wish to set the parameter to the default value in this file
without a prompt, precede the parameter with an exclamation point,
i.e.:
.PP
.Vb 3
\& !PARAM
\& The prompt. Set PARAM to?
\& default value^Ialternate value
.Ve
If you wish only to prompt for a value if a previous parameter was
set, put the previous parameter to set in curly brackets before the
actual parameter:
.PP
.Vb 3
\& {MYSQL}SQLDSN
\& Data source name (DSN) for MySQL?
\& dbi:mysql:test___MVC_CATALOGNAME__
.Ve
The above will be ignored if the \s-1MYSQL\s0 parameter was not previously
set to a true value.
.PP
Note that information collected in the main makecat run (in this case,
the catalog name) can be inserted via macro substitution.
.PP
Additional help
.PP
If the additional_help file is present, additional instructions for
\&\s-1PARAM\s0 may be provided.
.PP
.Vb 1
\& PARAM
.Ve
.Vb 2
\& These are additional instructions for PARAM, and they
\& may span multiple lines up to the first blank line.
.Ve
The prompt would now be:
.PP
.Vb 2
\& These are additional instructions for PARAM, and they
\& may span multiple lines up to the first blank line.
.Ve
.Vb 1
\& The prompt. Set PARAM to?.....[The default value of PARAM]
.Ve
Command files
.PP
If the file config/precopy_commands exists, it will be read as a
command followed by the prompt/help value.
.PP
.Vb 3
\& mysqladmin create __MVC_CATALOGNAME__
\& We need to create an SQL database for your Interchange
\& database tables.
.Ve
This will cause the prompt:
.PP
.Vb 2
\& We need to create an SQL database for your Interchange
\& database tables.
.Ve
.Vb 1
\& Run command "mysqladmin create simple"?
.Ve
If the response is \*(L"y\*(R" or \*(L"yes,\*(R" the command will be run by passing it
through the Perl \fIsystem()\fR function. As with any of the additional
configuration files, \s-1MVC_PARAM\s0 macro substitution is performed on the
command and help. Proper permissions for the command are required.
.PP
The file config/postcopy_commands is exactly the same as
, except the prompt occurs after the catalog files
are copied and macro substitution is performed on all files.
.PP
There may also be SubCatalog directives:
.PP
.Vb 1
\& SubCatalog easy simple /home/catalogs/simple /cgi-bin/easy
.Ve
easy
.Ip "" 4
The name of the subcatalog, which also controls the name of the
subcatalog configuration file. In this case, it is easy.cfg.
.PP
simple
.Ip "" 4
The name of the base configuration that will be the basis for the
catalog. Parameters in the easy.cfg file that are different will
override those in the catalog.cfg file for the base configuration.
.PP
The remaining parameters are similar to the Catalog directive.
.PP
Additional interchange.cfg parameters set up administrative parameters
that are catalog wide. See the server configuration file for details
on each of these.
.PP
Each catalog can be completely independent with different databases,
or catalogs can share pages, databases, and session files. This means
that several catalogs can share the same information, allowing
\&\*(L"virtual malls.\*(R"
.Sh "Manual Installation of Catalogs"
.IX Subsection "Manual Installation of Catalogs"
An Interchange installation is complex, and requires quite a few
distinct steps. Normally you will want to use the interactive catalog
builder, makecat, described above. It makes the process much
easier. Please see the iccattut document for a full tutorial on
building a catalog by hand.
.SH "Link Programs"
.IX Header "Link Programs"
Interchange requires a web server that is already installed on a
system. It does have an internal server which can be used for
administration, testing, and maintenance, but this will not be useful
or desirable in a production environment.
.PP
As detailed previously, Interchange is always running in the
background as a daemon, or resident program. It monitors either a
UNIX-domain file-based socket or a series of INET-domain sockets. The
small \s-1CGI\s0 link program, called in the demo simple, is run to
connect to one of those sockets and provide the link to a browser.
.PP
\&\fBNote: \fRSince Apache is the most popular web server, these
instructions will focus on it. If using another type of web server,
some translation of terms may be necessary.
.PP
A ScriptAlias or other \s-1CGI\s0 execution capability is needed to use
the link program. (The default ScriptAlias for many web servers is
/cgi-bin.) If ExecCGI is set for all directories, then any
program ending in a particular file suffix (usually .cgi) will be
seen as a \s-1CGI\s0 program.
.PP
Interchange, by convention, names the link program the same name as
the catalog \s-1ID\s0, though this is not required. In the distribution demo,
this would yield a program name or \s-1SCRIPT_PATH\s0 of /cgi-bin/simple
or /simple.cgi. This \s-1SCRIPT_PATH\s0 can be used to determine which
Interchange catalog will be used when the link program is accessed.
.Sh "UNIX-Domain Sockets"
.IX Subsection "UNIX-Domain Sockets"
This is a socket which is not reachable from the Internet directly,
but which must come from a request on the server. The link program
vlink is the provided facility for such communication with
Interchange. This is the most secure way to run a catalog, for there
is no way for systems on the Internet to interact with Interchange
except through its link program.
.PP
The most important issue with UNIX-domain sockets on Interchange is
the permissions with which the \s-1CGI\s0 program and the Interchange server
run. To improve security, Interchange normally runs with the socket
file having 0600 permissions (rw\-\-\-\-\-\-\-), which mandates that the \s-1CGI\s0
program and the server run as the same user \s-1ID\s0. This means that the
vlink program must be \s-1SUID\s0 to the same user \s-1ID\s0 as the server
executes under. (Or that \s-1CGIWRAP\s0 is used on a single catalog system).
.PP
With Interchange's multiple catalog capability, the permissions
situation gets a bit tricky. Interchange comes with a program,
makecat, which configures catalogs for a multiple catalog system.
It should properly set up ownership and permissions for multiple users
if run as the superuser.
.Sh "INET-Domain Sockets"
.IX Subsection "INET-Domain Sockets"
These are sockets which are reachable from the Internet directly. The
link program tlink is the provided facility for such communication
with Interchange. Other browsers can talk to the socket directly if
mapped to a catalog with the global TcpMap directive. To improve
security, Interchange usually checks that the request comes from one
of a limited number of systems, defined in the global TcpHost
directive. (This check is not made for the internal \s-1HTTP\s0 server.)
.Sh "Internal \s-1HTTP\s0 Server"
.IX Subsection "Internal HTTP Server"
If the socket is contacted directly (only for INET-domain sockets),
Interchange will perform the \s-1HTTP\s0 server function itself, talking
directly to the browser. It can monitor any number of ports and map
them to a particular catalog. By default, it only maps the special
catalog mv_admin, which performs administrative functions. The default
port is 7786, which is the default compiled into the distribution
tlink program. This port can be changed via the TcpMap directive.
.PP
To prevent catalogs that do not wish access to be made in this way
from being served from the internal server, Interchange has a fixed
\&\s-1SCRIPT_PATH\s0 of /catalogname (/simple for the distribution demo)
which needs to be placed as an alias in the Catalog directive to
enable access. See TcpMap for more details.
.Sh "Setting Up \s-1VLINK\s0 and \s-1TLINK\s0"
.IX Subsection "Setting Up VLINK and TLINK"
The vlink and tlink programs, compiled from vlink.c and
tlink.c, are small C programs which contact and interface to a
running Interchange daemon. The \s-1VLINK\s0 executable is normally made
setuid to the user account which runs Interchange, so that the
UNIX-domain socket file can be set to secure permissions (user
read-write only). It is normally not necessary for the user to do
anything. They will be compiled by the configuration program. If the
Interchange daemon is not running, either of the programs will display
a message indicating that the server is not available. The following
defines in the produced config.h should be set:
.Ip "\s-1LINK_FILE\s0" 4
.IX Item "LINK_FILE"
Set this to the name of the socket file that will be used for
configuration, usually \*(L"/usr/local/lib/interchange/etc/socket\*(R" or the
\&\*(L"etc/socket\*(R" under the directory chosen for the VendRoot.
.Ip "\s-1LINK_HOST\s0" 4
.IX Item "LINK_HOST"
Set this to the \s-1IP\s0 number of the host which should be contacted. The
default of 127.0.0.1 (the local machine) is probably best for many
installations.
.Ip "\s-1LINK_PORT\s0" 4
.IX Item "LINK_PORT"
Set this to the \s-1TCP\s0 port number that the Interchange server will
monitor. The default is 7786 (the decimal \s-1ASCII\s0 codes for 'M' and 'V')
and does not normally need to be changed.
.Ip "\s-1LINK_TIMEOUT\s0" 4
.IX Item "LINK_TIMEOUT"
Set this to the number of seconds vlink or tlink should wait
before announcing that the Interchange server is not running. The
default of 45 is probably a reasonable value.
.Sh "Compiling \s-1VLINK\s0 and \s-1TLINK\s0"
.IX Subsection "Compiling VLINK and TLINK"
There is a compile_link program which will assist with this. Do:
.PP
.Vb 1
\& perldoc VENDROOT/bin/compile_link
.Ve
for its documentation.
.Sh "Manually Compiling \s-1VLINK\s0 and \s-1TLINK\s0"
.IX Subsection "Manually Compiling VLINK and TLINK"
Change directories to the src directory, then run the \s-1GNU\s0 configure
script:
.PP
.Vb 2
\& cd src
\& ./configure
.Ve
There will be some output displayed as the configure script checks the
system. Then, compile the programs:
.PP
.Vb 1
\& perl compile.pl
.Ve
To compile manually:
.PP
.Vb 2
\& cc vlink.c -o vlink
\& cc tlink.c -o tlink
.Ve
On manual compiles, ensure that the C compiler will be invoked
properly with this little ditty:
.PP
.Vb 2
\& perl -e 'do "syscfg"; system("$CC $LIBS $CFLAGS $DEFS -o tlink tlink.c");'
\& perl -e 'do "syscfg"; system("$CC $LIBS $CFLAGS $DEFS -o vlink vlink.c");'
.Ve
On some systems, the executable can be made smaller with the strip
program, if available. It is not required.
.PP
.Vb 2
\& strip vlink
\& strip tlink
.Ve
If Interchange is to run under a different user account than the
individual configuring the program, make that user the owner of
vlink. Do not make vlink owned by root, because making vlink
\&\s-1SETUID\s0 root is an huge and unnecessary security risk. It should also
not normally run as the default Web user (often nobody or
http)).
.PP
.Vb 1
\& chown interchange vlink
.Ve
Move the vlink executable to the cgi-bin directory:
.PP
.Vb 1
\& mv vlink /the/cgi-bin/directory
.Ve
Make vlink \s-1SETUID:\s0
.PP
.Vb 1
\& chmod u+s /the/cgi-bin/directory/vlink
.Ve
Most systems unset the \s-1SUID\s0 bit when moving the file, so change it
after moving.
.PP
The \s-1SCRIPT_NAME\s0, as produced by the \s-1HTTP\s0 server, must match the name
of the program. (As usual, let the makecat program do the work.)
.Sh "\s-1VLINK\s0 or \s-1TLINK\s0 Compile Problems"
.IX Subsection "VLINK or TLINK Compile Problems"
The latest version of vlink.c and tlink.c have been compiled on
the following systems:
.PP
.Vb 12
\& AIX 4.1
\& BSD2.0 (Pentium/x86)
\& Debian GNU/Linux
\& Digital Unix (OSF/Alpha)
\& FreeBSD 2.x, 3.x, 4.x
\& IRIX 5.3, IRIX 6.1
\& OpenBSD 2.7
\& Red Hat Linux 6.2, 7.0, 7.1, 7.2, 7.3, 8.0
\& SCO OpenServer 5.x
\& Solaris 2.x (Sun compiler and GCC)
\& Solaris 7 (Sun compiler and GCC)
\& SunOS 4.1.4
.Ve
Some problems may occur. In general, ignore warnings about pointers.
.PP
Make sure that you have run the configure program in the src
directory. If you use Interchange's makecat program, it will try to
compile an appropriate link at that time, and will substitute tlink.pl
if that doesn't work.
.PP
You can compile manually with the proper settings with this series of
commands:
.PP
.Vb 4
\& cd src
\& ./configure
\& perl -e 'do "syscfg"; system ("$CC $CFLAGS $DEFS $LIBS -o tlink tlink.c")'
\& perl -e 'do "syscfg"; system ("$CC $CFLAGS $DEFS $LIBS -o vlink vlink.c")'
.Ve
There is also a compile_link program which has documentation
embedded and which will compile an appropriate link. If you cannot
compile, try using the tlink.pl script, written in Perl instead of
C, which should work on most any system. Since vlink needs to have
values set before compilation, a pre-compiled version will not work
unless it has the exact values you need on your system. If you can use
the defaults of 'localhost' and port 7786, you may be in luck.
.SH "Installing Perl Modules without Root Access"
.IX Header "Installing Perl Modules without Root Access"
Installing Interchange without root access is no problem. However,
installing Perl modules without root access is a little trickier.
.PP
You must build your makefile to work in your home dir. Something like:
.PP
.Vb 7
\& PREFIX=~/usr/local \e
\&INSTALLPRIVLIB=~/usr/local/lib/perl5 \e
\&INSTALLSCRIPT=~/usr/local/bin \e
\&INSTALLSITELIB=~/usr/local/lib/perl5/site_perl \e
\&INSTALLBIN=~/usr/local/bin \e
\&INSTALLMAN1DIR=~/usr/local/lib/perl5/man \e
\&INSTALLMAN3DIR=~/usr/local/lib/perl5/man/man3
.Ve
Put this in a file, say 'installopts', and use it for the Makefile.PL.
.PP
.Vb 1
\& perl Makefile.PL `cat installopts`
.Ve
Then, forget ./config. Just do:
.PP
.Vb 3
\& make
\&make test
\&make install
.Ve
Some of the tests may fail, but that's probably ok.
.PP
Also make sure to install Bundle::Interchange, which will need the
same config data as you put into 'installopts'.
.SH "Installation Troubleshooting"
.IX Header "Installation Troubleshooting"
Interchange uses the services of other complex programs, such as Perl,
Web servers, and relational databases, to work. Therefore, when there
is a problem, check these programs before checking Interchange. Many
more basic installation problems have to do with those than with
Interchange itself.
.PP
If an error message is received about not being able to find
libraries, or a core dump has occurred, or a segment fault message, it
is always an improperly built or configured Perl. Contact the system
administrator or install a new Perl.
.PP
The makecat program is intended to be used to create the starting
point for the catalog. If the demo does not work the first time, keep
trying. If it still does not work, try running in \s-1INET\s0 mode.
.PP
Check the two error log files: error.log in the Interchange home
directory (where interchange.cfg resides) and error.log in the
catalog directory (where catalog.cfg resides; there can be many of
these). Many problems can be diagnosed quickly if these error logs are
consulted.
.PP
Check the \s-1README\s0 file, the \s-1FAQ\s0, and mail list archive at the official
Interchange web site for information:
.PP
.Vb 1
\& http://www.icdevgroup.org/
.Ve
Double check the following items:
.Ip "1." 4
Using \s-1UNIX\s0 sockets?
.RS 4
.Ip "\(bu" 8
Check that the vlink program is \s-1SUID\s0, or the appropriate changes
have been made in the SocketPerms directive. Unless the files are
world-writable, the vlink program and the Interchange server must run
as the same user \s-1ID\s0! If running \s-1CGI-WRAP\s0 or \s-1SUEXEC\s0, the vlink
program must not be \s-1SUID\s0.
.Ip "\(bu" 8
If having trouble with the vlink program (named construct in the
demo configuration), try re-running makecat and using \s-1INET\s0 mode
instead. (Or copy the tlink \s-1INET\s0 mode link program over vlink).
This should work unchanged for many systems.
.Ip "\(bu" 8
If using an \s-1ISP\s0 or have a non-standard network configuration, some
changes to interchange.cfg are necessary. For tlink to work, the
proper host \fIname\fR\|(s) must be configured into the TcpHost directive in
interchange.cfg. The program selects port 7786 by default (the \s-1ASCII\s0
codes for \*(L"M\*(R" and \*(L"V\*(R", for MiniVend). If another port is used, it must
be set to the same number in both the tlink program (by running
compile_link) and the interchange.cfg file. The tlink program
does not need to be \s-1SUID\s0.
.RE
.RS 4
.RE
.Ip "2." 4
Proper file permissions?
.RS 4
.Ip "\(bu" 8
The Interchange server should not run as the user nobody! The
program files can be owned by anyone, but any databases, \s-1ASCII\s0
database source files, error logs, and the directory that holds them
must be writable by the proper user \s-1ID\s0, that is the one that is
executing the Interchange program.
.Ip "\(bu" 8
The best way to operate in multi-user, multiple catalog setups is to
create a special interch user, then put that user in the group that
contains each catalog user. If a group is defined for each individual
user, this provides the best security. All associated files can be in
660 or 770 mode. There should be no problems with permissions and no
problems with security.
.RE
.RS 4
.RE
.Ip "3." 4
Is the vlink program being executed on a machine that has the
socket file etc/socket on a directly attached disk?
.RS 4
.Ip "\(bu" 8
UNIX-domain sockets will not work on NFS-mounted file systems! This
means that the Interchange server and the \s-1CGI\s0 program vlink must be
executing on the same machine.
.Ip "\(bu" 8
The tlink program does not have this problem, but it must have the
proper host \fIname\fR\|(s) and \s-1TCP\s0 ports set in the TcpHost and TcpMap
directives in interchange.cfg. Also, be careful of security if
sensitive information, like customer credit card numbers, is being
placed on a network wire.
.RE
.RS 4
.RE
.SH "Usertracking"
.IX Header "Usertracking"
Several actions from the user are recorded by Interchange's
usertracking facility. The usertracking data is logged at two
locations, depending on your setup.
.PP
The first location is the one specified by the \fITrackFile\fR
configuration directive, e.g. logs/usertrack in the foundation
demo.
.PP
The second location are the \s-1HTTP\s0 headers. You can configure Apache to
write this header into the access logs.
.PP
.Vb 3
\& LogFormat "%h %l %u %t \e"%r\e" %>s %b \e"%{Referer}i\e" \e"%{User-Agent}i\e" \e
\& %T %v \e"%{X-Track}o\e"" track
\&CustomLog /var/log/apache/access.log track
.Ve
.Vb 1
\& ________________________________________
.Ve
Copyright 2002\-2004 Interchange Development Group. Copyright 2001\-2002
Red Hat, Inc. Freely redistributable under terms of the \s-1GNU\s0 General
Public License. line:
.PP
Catalog-Building Tutorial
.SH "Purpose"
.IX Header "Purpose"
The purpose of this document is to guide you through constructing a
simple Interchange catalog from scratch. The demo catalog that ships
with Interchange is quite complex since it highlights some of the many
capabilities that Interchange offers. As a template for your own
catalog, the demo can be an intimidating place to start if your
purpose is to learn.
.PP
The simple catalog you create using this tutorial should give you a
feel for the basic Interchange system. It should also be considered a
stepping stone to a more complete and functional e-commerce system
built with Interchange. The tutorial relies as much as possible on
default settings to accentuate how Interchange works. It will use as
few of Interchange's capabilities as possible, while still building a
usable store. The resulting site will be simple but usable. The value
of this tutorial is in the instruction that occurs along the way.
.PP
It is recommended that you create the files used in this tutorial
yourself. You will learn more by creating the directory structure and
using your favorite text editor to create files in the proper places
on your own system as they are discussed.
.SH "Before you begin"
.IX Header "Before you begin"
This section explains the initial set up tasks that must be completed
before you can begin building your simple e-commerce site.
.Sh "Install Interchange and the demo catalog"
.IX Subsection "Install Interchange and the demo catalog"
The easiest way to get Interchange and the demo set up is through an
\&\fI\s-1RPM\s0 install\fR on the Red Hat Linux or Linux Mandrake operating
systems. You can also get Interchange by unpacking an Interchange
tarball or checking out a copy of the \s-1CVS\s0 repository and doing a
\&\fImanual installation\fR. These installations can be done either as a
regular user or as root, installing for a special Interchange user.
.PP
You must also know what type of installation you ran so you know where
to place the various files created. Before proceeding, verify that
Interchange is properly installed. Also, keep in mind which type of
installation you did:
.Ip "\(bu" 4
\&\s-1RPM\s0 (\s-1RPM\s0 Package Manager) install
.Ip "\(bu" 4
Manual install as root
.Ip "\(bu" 4
Manual install as regular user
.PP
\&\fBNote: \fRAfter installation, \fImakecat\fR should be run to build your
catalog. For information on installing Interchange and building your
catalog using \fImakecat\fR, see the \fIInterchange Getting Started
Guide\fR. Do not to continue with this tutorial without a working demo
catalog.
.PP
Installing the demo catalog set up the Interchange global
configuration file \fIinterchange.cfg\fR, which resides in the
Interchange software directory. Also, it compiled the link program for
your specific server and placed the executable program in your cgi-bin
directory. This is necessary for your catalog to run properly.
.Sh "The Interchange operating system user"
.IX Subsection "The Interchange operating system user"
If Interchange was installed as a regular user, that will be the user
Interchange runs as. If Interchange was installed as root or from an
\&\s-1RPM\s0, you need to know the name of the separate Interchange user. The
Interchange daemon will not run as root, and should not run as the web
server user (usually 'apache', 'www', 'httpd', or 'nobody'). If
Interchange was installed from the \s-1RPM\s0, or with the default source
installation settings, the username is interch. If you selected a
different user name, you will need to know what it is.
.Sh "Important directories"
.IX Subsection "Important directories"
In order to complete this tutorial you will need to know the location
of each of the following directories and have write permissions on
them:
.Ip "\(bu" 4
Interchange software directory
.RS 4
.Ip "\(bu" 8
\&\fB\s-1RPM\s0 install:\fR /usr/lib/interchange
.Ip "\(bu" 8
\&\fBManual install as root:\fR /usr/local/interchange
.Ip "\(bu" 8
\&\fBManual install as regular user:\fR /home/username/interchange
.RE
.RS 4
.RE
.Ip "\(bu" 4
Catalogs directory
.RS 4
.Ip "\(bu" 8
\&\fB\s-1RPM\s0 install:\fR /var/lib/interchange
.Ip "\(bu" 8
\&\fBManual install as root:\fR /usr/local/interchange/catalogs
.Ip "\(bu" 8
\&\fBManual install as regular user:\fR /home/username/catalogs
.RE
.RS 4
.RE
.Ip "\(bu" 4
cgi-bin directory
.RS 4
.Ip "\(bu" 8
\&\fB\s-1RPM\s0 install or source install as root:\fR /var/www/cgi-bin
.Ip "\(bu" 8
\&\fBManual install as root (locally installed web server):\fR
/usr/local/htdocs, /opt/www, ...
.Ip "\(bu" 8
\&\fBManual install as regular user:\fR /home/username/public_html (with
\&.cgi extension)
.RE
.RS 4
.RE
.PP
\&\fBNote: \fRThe installation of Interchange is very flexible and the file
locations on your system may vary, depending on how your system was
set up. It is recommended that you not proceed until you are sure you
have this information and the necessary permissions to write to these
directories.
.Sh "Your catalog \s-1URL\s0"
.IX Subsection "Your catalog URL"
Finally, you need to know the \s-1URL\s0 to access your store from a web
browser. Again, this can vary depending on how your web server has
been set up. But, assuming a common setup of the Apache web server,
your \s-1URL\s0 should be one of the following:
.Ip "\(bu" 4
\&\fBRoot or \s-1RPM\s0 install:\fR http://localhost/cgi-bin/tutorial/pagename
.Ip "\(bu" 4
\&\fBManual install as user:\fR
http://localhost/~username/tutorial.cgi/pagename
.PP
If you aren't running your web browser on the server where Interchange
is running, you need to substitute your server's host name (for
example: machine.domain.com for localhost) where mentioned.
.PP
\&\fBNote: \fRIt is recommended that you use the real machine name instead
of localhost. The standard for cookies specifies that they can only be
set when a domain name has at least two dots in it. If you use
localhost, you will lose session information if you leave catalog,
since the session \s-1ID\s0 is passed only as part of the \s-1URL\s0.
.Sh "Starting or restarting Interchange"
.IX Subsection "Starting or restarting Interchange"
When you make changes to the configuration files you need to restart
the Interchange server. How this is done depends on how you installed
Interchange:
.Ip "\(bu" 4
\&\fB\s-1RPM\s0 install as root:\fR /usr/sbin/interchange \-r
.Ip "\(bu" 4
\&\fBManual install as Interchange user:\fR
/usr/local/interchange/bin/interchange \-r
.Ip "\(bu" 4
\&\fBManual install as root:\fR su interch \-c
\&'/usr/local/interchange/bin/interchange \-r'
.Ip "\(bu" 4
\&\fBManual install as regular user:\fR ~/interchange/bin/interchange \-r
.PP
Find the right command for your system and remember it, since you will
need to restart Interchange a few times during the tutorial.
.Sh "Tutorial assumptions"
.IX Subsection "Tutorial assumptions"
Because it is impossible to cover all scenarios, this tutorial assumes
that you installed Interchange on Red Hat Linux from the \s-1RPM\s0 packages.
This creates the following settings:
.Ip "\(bu" 4
\&\fBInterchange software directory:\fR /usr/lib/interchange
.Ip "\(bu" 4
\&\fBCatalogs directory:\fR /var/lib/interchange
.Ip "\(bu" 4
\&\fBcgi-bin directory:\fR /var/www/cgi-bin
.Ip "\(bu" 4
\&\fBInterchange user:\fR interch
.Ip "\(bu" 4
\&\fBDemo catalog name:\fR foundation
.Ip "\(bu" 4
\&\fBDemo catalog \s-1URL\s0 base:\fR http://localhost/cgi-bin/foundation
.Ip "\(bu" 4
\&\fBTutorial catalog name:\fR tutorial
.Ip "\(bu" 4
\&\fBTutorial catalog \s-1URL\s0 base:\fR http://localhost/cgi-bin/tutorial
.Ip "\(bu" 4
\&\fBTutorial catalog directory:\fR /var/lib/interchange/tutorial
.PP
If you did not install with these settings, substitute the correct
values for your system when these settings are mentioned in the
tutorial.
.SH "Building Your Catalog"
.IX Header "Building Your Catalog"
This section describes the pages and directories that need to be
established to create a properly functioning catalog.
.Sh "Create the link program"
.IX Subsection "Create the link program"
You need to make a copy of the demo link program in your cgi-bin
directory and name it \fItutorial\fR.
.PP
The demo link program has the same name as your demo catalog, usually
foundation. The link program links the Interchange daemon with your
web server. Make sure that it has the same owner and file permissions
as the one you copied from. The set-UID bit is especially (unless you
installed as a regular user). Normally you will need to be root to
have write permissions in the cgi-bin directory.
.PP
Type this command as root while in your cgi-bin directory:
.PP
.Vb 1
\& cp -p foundation tutorial
.Ve
If everything is working correctly, typing ls \-l should describe
your files roughly like this:
.PP
.Vb 2
\& -rwsr-xr-x 1 interch interch 7708 Dec 16 22:47 foundation
\& -rwsr-xr-x 1 interch interch 7708 Dec 16 22:47 tutorial
.Ve
.Sh "Create the tutorial catalog directory"
.IX Subsection "Create the tutorial catalog directory"
As root, create a subdirectory named \fItutorial\fR under your catalogs
directory (probably \fI/var/lib/interchange/\fR). This is where all of
the catalog-specific files will go. It needs to be readable, writable,
and executable by the Interchange user. This will be referred to as
your catalog directory. Type the following while in the catalogs
directory to create the tutorial subdirectory:
.PP
.Vb 3
\& mkdir tutorial
\& chown interch.interch tutorial
\& chmod 770 tutorial
.Ve
.Sh "Become the Interchange user"
.IX Subsection "Become the Interchange user"
You should be able to do everything you need to do as the 'interch'
user for the rest of this tutorial. So you can switch to that user now
(su \- interch). If you installed Interchange from the \s-1RPM\s0, the user
\&\fBinterch\fR probably doesn't have a password. You'll have to set it
with a command such as passwd interch while root.
.Sh "Go to the tutorial catalog directory"
.IX Subsection "Go to the tutorial catalog directory"
Change to the catalog directory with the 'cd' command. For the rest of
this tutorial, all file locations will be given relative to the
tutorial catalog directory. For example, \fIpages/ord/basket.html\fR
would actually be
\&\fI/var/lib/interchange/tutorial/pages/ord/basket.html\fR or the
equivalent on your system. The only exception is \fIinterchange.cfg\fR,
which is in the Interchange software directory.
.PP
\&\fBNote: \fRTo improve clarity, we will append a trailing slash to
directory names to clearly distinguish them from file names. (Similar
to the output of the \fIls\fR command with the \-F option.)
.Sh "Create the session directory"
.IX Subsection "Create the session directory"
You need to create the session directory where Interchange saves
information on each visitor's browsing session. If you do not have
this directory, your catalog will not work. This directory is called
\&\fIsession/\fR and goes under your catalog directory. Type mkdir
session to create this directory.
.SH "Configuration files"
.IX Header "Configuration files"
Interchange configuration is controlled by a number of directives,
which are specified in two files. Global configuration directives go
in \fIinterchange.cfg\fR in the Interchange software directory.
Catalog-specific configuration directives go in \fIcatalog.cfg\fR in the
catalog directory.
.PP
A complete directive consists of the directive name followed by
whitespace-separated parameters. Any number of spaces or tabs can be
between the directive and its options, but the directive and its
options must be on the same line. The directive is case-insensitive,
but it is recommended that you use it consistently for readability.
.PP
You can insert blank lines or comment lines (lines where the first
non-blank character is '#') throughout the configuration files to
improve readability. The order the lines appear in is significant, but
unimportant for the simple catalog you are creating.
.PP
For the next part, access your text editor (for example, vi, emacs,
pico, joe, gedit, or nedit) to start editing some files.
.Sh "interchange.cfg"
.IX Subsection "interchange.cfg"
The first directive we need to use is a global directive that tells
Interchange where the new catalog is, called \fICatalog\fR. The
\&\fBCatalog\fR directive has the following format:
.PP
.Vb 1
\& Catalog name catalog_base_directory link_url_path
.Ve
Open \fIinterchange.cfg\fR in the Interchange software directory. Go near
the top of the file, right below the other Catalog directives, and add
this line:
.PP
.Vb 1
\& Catalog tutorial /var/lib/interchange/tutorial /cgi-bin/tutorial
.Ve
Save the file.
.Sh "catalog.cfg"
.IX Subsection "catalog.cfg"
For the rest of the tutorial, most of the files mentioned do not exist
yet. You will create them yourself with initial text we give.
.PP
You need to create a \fIcatalog.cfg\fR file for your tutorial store (in
the tutorial catalog directory). We'll start with a very simple
products database table with a few fields and a few products.
.PP
The \fBDatabase\fR directive describes a database table to the
Interchange system in this format:
.PP
.Vb 1
\& Database name filename format
.Ve
Interchange has several database options available. We will use the
simplest, which is the built-in default (specifically, some variant of
\&\s-1DBM\s0). The default location for \fIfilename\fR is in a subdirectory called
\&\fIproducts\fR under the catalog directory. Interchange recognizes a
number of file formats. We will use a tab-delimited text file. Enter
the following into \fIcatalog.cfg\fR:
.PP
.Vb 1
\& Database products products.txt TAB
.Ve
This tells Interchange that you have a database table named 'products'
that is described in a tab-delimited file named \fIproducts.txt\fR. You
can describe an unlimited number of arbitrary database tables for the
system to use this way. Interchange keeps a list of default tables
called \*(L"Product Files,\*(R" reflecting its e-commerce roots. You can
specify all of the database tables that contain products by using the
\&\fBProductFiles\fR directive. There is no default for this, so you will
have to specify your products table's name by adding the following
line to \fIcatalog.cfg\fR:
.PP
.Vb 1
\& ProductFiles products
.Ve
There are a few other directives that Interchange expects to see in
order to complete the minimum configuration. They are \fBVendURL\fR,
\&\fBSecureURL\fR, and \fBMailOrderTo\fR. They are, respectively, your
catalog's base \s-1URL\s0, its secure \s-1URL\s0, and the e-mail address to mail
order notices to. Add the following lines to \fIcatalog.cfg\fR to
establish these directives:
.PP
.Vb 3
\& VendURL http://localhost/cgi-bin/tutorial
\& SecureURL http://localhost/cgi-bin/tutorial
\& MailOrderTo your@email.address
.Ve
The \fIcatalog.cfg\fR file should look like this when you save it:
.PP
.Vb 5
\& Database products products.txt TAB
\& ProductFiles products
\& VendURL http://localhost/cgi-bin/tutorial
\& SecureURL http://localhost/cgi-bin/tutorial
\& MailOrderTo your@email.address
.Ve
.SH "The products database table"
.IX Header "The products database table"
.Sh "products/products.txt"
.IX Subsection "products/products.txt"
Create the \fIproducts/\fR directory in your tutorial catalog directory.
.PP
The \fIproducts/products.txt\fR file will serve two purposes. It will
provide Interchange with the layout of the products database table and
it will also provide the data. When Interchange parses the
products.txt file, it will expect the first line to contain the names
of the fields for the database table (for example, sku, description,
price). The first field in the list is expected to be a primary key
(unique identifier) for that row. In most cases you are going to use
the \s-1SKU\s0 (stock keeping unit) as the unique identifier for each
product.
.PP
The product database is handled as a special case since Interchange
expects at least the description, price, and product \s-1ID\s0 (sku) fields.
In other words, the \fIproducts.txt\fR file must at least contain fields
named sku, price, and description. You can have other fields too, if
you wish.
.PP
The simple store that we are going to build will sell tests. You can
choose another sample product line, but it is recommended that you
keep it simple. Create the file \fIproducts/products.txt\fR to look like
this, with a single tab separating each field:
.PP
.Vb 5
\& sku description price
\& 4595 Nice Bio Test 275.45
\& 2623 Stack of Econ Quizzes 1.24
\& 0198 Really Hard Physics Test 1589.34
\& 1299 Ubiquitous diff eq final 37.00
.Ve
\&\fBNote: \fRWhen using tab-delimited files as we are, make sure you have
exactly one tab between each field. Some text editors will use spaces
to simulate tabs. Interchange expects actual \s-1ASCII\s0 tab characters;
extra spaces or other characters will corrupt your data.
.PP
You may notice that the columns don't line up in your text editor.
This is the nature of tab-delimited files. Do not try to fix these.
.SH "Page templates"
.IX Header "Page templates"
Since most sites have certain aspects of the site that remain the same
as the content of the pages changes, we are going to create a template
that we can use for all pages. We'll divide the page into four
sections:
.PP
.Vb 14
\& _____________________
\& | |
\& | top |
\& | |
\& |---------------------|
\& | | |
\& | | |
\& | left | main |
\& | | |
\& | | |
\& |---------------------|
\& | |
\& | bottom |
\& |_____________________|
.Ve
The \*(L"main\*(R" section holds the content that is different for each page.
The \*(L"top\*(R" section is for headers, banners, menus, and so on. The
\&\*(L"left\*(R" section can be used as a sidebar or navigation bar, and the
\&\*(L"bottom\*(R" section can contain the copyright and contact info. The top,
left, and bottom sections will remain constant throughout the site.
Making a change to information in one of these sections will make that
change to all pages in your site.
.PP
Now type the \s-1HTML\s0 for each template section in an individual plain
text file in the catalog directory, named 'top', 'left', and 'bottom',
respectively using the code displayed below. No '.html' suffixes are
used on these because they are not meant to be parsed directly by
Interchange as full pages.
.Sh "top"
.IX Subsection "top"
.Vb 8
\&
\&
\& The Interchange Test Catalog
\&
\&
\&
\&
\& The Interchange Test Catalog
.Ve
.Sh "left"
.IX Subsection "left"
.Vb 3
\&
\& (left)
\&
.Ve
.Sh "bottom"
.IX Subsection "bottom"
.Vb 7
\&
\&
\& (bottom)
\&
\&
\&
\&
.Ve
.Sh "The Interchange Tag Language"
.IX Subsection "The Interchange Tag Language"
Now we need a way to pull the template pieces we just created into the
proper places to make a complete page. This is done using \s-1ITL\s0, the
Interchange Tag Language.
.PP
\&\s-1ITL\s0 is at the heart of almost all Interchange catalog pages. It's how
you use Interchange's functionality. The \s-1ITL\s0 tags appear between
square brackets like [this]. Options appear after the tag, separated
by whitespace, like this: [tag option1 option2] and this: [tag
option1=value1 option2=value2]. They can span multiple lines. (That
can help readability when the tag has many options.) There are many
\&\s-1ITL\s0 tags, and for this tutorial very few will be addressed. For a
complete listing of the \s-1ITL\s0 tags, see the \fIInterchange Tag Reference
Guide\fR.
.PP
Your first tag will be [include], which reads the file mentioned
(relative to the catalog directory), parses any Interchange tags, and
puts the result in place of the tag. This is demonstrated on the next
page you need to create.
.SH "Creating a welcome page"
.IX Header "Creating a welcome page"
.Sh "pages/index.html"
.IX Subsection "pages/index.html"
Create a directory called \fIpages/\fR in your tutorial catalog
directory.
.PP
Type the following text and save it as \fIpages/index.html\fR. This will
create a page to test that everything works so far.
.PP
.Vb 4
\& [include top]
\& [include left]
\& This is where your content goes.
\& [include bottom]
.Ve
Restart Interchange so your changes take effect. Go to your web
browser and load the page. The \s-1URL\s0 should be similar to the following:
http://localhost/cgi-bin/tutorial/index.html.
.PP
\&\fBNote: \fRInterchange pages in the \fIpages/\fR or other directories
\&\fBmust\fR have the .html suffix on them. You can drop the suffix in your
\&\s-1URL\s0 and in other places, such as the [page] tag you'll learn about
later, but the file name on disk must have the suffix.
.SH "Troubleshooting"
.IX Header "Troubleshooting"
Your first Interchange page should have displayed as described in your
browser. If it didn't, you need to figure out what went wrong. Most of
the time, overlooked details are the problem. Double-checking your
typing is a good habit to get into.
.PP
The following is a troubleshooting checklist to use when you run into
problems:
.Ip "1." 4
Have you created directories with the proper names in the proper
locations? (See Appendix A for a full directory and file structure of
the tutorial catalog.)
.Ip "2." 4
Have you misspelled any file names or put them in the wrong
directories? Are the files and parent directories readable by the
interch user? Double-check with the \fIls\fR command.
.Ip "3." 4
Did you type letters in the proper case? Remember that both Unix and
Interchange are case-sensitive, and for the most part you may not
switch upper- and lower-case letters.
.Ip "4." 4
Did you type all punctuation, \s-1ITL\s0 tags, and \s-1HTML\s0 tags correctly?
.Ip "5." 4
Did you use whitespace correctly in the cases where it mattered?
Remember to use tabs when tabs are called for (in lists and database
text files).
.Ip "6." 4
Did you restart Interchange if you changed anything in
\&\fIinterchange.cfg\fR or \fIcatalog.cfg\fR, or if you're in a high-traffic
mode?
.Ip "7." 4
Check your catalog error log, \fIerror.log\fR in your tutorial catalog
directory, to see if Interchange reported any errors.
.Ip "8." 4
Check the Interchange server error log, \fIerror.log\fR in the
Interchange software directory, to see if it had problems loading the
catalog at all.
.Ip "9." 4
View the \s-1HTML\s0 source of any catalog pages that are loading incorrectly
to check for a coding error. The problem may reveal itself when you
see what \s-1HTML\s0 the browser is getting.
.SH "Displaying products"
.IX Header "Displaying products"
.Sh "Listing all products"
.IX Subsection "Listing all products"
Now that your store is running, you need to display your products on
the welcome page. We will loop over all of the products in our
database and produce an entry for each one in a table. Replace the
line \*(L"This is where your content goes\*(R" in \fIpages/index.html\fR with the
following:
.PP
.Vb 6
\&
\&
\& Test #
\& Description
\& Price
\&
.Ve
.Vb 1
\& . . .
.Ve
.Vb 1
\&
.Ve
Now we will use Interchange tags to fill in the rest of the table from
the products database you created. The [loop] [/loop] \s-1ITL\s0 tag pair
tells Interchange to iterate over each item in the parameter list. In
this case, the loop is over the result of an Interchange search. The
search parameter does a database search on the provided parameters. In
this case, we're doing a very simple search that returns all of the
fields for all of the entries in the products database. The parameters
passed to the search tell Interchange to \fIreturn all\fR ('ra') on the
file ('fi') \fIproducts\fR respectively. The following should take the
place of the ellipsis in the code you placed in \fIindex.html\fR:
.PP
.Vb 1
\& [loop search="ra=yes/fi=products"]
.Ve
.Vb 1
\& . . .
.Ve
.Vb 1
\& [/loop]
.Ve
In the loop we just established, the individual elements of the entry
using the [loop-field] tag. The following code should replace the
above ellipsis in the code we placed in \fIpages/index.html\fR:
.PP
.Vb 5
\&
\& [loop-code]
\& [loop-field description]
\& [loop-field price]
\&
.Ve
The [loop-code] tag refers to the primary key (unique identifier) for
the current row of the database table in question. In this case, it
will produce the same output as the [loop-field sku] tag, because the
\&'sku' field is the primary key for products table. In each case the
tag is replaced by the appropriate element. When put together,
Interchange generates a page with your products table on it.
.PP
Your finished page should look like this:
.PP
.Vb 17
\& [include top]
\& [include left]
\&
\&
\& Test #
\& Description
\& Price
\&
\& [loop search="ra=yes/fi=products"]
\&
\& [loop-code]
\& [loop-field description]
\& [loop-field price]
\&
\& [/loop]
\&
\& [include bottom]
.Ve
Test this page by refreshing the index.html page in your browser.
.Sh "pages/flypage.html"
.IX Subsection "pages/flypage.html"
The next step is to create an individual page for each item. To do
this, you need to create a special generic page called
\&\fIpages/flypage.html\fR. When a page is requested that does not exist in
the \fIpages/\fR directory, Interchange will check and see if the
requested page has the same name as a product \s-1ID\s0 from the product
database table (in this case a \s-1SKU\s0). If it does, it will show the
flypage for that product. If there's no product with that \s-1ID\s0, the
special error page \fIspecial_pages/missing.html\fR (described in the
next section) will be displayed.
.PP
For example, if the page \fI0198.html\fR was requested, Interchange first
checks for a page with that name. If one is not found, it searches the
products database table for a product with that \s-1ID\s0. Interchange then
creates a product page \*(L"on the fly\*(R" using \fIpages/flypage.html\fR. When
constructing the flypage, the entire product record for the requested
product is available through the [item-field] tag (similar to the
[loop-field] tag). To create a fly page, type the following code and
save it as \fIpages/flypage.html\fR.
.PP
.Vb 2
\& [include top]
\& [include left]
.Ve
.Vb 2
\& Test #[item-code]
\& [item-field description] . . . [item-field price]
.Ve
.Vb 1
\& [include bottom]
.Ve
Then, to provide links to the product flypages from your home page,
modify \fIpages/index.html\fR slightly, so that:
.PP
.Vb 1
\& [loop-field description]
.Ve
becomes:
.PP
.Vb 1
\& [loop-field description]
.Ve
.Sh "special_pages/missing.html"
.IX Subsection "special_pages/missing.html"
Create the \fIspecial_pages/\fR directory in your tutorial catalog
directory (not in the \fIpages/\fR directory).
.PP
As mentioned, it is a good idea to display an error page when
Interchange is asked for an unknown page. To create a missing page for
display, type the following and save it as
\&\fIspecial_pages/missing.html\fR.
.PP
.Vb 3
\& [include top]
\& [include left]
\& We're sorry, the page you requested has not been found.
.Ve
.Vb 2
\& Try finding what you need on the [page index]welcome page.
\& [include bottom]
.Ve
The addition of this page ensures that users see your error message
instead of a mysterious server error if they mistype a \s-1URL\s0.
.SH "The shopping basket"
.IX Header "The shopping basket"
.Sh "A link for ordering"
.IX Subsection "A link for ordering"
Now that you have your products available, let's add a shopping cart
so customers can purchase them. This is created using the [order] tag.
These tags create an \s-1HTML\s0 link that causes the specified item to be
ordered and transfers the shopper to the basket page. This is a
built-in shortcut to the complete order process which uses an \s-1HTML\s0
form submission process. The parameter for the [order] tag is the
product \s-1ID\s0. To add these tags to the catalog, make the following
change to \fIpages/index.html\fR:
.PP
.Vb 7
\&
\& [loop-code]
\& [loop-field description]
\& [loop-field price]
\&+ [order [loop-code]]Order Now
\&
\& [/loop]
.Ve
\&\fBNote: \fRThe line you need to add is marked by a '+'. However, do not
include the '+' when adding this line. The surrounding lines are shown
to give you context. This style is called a \*(L"context diff\*(R" and is used
often in this tutorial.
.Sh "pages/ord/basket.html"
.IX Subsection "pages/ord/basket.html"
Create the directory \fIpages/ord/\fR in the tutorial catalog directory.
In other words, \fIord/\fR should be inside the \fIpages/\fR directory.
.PP
For the [order] tag, Interchange expects a default page called
\&\fIpages/ord/basket.html\fR. This page displays the contents of the
shopping basket and contains other shopping basket functionality.
.PP
The Foundation store has a full-featured shopping basket available for
use, but this tutorial teaches you to build your own simple one. The
shopping basket items can be accessed using a set of tags that have an
[item] prefix. Put the following code in the new file
\&\fIpages/ord/basket.html\fR. The section that follows explains the tags
used.
.PP
.Vb 2
\& [include top]
\& [include left]
.Ve
.Vb 1
\& This is your shopping cart!
.Ve
.Vb 1
\&
.Ve
.Vb 6
\&
\& Qty.
\& Description
\& Cost
\& Subtotal
\&
.Ve
.Vb 8
\& [item-list]
\&
\& [item-quantity]
\& [item-field description]
\& [item-price]
\& [item-subtotal]
\&
\& [/item-list]
.Ve
.Vb 1
\&
.Ve
.Vb 4
\&
\& Total:
\& [subtotal]
\&
.Ve
.Vb 1
\&
.Ve
.Vb 1
\&
.Ve
.Vb 4
\&
\& [page checkout]Purchase now
\& [page index]Return to shopping
\&
.Ve
.Vb 1
\& [include bottom]
.Ve
The basket items can be accessed one at a time by using the
[item-list] tag. So we will create a table by iterating through the
basket items. The text within the [item-list] [/item-list] tags is
created for each item in the list.
.Ip "\(bu" 4
[item-quantity] shows the quantity of the item ordered. If the same
item is ordered multiple times, the quantity increases.
.Ip "\(bu" 4
[item-field description] shows the description from the product
database table. Any field that is not special to Interchange can be
accessed from the shopping cart this way.
.Ip "\(bu" 4
[item-price] shows the per-item price that is defined in the product
database table.
.Ip "\(bu" 4
[item-subtotal] shows the total cost of this order line. This is
normally the price multiplied by the quantity, but it can also take
into account other considerations, such as various kinds of price
discounts.
.Ip "\(bu" 4
[subtotal] shows the calculated shopping basket subtotal.
.Ip "\(bu" 4
[page index] creates the starting \s-1HTML\s0 for a link to
the catalog welcome page.
.PP
You also need to put a link in the index page so that shoppers can go
to their shopping cart without ordering something. Modify the end of
\&\fIpages/index.html\fR by adding the following lines.
.PP
.Vb 4
\&
\&+
\&+ [page order]View shopping cart
\& [include bottom]
.Ve
Refresh the page and test the shopping basket in your browser.
.SH "Order checkout"
.IX Header "Order checkout"
.Sh "pages/checkout.html"
.IX Subsection "pages/checkout.html"
The site can now be completed by adding the ability to check out with
the shopping cart and finalize the order. To do this the customer
needs to provide a shipping address (which, for the sake of this
tutorial, we will assume is the same as the billing address), and
payment information. We will process the order by verifying the
customer's payment information and sending an email to the merchant
(ourselves) detailing the order.
.PP
First you need to create a checkout page. The checkout page consists
of a form that receives order information from the customer and
performs a simple credit card number check. In this tutorial we will
use a built-in test that only checks to see if a given credit card
number could be valid. If the information is acceptable the customer
will move to the next phase of the order process. If it is not, an
error page will be displayed.
.PP
To create a checkout page, type the following code and save it as
\&\fIpages/checkout.html\fR. The section that follows explains the code.
.PP
.Vb 3
\& [include top]
\& [include left]
\& Checkout Page
.Ve
.Vb 4
\&
.Ve
.Vb 2
\& [page index]Return to shopping instead
\& [include bottom]
.Ve
The \s-1HTML\s0 form begins with a method of 'post' (which sends the form
data as its own stream, as opposed to the 'get' method which encodes
the data as part of the \s-1URL\s0). The [process] tag creates a special \s-1URL\s0
for form processing. Interchange has a built-in form processor that is
configured by submitting certain fields in the form. The Finalize
button will invoke this form processor and link the user to the
\&\fIspecial_pages/receipt.html\fR page, which is described later.
.PP
You are submitting some hidden form values that will tell Interchange
how to process this form. The first value, \fBmv_todo\fR was set as
\&\fIsubmit\fR. This causes the form to be submitted for validation. The
second value, \fBmv_order_profile\fR was set as \fIorder_profile\fR. This
determines the validation process for the form. It is explained
further in the next section.
.PP
The last value, \fBmv_cyber_mode\fR, was set to be \fIminivend_test\fR. The
\&\fBmv_cyber_mode\fR value determines what method will be used to charge a
credit card. The value of \fIminivend_test\fR uses the internal test
method, which calculates a simple checksum against the card to
determine if it is a valid number.
.PP
When preparing an order for processing, Interchange looks for certain
named fields in the form values for name, address, and credit card
information. We are using all expected field names in this form so
that no translation needs to take place.
.PP
View the checkout page in your browser. The \*(L"Finalize!\*(R" link has not
been enabled, but the page should display properly.
.Sh "etc/profiles.order"
.IX Subsection "etc/profiles.order"
Create the \fIetc/\fR directory in the tutorial catalog directory now.
.PP
You need to set up verification for the order form by defining an
order profile for the form. An order profile determines what fields
are necessary for the form to be accepted. Create an order profile
verification page by typing the following and saving it as
\&\fIetc/profiles.order\fR. The section that follows explains the code
used.
.PP
.Vb 1
\& __NAME__ order_profile
.Ve
.Vb 6
\& fname=required
\& lname=required
\& address1=required
\& city=required
\& state=required
\& zip=required
.Ve
.Vb 2
\& &fatal=yes
\& &final=yes
.Ve
.Vb 1
\& __END__
.Ve
A single file can contain multiple profile definitions. First the
profile is named using the _\|_NAME_\|_ pragma. (This is unrelated to the
_\|_VARIABLE_\|_ syntax seen elsewhere in Interchange.) Then in the
profile there is a list of the form fields that are required. The
\&\fB&fatal\fR setting indicates that validation will fail if any of the
requirements are not met. \fB&final\fR indicates that this form will
complete the ordering process. This setting is helpful if you have a
multi-page ordering process and you want to validate each page
individually. The _\|_END_\|_ pragma signals the end of this profile,
after which you can begin another one.
.PP
In order to activate your order profile, add the following
\&\fBOrderProfile\fR directive to the end of \fIcatalog.cfg\fR:
.PP
.Vb 1
\& OrderProfile etc/profiles.order
.Ve
Watch for white space in front of the _\|_NAME_\|_ pragma, it can cause
your profile to be ignored. Rember to restart Interchange for any
changes to take effect.
.Sh "special_pages/needfield.html"
.IX Subsection "special_pages/needfield.html"
If the submitted form lacks a required field, Interchange will display
an error page. The default location is
\&\fIspecial_pages/needfield.html\fR. To create this page, type the
following text and save it as \fIspecial_pages/needfield.html\fR.
.PP
.Vb 3
\& [include top]
\& [include left]
\& The following information was not given:
.Ve
.Vb 1
\& [error all=1 show_var=1 show_error=1 joiner=' ']
.Ve
.Vb 2
\& Please go back to the [page checkout]checkout page
\& and fill out the form properly.
.Ve
.Vb 1
\& [include bottom]
.Ve
The [error] tag is the most important tag on this page. The \fBall\fR
parameter tells the tag to iterate through all of the errors reported
from the failed verification, and the \fBshow_var\fR parameter indicates
that the failed variable name should be displayed. For example, if the
first name was left empty, \fIfname\fR would be shown. The \fBshow_error\fR
parameter displays the actual error for the variable. The \fBjoiner\fR
parameter inserts an \s-1HTML\s0 \fI \fR tag between each error message,
so each error is displayed on its own line. In more complex
configurations, the [error] tag can be even more expressive.
.Sh "Credit card processing"
.IX Subsection "Credit card processing"
This tutorial uses a very simple order process. To accomplish this,
one more directive needs to be added to the file
\&\fIetc/profiles.order\fR:
.PP
.Vb 3
\& &fatal=yes
\& &final=yes
\&+ &credit_card=standard keep
.Ve
.Vb 1
\& __END__
.Ve
This issues two instructions to the credit card system.
.PP
The first option, \fBstandard\fR, uses the standard built-in encryption
algorithm to encrypt the credit card number and erases the unencrypted
copy from memory. We are using the standard option not to encrypt the
number but to run the checksum verification on the number to verify
that it is a potentially correct number. We will not be checking with
a real payment processor to see if it actually is a valid card number.
For testing purposes, you can use the card number 4111 1111 1111 1111,
which will pass the checksum test.
.PP
The second option, \fBkeep\fR, keeps the credit card number from getting
removed from memory. We want to keep the number in memory so that it
is available when it is mailed as part of the order.
.PP
If the credit card number passes and all of the required fields are
present, the customer will be sent to the final page. Interchange then
sends an e-mail to the store owner (you).
.Sh "etc/report"
.IX Subsection "etc/report"
When the customer's involvement in the order is complete, Interchange
composes an email and sends it to the recipient defined in the
MailOrderTo directive in \fIcatalog.cfg\fR. The default location for the
template for this email report is \fIetc/report\fR. Interchange tags can
be used to fill in the body of the message.
.PP
The report should include at least the customer's name, address, and
the items they ordered. The following is a simple report template;
save it as \fIetc/report\fR.
.PP
.Vb 4
\& Name: [value fname] [value lname]
\& Address: [value address1][if value address2]
\& [value address2][/if]
\& City, State, etc.: [value city], [value state] [value zip] [value country]
.Ve
.Vb 2
\& Credit Card #: [cgi mv_credit_card_number]
\& Expiration Date: [cgi mv_credit_card_exp_month]/[cgi mv_credit_card_exp_year]
.Ve
.Vb 6
\& ************ ORDER ************
\& [item-list]
\& [item-quantity] x [item-description] ([item-code]), [item-price] ea.
\& [/item-list]
\& Subtotal: [subtotal]
\& Total: [total-cost]
.Ve
This file is in plain text format where, unlike \s-1HTML\s0, white space is
relevant. It is fairly straightforward, except that the [if] tag was
added to only include the optional second address line if the customer
filled it in.
.PP
One of the special properties of the \fImv_credit_card_number\fR field is
that Interchange specifically precludes the credit card number from
being saved. This makes it unavailable to you in the [value] tag. The
\&\fB[cgi]\fR tag is used to circumvent this important security measure in
order to get the value submitted from the last form.
.PP
\&\fB\s-1WARNING\s0!\fR Obviously it is a bad idea to send a real credit card
number over an insecure channel like email. In a real configuration,
you would encrypt the number securely before emailing or storing it.
.Sh "special_pages/receipt.html"
.IX Subsection "special_pages/receipt.html"
Once the report has been run, Interchange will finish the order
process on the customer side by displaying a success screen containing
a receipt. The default location for this page is
\&\fIspecial_pages/receipt.html\fR. To create a receipt page, type the
following code and save it as \fIspecial_pages/receipt.html\fR.
.PP
.Vb 5
\& [include top]
\& [include left]
\& Thank you for ordering stuff from us. Have a nice day!
\& [page index]Return to our welcome page
\& [include bottom]
.Ve
Once the order is processed, the customer's shopping cart is emptied.
.PP
At this point you have a more-or-less functional store.
Congratulations.
.SH "Enhancing the catalog"
.IX Header "Enhancing the catalog"
Now that you have a working catalog, you can go back and add
improvements and test them incrementally. This section walks you
through several and then suggests more enhancements you can attempt on
your own.
.Sh "Price pictures"
.IX Subsection "Price pictures"
You may have noticed that the product prices aren't formatted as
prices usually are. The way to correct this is with an Interchange
feature called \fIprice pictures\fR.
.PP
There are several properties to price pictures: the currency symbol,
the thousands separator, the decimal point, the number of digits to
show behind the decimal, and so on. Most Unix systems have U.S.
currency and the English language as the default locale, which is
called en_US. The only thing you need to do on such a system is
specify the currency symbol, which, in this case, is the dollar sign.
To do this, add the following line to your \fIcatalog.cfg\fR file:
.PP
.Vb 1
\& Locale en_US currency_symbol $
.Ve
Restart Interchange and view your catalog. You will notice little has
changed on the welcome page or the flypages, but in the shopping cart
all your prices should be formatted as U.S. dollars (\*(L"1347.3\*(R" has
become \*(L"$1,347.30\*(R"). This is because Interchange automatically formats
shopping cart prices as currency. To turn off this feature, you would
have to change the [item-price] tag to [item-price noformat] in
\&\fIpages/ord/basket.html\fR.
.PP
But that's probably not what you want to do. You're probably more
interested in formatting your other prices as currency. To do that,
simply use the [currency] [/currency] tag pair for all price values.
Make the following change to \fIpages/index.html\fR:
.PP
.Vb 8
\& [loop search="ra=yes/fi=products"]
\&
\& [loop-code]
\& [loop-field description]
\&- [loop-field price]
\&+ [currency][loop-field price][/currency]
\&
\& [/loop]
.Ve
\&\fBNote: \fRThe line that begins with '\-' should be deleted. Do not type
the '\-'. The next line, that starts with '+', replaces it.
.PP
A similar change to the [item-field price] tag in the
\&\fIpages/flypage.html\fR page will fix that currency display. View the
page in your browser. All your prices should be formatted for U.S.
currency.
.PP
If your prices are not being formatted correctly, your default system
locale may be set up differently or your en_US locale settings may
be wrong. There are a few other \fIcatalog.cfg\fR directives you can use
to correct the situation:
.PP
.Vb 1
\& Locale en_US p_cs_precedes 1
.Ve
Makes the currency symbol precede the currency value. A '0' setting
makes the symbol come after the currency value.
.PP
.Vb 1
\& Locale en_US mon_thousands_sep ,
.Ve
Sets your thousands separator to a comma. It can be set to any value.
.PP
.Vb 1
\& Locale en_US mon_decimal_point .
.Ve
Sets your decimal separator to a comma. Many countries use a comma
instead of a period to separate the integer from the decimal part.
.PP
\&\fBNote: \fRConsult the Interchange documentation and your operating
system manual for more information on locale settings.
.Sh "Catalog variables"
.IX Subsection "Catalog variables"
Interchange provides a very useful feature that has not been discussed
yet called catalog variables. It provides a way for you to set a
variable to a certain value in the \fIcatalog.cfg\fR file and use it
anywhere in your catalog pages. The \fBVariable\fR directive allows an
Interchange catalog variable to be created with the name coming from
the first parameter and the value from the rest of the line, like
this:
.PP
.Vb 1
\& Variable SOMENAME whatever value you want
.Ve
To access that variable in your pages, type the token _\|_SOMENAME_\|_.
Notice that there are two underscore characters before the variable
name and two after it, and that in place of the word \s-1SOMENAME\s0 you
would put the actual name of the variable. The first thing Interchange
does on a page is to replace the token with the variable's value. The
value can also include Interchange tags to be parsed.
.Sh "A more interesting page footer"
.IX Subsection "A more interesting page footer"
You can put a contact email address at the bottom of each page in case
your customers want to contact you. You could just add it to the
footer, but by putting it into a variable you can use it in contact
pages as well. This allows you to easily change the variable
information and have that change reflected in all instances of that
variable. The following is an example of how to set a catalog variable
in \fIcatalog.cfg\fR:
.PP
.Vb 1
\& Variable CONTACT_EMAIL someone@your.domain
.Ve
Now make the following change to your template file \fIbottom\fR:
.PP
.Vb 9
\&
\&
\&- (bottom)
\&+ Contact us
\&+ if you have any questions.
\&
\&
\&