.\" 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 .Vb 1 \& Order toaster .Ve .Vb 2 \& \&
.Ve You may batch select whole groups of items: .PP .Vb 2 \&
\& .Ve .Vb 2 \& \& Standard Toaster .Ve .Vb 2 \& \& Super Toaster .Ve .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 \&
\& \& \& Qty: \& \& \&
.Ve .Vb 12 \&
\& \& \& Qty:
\& \& \& Qty:
\& \& \&
.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 \&
\& Item M3243 \& Quantity \& \& \& \&
.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 \& .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. 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 \& .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 \& .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 \& \& \&
    \& \& .Ve .Sh "left" .IX Subsection "left" .Vb 3 \& \& \& \& \& \&

    The Interchange Test Catalog

    (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 \& \& \& \& \& \& .Ve .Vb 1 \& . . . .Ve .Vb 1 \&
    Test #DescriptionPrice
    .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] \& \& \& \& \& \& \& [loop search="ra=yes/fi=products"] \& \& \& \& \& \& [/loop] \&
    Test #DescriptionPrice
    [loop-code][loop-field description][loop-field price]
    \& [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 \& \& \& \& \& \& .Ve .Vb 8 \& [item-list] \& \& \& \& \& \& \& [/item-list] .Ve .Vb 1 \& .Ve .Vb 4 \& \& \& \& .Ve .Vb 1 \&
    Qty.DescriptionCostSubtotal
    [item-quantity][item-field description][item-price][item-subtotal]
    Total:[subtotal]
    .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 1 \& .Ve .Vb 4 \& \& \& \& .Ve .Vb 4 \& \& \& \& .Ve .Vb 4 \& \& \& \& .Ve .Vb 3 \& \& \& .Ve .Vb 4 \& \& \& \& .Ve .Vb 4 \& \& \& \& .Ve .Vb 4 \& \& \& \& .Ve .Vb 4 \& \& \& \& .Ve .Vb 1 \&
    First name:
    Last name:
    Address:
    City:
    State:
    Postal code:
    Country:
    .Ve .Vb 3 \&

    \& Note: We assume that your billing address is the same as your shipping address. \&

    .Ve .Vb 1 \& .Ve .Vb 4 \& \& \& \& .Ve .Vb 10 \& \& \& \& .Ve .Vb 1 \&
    Credit card number:
    Credit card expiration date: \& Month (number from 1-12): \& \&
    \& Year (last two digits only): \& \&
    .Ve .Vb 4 \&

    \& \& \&

    .Ve .Vb 1 \&
    .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. \& \& \& \& .Ve Be sure to restart Interchange before reloading the page in your browser, since you made a change to \fIcatalog.cfg\fR. .PP Let's add another variable to your catalog. This variable demonstrates how an Interchange tag can be included in the variable. This Interchange tag returns the current date in a standard format. Add the following to \fIcatalog.cfg\fR: .PP .Vb 1 \& Variable DISPLAYDATE [time]%A, %B %d, %Y[/time] .Ve \&\fBNote: \fRSee the \fIInterchange Tag Reference Guide\fR for an explanation of the [time] tag. .PP Now add the following to the \fIleft\fR template piece: .PP .Vb 4 \& \&- (left) \&+ __DISPLAYDATE__ \& .Ve Restart Interchange and view the page. .Sh "Advanced credit card expiration date selection" .IX Subsection "Advanced credit card expiration date selection" To reduce the possibility of human error at checkout time, most online stores use a pull-down option menu to list the months and the years for the credit card expiration date, instead of having the user to type the numbers by hand. It also lets you avoid explaining whether the user should enter a 2\- or 4\-digit year. .PP Make the following change to your \fIpages/checkout.html\fR page. The section that follows explains the code. Read the explanation section below before typing the code to be sure you know where tabs should be used instead of spaces and where to watch out for `backticks`. .PP .Vb 53 \& \& Credit card expiration date: \& \&- Month (number from 1-12): \&- \&-
    \&- Year (last two digits only): \&- \&+ \&+ Month: \&+ \&+ \&+ Year: \&+ \&+ \& \& .Ve .Vb 1 \& .Ve In the first set of tags a list is generated of the months to choose from. This is accomplished by using a \fB[loop]\fR tag. In this case we are looping over an explicit list. The list is provided in the \fIlist\fR parameter. Use caution when typing this, as it is sensitive to formatting (which may not be reflected in this document). Make sure that the numbers are the first characters on each new line and that the elements are separated by a single tab. Since the columns in this list are not named, the first element can be accessed using \fB[loop-code]\fR or \fB[loop-pos 0]\fR with subsequent elements being accessed by \fB[loop-pos N]\fR where N is the number of the element you want. Notice that the elements are zero-indexed. Each time through this loop Interchange generates a select