For a complete introduction to Interchange config files and the supported syntax, please see the configuration glossary entry.
Table of Contents
AcceptRedirect — accept Web server redirects
The directive
enables processing of HTTP server redirects, i.e. when handling ErrorDocument
for a Web server such as Apache. For instance, if your Apache
httpd.conf contains
ErrorDocument 404 /cgi-bin/ic/standard
then a request for /somedir/index.html that is not found
on the Web server would be resent to
/cgi-bin/ic/standard/somedir/index.html, and
would be indistinguishable from the static Web server-served page.
Combined with the RedirectCache directive, you can automatically
create missing HTML pages in your web server's static HTML space,
so that they are found on next access.
Just beware; that turns them into static pages!
Although the idea seems attractive at first sight, caution should be taken not to allow Web server's ErrorDocument redirection to Interchange globally — it would render you subject to a denial-of-service attack at random URLs (i.e. a flood of MS Windows "Code Red" attacks). It is recommended that you enable it only for specific directories, as Apache or another HTTP server would stand much better up to such a "limited-scale" flood.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 5260 (context shows lines 5260-5272)
sub parse_yesno {
my($var, $value) = @_;
$_ = $value;
if (m/^y/i || m/^t/i || m/^1/ || m/^on/i) {
return 1;
}
elsif (m/^n/i || m/^f/i || m/^0/ || m/^of/i) {
return 0;
}
else {
config_error("Use 'yes' or 'no' for the $var directive\n");
}
}
Accounting
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 3015 (context shows lines 3015-3079)
sub parse_locale {
my($item,$settings) = @_;
return ($settings || '') unless $settings =~ /[^\d.]/;
$settings = '' if "\L$settings" eq 'default';
my $name;
my ($c, $store);
if(defined $C) {
$c = $C->{$item} || { };
$C->{$item . "_repository"} = {}
unless $C->{$item . "_repository"};
$store = $C->{$item . "_repository"};
}
else {
no strict 'refs';
$c = ${"Global::$item"} || {};
${"Global::$item" . "_repository"} = {}
unless ${"Global::$item" . "_repository"};
$store = ${"Global::$item" . "_repository"};
}
my ($eval, $safe);
if ($settings =~ s/^\s*([-\w.@]+)(?:\s+)?//) {
$name = $1;
undef $eval;
$settings =~ /^\s*{/
and $settings =~ /}\s*$/
and $eval = 1;
$eval and ! $safe and $safe = new Safe;
if(! defined $store->{$name} and $item eq 'Locale') {
my $past = POSIX::setlocale(POSIX::LC_ALL);
if(POSIX::setlocale(POSIX::LC_ALL, $name) ) {
$store->{$name} = POSIX::localeconv();
}
POSIX::setlocale(POSIX::LC_ALL, $past);
}
my($sethash);
if ($eval) {
$sethash = $safe->reval($settings)
or config_warn("bad Locale setting in %s: %s", $name, $@),
$sethash = {};
}
else {
$settings =~ s/^\s+//;
$settings =~ s/\s+$//;
$sethash = {};
%{$sethash} = Text::ParseWords::shellwords($settings);
}
$c = $store->{$name} || {};
my $nodefaults = delete $sethash->{MV_LOCALE_NO_DEFAULTS};
for (keys %{$sethash}) {
$c->{$_} = $sethash->{$_};
}
}
else {
config_error("Bad locale setting $settings.\n");
}
$C->{LastLocale} = $name if $C and $item eq 'Locale';
$store->{$name} = $c unless $store->{$name};
return $c;
}
AccumulateCode — fetch Interchange code on-demand from CodeRepository instead of starting up with everything
The directive instructs Interchange to fetch code blocks "on-demand" from the
CodeRepository instead of starting up with everything.
It helps speed up Interchange startup time and reduce memory footprint.
So, at runtime, when particular functionality is needed but is not
yet present in the running Interchange installation, it is copied from
CodeRepository to
$Global::TagDir/Accumulated/
and automatically activated.
Later, when you restart Interchange the next time, these code blocks will be
found in the accumulated directory and loaded normally
(there will be no need to fetch them from CodeRepository
again).
Over time, as you access pages and routines, a full set of tags
used by a catalog
will be copied to the accumulated directory, and you will then be
able to turn AccumulateCode off.
(In fact, AccumulateCode is recommended for development and should
really be turned off in production systems).
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 5260 (context shows lines 5260-5272)
sub parse_yesno {
my($var, $value) = @_;
$_ = $value;
if (m/^y/i || m/^t/i || m/^1/ || m/^on/i) {
return 1;
}
elsif (m/^n/i || m/^f/i || m/^0/ || m/^of/i) {
return 0;
}
else {
config_error("Use 'yes' or 'no' for the $var directive\n");
}
}
AcrossLocks — open real databases instead of fast dummy pointers
All configured databases are opened every time an Interchange page is visited and enters processing. Opening a new database connection takes time, so Interchange provides fast dummy pointer to each database until that database is actually used within the page.
Enabling this directive has the effect of disabling fast pointers and always opening real databases.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 5260 (context shows lines 5260-5272)
sub parse_yesno {
my($var, $value) = @_;
$_ = $value;
if (m/^y/i || m/^t/i || m/^1/ || m/^on/i) {
return 1;
}
elsif (m/^n/i || m/^f/i || m/^0/ || m/^of/i) {
return 0;
}
else {
config_error("Use 'yes' or 'no' for the $var directive\n");
}
}
ActionMap — modify existing or define custom Interchange actions
The directive allows creation of new (and modification of existing) Interchange ActionMaps using Perl subroutines.
If the action does not return a true value, Interchange processing will stop right there, allowing you to fully handle the request from your action.
See ActionMap glossary entry for more explanation and the list of built-in Interchange actionmaps.
Example: Replacing the Order action with a no-op
Put the following in catalog.cfg:
ActionMap order sub { 1 }
Since we effectively turned Order into a no-operation action, the usual
order link such as
<A HREF="[area order/nextpage]">Order</a>
would be equivalent to [page nextpage]Order (does nothing)</a>.
Example: Splitting a request into action map, page name and arguments
Here's an example of an actionmap "test" that translates
HTTP requests in form of test/
into actual page requests to page/argumentspage.html with optional arguments.
ActionMap test <<EOA
sub {
my $url = shift;
# Remove actionmap name from the URL
$url =~ s:^test/+::i;
# Arguments are optional
if ($url =~ s:/+(.*)$::) {
$CGI->{mv_arg} = $1;
}
$CGI->{mv_nextpage} = $url;
return 1;
}
EOA
For an introduction to Action Maps, see ActionMap glossary entry.
The standard process ActionMap has a number of
configuration settings which can be controlled through FormAction.
For catalog-level ActionMaps, Interchange does not strip the actionmap nam from the requested HTTP path; for global ActionMaps it does. See the section called “EXAMPLES”.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 2134 (context shows lines 2134-2213)
sub parse_action {
my ($var, $value, $mapped) = @_;
if (! $value) {
return $InitializeEmpty{$var} ? '' : {};
}
return if $Vend::ExternalProgram;
my $c;
if($mapped) {
$c = $mapped;
}
elsif(defined $C) {
$c = $C->{$var} ||= {};
}
else {
no strict 'refs';
$c = ${"Global::$var"} ||= {};
}
if (defined $C and ! $c->{_mvsafe}) {
my $calc = Vend::Interpolate::reset_calc();
$c->{_mvsafe} = $calc;
}
my ($name, $sub) = split /\s+/, $value, 2;
# Untaint and strip this pup
$sub =~ s/^\s*([\000-\377]*\S)\s*//;
$sub = $1;
if($sub !~ /\s/) {
no strict 'refs';
if($sub =~ /::/ and ! $C) {
$c->{$name} = \&{"$sub"};
}
else {
if($C and $C->{Sub}) {
$c->{$name} = $C->{Sub}{$sub};
}
if(! $c->{$name} and $Global::GlobalSub) {
$c->{$name} = $Global::GlobalSub->{$sub};
}
}
if(! $c->{$name} and $AllowScalarAction{$var}) {
$c->{$name} = $sub;
}
elsif(! $c->{$name}) {
$@ = errmsg("Mapped %s action routine '%s' is non-existent.", $var, $sub);
}
}
elsif ( ! $mapped and $sub !~ /^sub\b/) {
if($AllowScalarAction{$var}) {
$c->{$name} = $sub;
}
else {
my $code = <<EOF;
sub {
return Vend::Interpolate::interpolate_html(<<EndOfThisHaiRYTHING);
$sub
EndOfThisHaiRYTHING
}
EOF
$c->{$name} = eval $code;
}
}
elsif (! $C or $Global::AllowGlobal->{$C->{CatalogName}}) {
package Vend::Interpolate;
$c->{$name} = eval $sub;
}
else {
package Vend::Interpolate;
$c->{$name} = $c->{_mvsafe}->reval($sub);
}
if($@) {
config_warn("Action '%s' did not compile correctly (%s).", $name, $@);
}
return $c;
}
AddDirective — add a new configuration directive
This directive allows you to extend the set of regular
configuration
directives accepted in each catalog.cfg. The added
directives are then treated the same as the existing "built-ins".
Three standard arguments can be specified: the
directive_name,
parse_function_name and
default_value.
If the parser function is not defined (either by omitting it or
literally specifying undef), then no parser
will be called on the value at all,
and the value of the directive will be exactly what users specify in their
config files (which will usually be Perl scalar values). If the parser
argument is supplied, then the requested parser function
must already be defined because it can't be referenced
in advance. It can be defined either as a
Sub or GlobalSub block, or can refer to an existing parser
function from lib/Vend/Config.pm.
The file lib/Vend/Config.pm contains all the default
parser functions, which are recognized by the mandatory prefix
parse_. (You do not, however, include
parse_ in the parse_function_name.)
The default_value does not have to be specified.
Directly modifying Config.pm (or any other
files from the Interchange installation) is discouraged for portability and other
reasons. Therefore, to add your custom parsing function, you should
modify interchange.cfg as seen in the section called “EXAMPLES”
(note again that the parser definition
must logically come before AddDirective).
Example: Adding a new catalog configuration directive with a custom parse routine
Let's add the DocRoot directive. Put the following
in your interchange.cfg:
GlobalSub <<EOS
sub declare_extra_config {
package Vend::Config;
sub parse_docroot {
my ($var, $value) = @_;
unless ( -d $value ) { $@ = errmsg("Directory $value: $!") }
if ($@) { config_warn($@) }
return;
}
}
EOS
AddDirective DocRoot docroot "/var/www"
Example: Adding the "Swish" directive with an existing parse routine
Require module Vend::Swish Variable swish Vend::Swish AddDirective Swish hash
Note that boolean, one of the default parse functions, is
actually
a boolean list, and not a true boolean value. The list achieves the effect
of being boolean by logically returning true or false,
depending on whether the searched item is present in the list or not.
True boolean values are called "yesno"s in Interchange parlance.
Please see the configuration glossary entry for a discussion on config directives.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 2868 (context shows lines 2868-2885)
sub parse_directive {
my($name, $val) = @_;
return '' unless $val;
my($dir, $parser, $default) = split /\s+/, $val, 3 ;
if(! defined &{"parse_$parser"} and ! defined &{"$parser"}) {
if (defined $Global::GlobalSub->{"parse_$parser"}) {
no strict 'refs';
*{"Vend::Config::parse_$parser"} = $Global::GlobalSub->{"parse_$parser"};
} else {
$parser = undef;
}
}
$default = '' if ! $default or $default eq 'undef';
$Global::AddDirective = [] unless $Global::AddDirective;
push @$Global::AddDirective, [ $dir, $parser, $default ];
return $Global::AddDirective;
}
AdminSub — specify global subroutines that can be used only by catalogs listed under AllowGlobal directive
Specify global subroutines that may only be used by catalogs
which are listed under the AllowGlobal directive.
Otherwise, in the default course of action, global subroutines can be used by all catalogs.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 2957 (context shows lines 2957-2974)
sub parse_boolean {
my($item,$settings) = @_;
my(@setting) = grep /\S/, split /[\s,]+/, $settings;
my $c;
if(defined $C) {
$c = $C->{$item} || {};
}
else {
no strict 'refs';
$c = ${"Global::$item"} || {};
}
for (@setting) {
$c->{$_} = 1;
}
return $c;
}
AdminUser — specify usernames that are given full access to all catalogs, regardless of any permissions
Username and password pairs for users which are given administrator privileges to all catalogs.
This functionality is standalone — you do not need to have the access database since usernames and passwords here are specified directly.
AliasTable — specify database that contains page aliases ("redirect" instructions)
The directive specifies Interchange database that contains page aliases (default database name is alias).
This way, flypages can be aliased and redirected to different locations without performing file lookup cycles.
Primary applications include content management and creation of pseudo-paths. See the section called “EXAMPLES”.
Example: Creating AliasTable database
base_page real_page 4595 index
In our example, page 4595.html redirects
back to the index page.
You might notice that the fields names and values above are not properly aligned. This is an unfortunate nature of tab delimited files.
To minimize the chance of confusion, you can download properly composed example file alias.txt.
AllowGlobal — specify catalogs that may define subroutines and tags which operate with full Interchange server permissions
Specify catalogs that can operate with the full permissions of the Interchange server.
Don't use this directive unless the catalog user is completely trusted.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 2957 (context shows lines 2957-2974)
sub parse_boolean {
my($item,$settings) = @_;
my(@setting) = grep /\S/, split /[\s,]+/, $settings;
my $c;
if(defined $C) {
$c = $C->{$item} || {};
}
else {
no strict 'refs';
$c = ${"Global::$item"} || {};
}
for (@setting) {
$c->{$_} = 1;
}
return $c;
}
AlwaysSecure — specify pages that are always to be served over a HTTPS connection
The directive specifies Interchange pages that are always to be served over a secure (HTTPS) connection.
Example: Specifying AlwaysSecure
AlwaysSecure ord/checkout AlwaysSecure <<EOD change_password login member/account ord/billing ord/checkout ord/finalize ord/multi ord/shipping query/order_detail EOD
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 2957 (context shows lines 2957-2974)
sub parse_boolean {
my($item,$settings) = @_;
my(@setting) = grep /\S/, split /[\s,]+/, $settings;
my $c;
if(defined $C) {
$c = $C->{$item} || {};
}
else {
no strict 'refs';
$c = ${"Global::$item"} || {};
}
for (@setting) {
$c->{$_} = 1;
}
return $c;
}
AutoEnd — specify macro to be executed automatically at the end of every page access
Specify an Interchange to be invoked automatically, at the end of every page access. This step is performed after all page parsing occurs, just before the whole transaction ends.
In other respects, it behaves the same as its closely related
directive Autoload.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 3700 (context shows lines 3700-3734)
sub parse_routine_array {
my($item,$settings) = @_;
return '' unless $settings;
my $c;
if(defined $C) {
$c = $C->{$item};
}
else {
no strict 'refs';
$c = ${"Global::$item"};
}
my @mac;
if($settings =~ /^[-\s\w,]+$/) {
@mac = grep /\S/, split /[\s,]+/, $settings;
}
else {
push @mac, $settings;
}
if(ref($c) eq 'ARRAY') {
push @$c, @mac;
}
elsif($c) {
$c = [$c, @mac];
}
else {
$c = scalar(@mac) > 1 ? [ @mac ] : $mac[0];
}
return $c;
}
AutoModifier — specify products database columns containing values for product attributes
The directive specifies names of the product attributes
which should be automatically loaded from database columns.
Table, column and key identifiers belonging to a single specification
are separated by a colon (:), while multiple specifications
are separated by whitespace.
In other words,
when an item is added to the shopping cart using Interchange's routines, the
attributes declared in AutoModifier will be set to the values of the
fields in the products database.
This facility will often be employed in determining product
price, discount, tax and shipping, and
other custom attributes; these attributes will probably
be used in custom Perl code that will scan the electronic
cart contents and perform some decisions. For example, by defining
database columns heavy and
downloadable, you will be
able to perform decisions
based on $item->{heavy} and
$item->{downloadable} (but there are more access methods,
see the attribute glossary entry.
Example: Specifying AutoModifier
To set whether an item is defined as "heavy" and requires truck shipment, or is "downloadable", set:
AutoModifier heavy downloadable
Also make sure to have the heavy and downloadable columns defined in your products database.
Example: set attribute 'weighty' from inventory table, column 'heavy'
AutoModifier weighty=inventory:heavy
Example: set attribute 'heavy' from inventory table, with a different SKU
AutoModifier inventory:heavy:mv_sku
This can useful when doing shipping calculations or in embedded Perl code that works on item attributes.
See attribute for a complete introduction to item attributes.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 3678 (context shows lines 3678-3698)
sub parse_array {
my($item,$settings) = @_;
return '' unless $settings;
my(@setting) = grep /\S/, split /[\s,]+/, $settings;
my $c;
if(defined $C) {
$c = $C->{$item} || [];
}
else {
no strict 'refs';
$c = ${"Global::$item"} || [];
}
for (@setting) {
check_legal($item, $_);
push @{$c}, $_;
}
$c;
}
AutoVariable — specify config directives that are to be made available through the Variable space
Specify list of configuration directives whose values are to be made
available through the variable space.
This allows you to conveniently
write say, __, and
retrieve the corresponding configuration directive's value.
DirectiveName__
To support s, arrays and hashes of values (all three basic Perl types), the syntax had to be extended a little. With array or hash configuration directives, you need to append the index number or hash key respectively. See the section called “EXAMPLES” for clarification.
Note that the behavior of AutoVariable is not dynamic — if need
to re-invoke AutoVariable every time you want to "refresh" the
value visible through __.
DirectiveName__
Example: Enabling configuration directives through Variable space
Put the following in catalog.cfg:
VendURL http://myhost.mydomain.local/cgi-bin/ic/catalog SecureURL https://myhost.mydomain.local/cgi-bin/ic/catalog MailOrderTo root@mydomain.local SafeUntrap sort SysLog command /usr/bin/logger AutoVariable VendURL SecureURL MailOrderTo SafeUnutrap SysLog
Example: Displaying a scalar value
Put the following on a page:
Orders are e-mailed to: __MailOrderTo__
Example: Displaying an array value
Put the following on a page:
First SafeUntrap value is: __SafeUntrap_0__
The directive does not support hash keys that contain non-word characters or whitespace. Also, only the first-level of array and hash indices/keys is translated properly.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 2505 (context shows lines 2505-2536)
sub parse_autovar {
my($var, $val) = @_;
return '' if ! $val;
my @dirs = grep /\w/, split /[\s,\0]+/, $val;
my $name;
foreach $name (@dirs) {
next unless $name =~ /^\w+$/;
my $val = get_directive($name);
if(! ref $val) {
parse_variable('Variable', "$name $val");
}
elsif ($val =~ /ARRAY/) {
for(my $i = 0; $i < @$val; $i++) {
my $an = "${name}_$i";
parse_variable('Variable', "$an $val->[$i]");
}
}
elsif ($val =~ /HASH/) {
my ($k, $v);
while ( ($k, $v) = each %$val) {
next unless $k =~ /^\w+$/;
parse_variable('Variable', "$k $v");
}
}
else {
config_warn('%s directive not parsable by AutoVariable', $name);
}
}
}
Autoload — specify actions to be executed automatically at the beginning of every page access
Specify actions (in form of Perl subroutines or ITL tags) that are to be invoked automatically, on every page access. This step is performed before any page parsing occurs, and before the action or page is even determined.
The directive can be set to the name of a subroutine (Sub or
GlobalSub), or to a string containing ITL tags.
The return value from the code run is discarded.
Example: Simple Autoload example
Put the following in interchange.cfg:
GlobalSub <<EOR
sub simple_gsub {
open OUT, "> /tmp/out";
print OUT scalar localtime, "\n";
close OUT;
}
EOR
Put the following in catalog.cfg:
Autoload simple_gsub
Now, at each page visit, the file /tmp/out will
contain the access time. This example is pretty useless and does not
convey good programming practice (the file opening part), but it does
show a practical, stand-alone example.
Example: Redirect page accesses
Let's say that a new page visit is "triggered" as a result of users
submitting a HTML form. At that point, mv_nextpage
contains the name of the page to display next, of course.
The following would redirect all accesses from
directory public/ to
directory private/:
Autoload [perl] $CGI->{mv_nextpage} =~ s:^public/:private/:; [/perl]
Example: Temporary change of configuration directives
As you might know, on each page access, all catalog configuration directives (global and catalog) are "re-instantiated", and valid for the current page. This particularly convenient feature allows us to change (modify, add or delete) configuration directives as we see fit on a per-page basis, without worrying about them being persistent, and consequently, even without the need to re-set them back to original values.
The following example (put in catalog.cfg) displays a different flypage for
Opera web browsers:
Autoload <<EOA
[perl]
if ($Session->{browser} =~ /opera/i) {
$Config->{Special}->{flypage} = 'opera_flypage';
}
[/perl]
EOA
Please note that SpecialPage is the corresponding directive in
the catalog configuration (and not Special as
we see above). This is an exceptional case — the hash keys otherwise
have the same name as the catalog configuration directives themselves.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 3700 (context shows lines 3700-3734)
sub parse_routine_array {
my($item,$settings) = @_;
return '' unless $settings;
my $c;
if(defined $C) {
$c = $C->{$item};
}
else {
no strict 'refs';
$c = ${"Global::$item"};
}
my @mac;
if($settings =~ /^[-\s\w,]+$/) {
@mac = grep /\S/, split /[\s,]+/, $settings;
}
else {
push @mac, $settings;
}
if(ref($c) eq 'ARRAY') {
push @$c, @mac;
}
elsif($c) {
$c = [$c, @mac];
}
else {
$c = scalar(@mac) > 1 ? [ @mac ] : $mac[0];
}
return $c;
}
BounceReferrals — remove visible affiliate code from URLs after first access
When BounceReferrals is enabled, GET requests to URLs with
mv_pc or mv_source set to an affiliate code are redirected
to the same URL minus the affiliate code.
This keeps search engines that respect redirects from storing the affiliate code-salted URLs in their indexes, and helps them focus on the real resource with a single URL instead of a multitude of salted links.
When this directive is enabled and visitors do not already have a session
cookie (the most common case on first access), they are bounced to an URL
that does not have the affiliate code but has the session ID.
There's no easy way around this, and we consider it a separate issue from the
BounceReferrals concept.
If session IDs in URLs are a concern, they'll need a separate solution.
Historically, many application servers always bounce the first request to check for cookie support. Nowadays, many simply require cookies for anything that needs a session. Interchange is different on both counts.
Interchange 5.7.0:
Source: lib/Vend/Config.pm
Line 5260 (context shows lines 5260-5272)
sub parse_yesno {
my($var, $value) = @_;
$_ = $value;
if (m/^y/i || m/^t/i || m/^1/ || m/^on/i) {
return 1;
}
elsif (m/^n/i || m/^f/i || m/^0/ || m/^of/i) {
return 0;
}
else {
config_error("Use 'yes' or 'no' for the $var directive\n");
}
}