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.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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.9.0:
Source: lib/Vend/Config.pm
Line 3071 (context shows lines 3071-3135)
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 Vend::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.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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 the database is actually used within the page.
Enabling this directive has the effect of disabling fast pointers and always opening real databases.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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
/arguments
page.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
.
In the past, global ActionMaps had the action name stripped from the HTTP path. Beginning with Interchange 5.5, catalog and global ActionMaps are consistent in behavior and do not strip action name from the path.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2161 (context shows lines 2161-2258)
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; $name =~ s/-/_/g; ## Determine if we are in a catalog config, and if ## perl should be global and/or strict my $nostrict; my $perlglobal = 1; if($C) { $nostrict = $Global::PerlNoStrict->{$C->{CatalogName}}; $perlglobal = $Global::AllowGlobal->{$C->{CatalogName}}; } # Untaint and strip this pup $sub =~ s/^\s*((?s:.)*\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 ($perlglobal) { package Vend::Interpolate; if($nostrict) { no strict; $c->{$name} = eval $sub; } else { $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 parse 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
is optional.
Directly modifying Config.pm
(or any other
files from the Interchange installation) is discouraged for portability
reasons. Therefore, to add a 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.9.0:
Source: lib/Vend/Config.pm
Line 2924 (context shows lines 2924-2941)
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 — restrict specific global subroutines to catalogs listed under AllowGlobal directive
Restrict usage of specified global subroutines to catalogs
listed under the AllowGlobal
directive.
If AdminSub is unspecified, all global subroutines can be used by all catalogs.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3013 (context shows lines 3013-3030)
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 — (obsolete) specify usernames that are given full access to all catalogs, regardless of any permissions
Username and password pairs which are given administrator privileges to all catalogs.
Passwords are encrypted using standard Unix crypt.
This functionality is standalone — you do not need to have the users present in the UserDB or the access database.
Example: Setting AdminUser
An example with username "thunder" and password "rolls":
AdminUser thunder:H0NJOAxjci1Lw
The AdminUser functionality is considered to be flawed, see this mailing list post for more information.
This directive has been removed in Interchange 5.7 (Mar 11, 2010).
AliasTable — specify table containing page aliases ("redirect" instructions)
The directive specifies Interchange table that contains page aliases (default table 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 field names and values above are not properly aligned. This is the nature of tab delimited files.
To minimize the chance of confusion, you can download properly composed example file alias.txt.
AllowGlobal — specify catalogs allowed to operate with full Interchange server permissions
Specify catalogs allowed to operate with the full permissions of the Interchange server.
Don't use this directive unless the catalog is completely trusted.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3013 (context shows lines 3013-3030)
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; }
AllowRemoteSearch — specify database tables accessible for remote searches
Any table specified in this option will be remotely searchable, and you should not permit any table with sensitive information to be searched in this way. You should carefully consider the implications of adding any further tables to this configuration option.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 622
['AllowRemoteSearch', 'array_complete', 'products variants options'],
Source: lib/Vend/Config.pm
Line 3838 (context shows lines 3838-3851)
sub parse_array_complete { my($item,$settings) = @_; return '' unless $settings; my(@setting) = grep /\S/, split /[\s,]+/, $settings; my $c = []; for (@setting) { check_legal($item, $_); push @{$c}, $_; } $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.9.0:
Source: lib/Vend/Config.pm
Line 3013 (context shows lines 3013-3030)
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 macro 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.
Except for the time of execution, it behaves the same as its closely related
directive Autoload
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3802 (context shows lines 3802-3836)
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 table columns containing values for product attributes
The directive specifies names of the product attributes
which should be automatically loaded from table 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 decisions. For example, by defining
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 table 'inventory', column 'heavy'
AutoModifier weighty=inventory:heavy
Example: set attribute 'heavy' from table 'inventory', 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.9.0:
Source: lib/Vend/Config.pm
Line 3780 (context shows lines 3780-3800)
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 to make 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 scalars, 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 — you need
to re-invoke AutoVariable
every time you want to update the
value in __
.
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. In addition, only the first-level of array and hash indices/keys is translated properly.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2550 (context shows lines 2550-2581)
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
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3802 (context shows lines 3802-3836)
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 bounced 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.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
BounceReferralsRobot — remove visible affiliate code from URLs after first access (for robots only)
This directive is similar to BounceReferrals
but it
takes effect only on URLs accessed by robots.
This is useful for Google Analytics, Omniture SiteCatalyst, and similar analytics that need to see the referrals in the URL, and doesn't hurt anything for most users because redirecting away from the referral is most important for SEO.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
BounceRobotSessionURL — remove explicit mv_session_id in RobotUA request if provided
When BounceRobotSessionURL
is enabled, GET requests from RobotUAs
to URLs with mv_session_id
provided are redirected to the
same URL minus the session_id
This keeps search engines that respect redirects from storing the session_id-salted URLs in their indexes, and helps them focus on the real resource with a single URL instead of a multitude of salted links.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
Capability — test existence of a capability
Just like Require
or Suggest
, this directive checks for
a capability, but unlike the first two it never causes a
warning or other message. This allows a module to be loaded if available
and a program can later check for the capability and dynamically adapt to the
configuration.
"Capabilities" you can check for are:
globalsub
— existence of a GlobalSub
sub
— existence of a Sub
taggroup
— existence of a TagGroup
usertag
— existence of a UserTag
module (or perlmodule)
— existence of a Perl module
include (or perlinclude)
— prepend specified path to Perl's @INC
include path (makes most sense with Require
, not with Suggest
or Capability
even though it can be called that way for equivalent effect)
file
— existence of a readable file
executable
— existence of an executable file
Example: Testing for existence of all supported items
Capability globalsub my_global_sub Capability sub my_sub Capability taggroup :group1,:group2 :group3 Capability usertag my_global_usertag Capability usertag my_catalog_usertag Capability module Archive::Zip Capability module Set::Crontab /usr/local/perl/modules/ Capability file /etc/syslog.conf Capability file relative-dir/file Capability executable /usr/local/bin/gfont Capability executable bin/gfont
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2588 (context shows lines 2588-2590)
sub parse_capability { return parse_require(@_, 1, 1); }
CartTrigger — specify subroutines to invoke when cart contents change
The directive specifies names of the Perl subroutines to invoke when cart contents change. The subroutines can be defined on both global and catalog level.
The subroutines execute whenever the contents of cart are changed via
the standard means available through CGI variable space (i.e. when
changes are invoked via the process
system ActionMap —
through mv_order_item
and mv_order_quantity
field submissions,
or from a standard Interchange cart page).
The subroutines will be executed per-change, such that any page process resulting in multiple alterations to the cart will potentially call these functions multiple times.
The following arguments are passed to all specified subroutines:
A reference to cart
A scalar representing the action that fired the trigger; its value will be
one of add
, update
or
delete
A hashref pointing to the new row (except for the delete
action, in which case this will be undefined)
A hashref representing the old row (except for the add
action); for the update
action, this will be a
copy of the row prior to the change.
The old row will no longer be a member of the cart
The symbolic name of the cart
The return value from each subroutine call is pushed onto an array;
when the particular trigger firing is complete (i.e. all subroutines specified
in CartTrigger
have been called), the full array of results will be
returned. However, the initial version of this functionality does not use
these return values in any meaningful way.
Example: Quantity of subitems follows their master item
The quantity of sub items are automatically changed to the quantity of the corresponding master item regardless of the current quantity.
Sub <<EOS sub cascade_quantities { my ($cartref, $action, $newref, $oldref, $cartname) = @_; # act upon the main cart only return unless $cartname eq 'main'; if ($action eq 'update' && $newref->{mv_si} == 0 && $newref->{quantity} != $oldref->{quantity}) { # update quantities of sub items for my $subref (grep {$_->{mv_mi} eq $newref->{mv_mi}} @$cartref) { $subref->{quantity} = $newref->{quantity}; } } } EOS CartTrigger cascade_quantities CartTriggerQuantity Yes
It must be noted that the Interchange cart subsystem is based on arrayrefs of hashrefs (all Perl programming terms) — there is no object encapsulation for limiting or monitoring program access to the contents of any cart. Consequently, direct manipulation of the cart from within Perl will not cause these triggers to fire. The triggers only fire when the cart contents are modified through the standard Interchange CGI-based variable processing. Therefore, it is assumed (for the moment, at least) that any programmer sufficiently comfortable or confident to manipulate cart contents directly can also be given the responsibility of deciding whether or not it is appropriate to invoke cart triggers along the way.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3802 (context shows lines 3802-3836)
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; }
CartTriggerQuantity — specify whether quantity changes to cart items will cause CartTrigger subroutines to execute
The directive specifies whether quantity changes on existing cart
items will cause specified CartTrigger
subroutines to execute.
Note, however, that a quantity change to zero will result in item deletion,
and will consequently cause CartTrigger
s to execute regardless
of CartTriggerQuantity
's value.
It must be noted that the Interchange cart subsystem is based on arrayrefs of hashrefs (all Perl programming terms) — there is no object encapsulation for limiting or monitoring program access to the contents of any cart. Consequently, direct manipulation of the cart from within Perl will not cause these triggers to fire. The triggers only fire when the cart contents are modified through the standard Interchange CGI-based variable processing. Therefore, it is assumed (for the moment, at least) that any programmer sufficiently comfortable or confident to manipulate cart contents directly can also be given the responsibility of deciding whether or not it is appropriate to invoke cart triggers along the way.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
Catalog — register catalog with the Interchange server
The directive registers a catalog that will run on the corresponding Interchange installation.
The directive expects three or more arguments.
First expected is the name of the catalog. It will be referred to by the specified name in error, warning, and informational messages. It must contain only alphanumeric characters, hyphens, and underscores. It is highly recommended that it is also all lowercase.
Second argument specifies the filesystem base directory of the catalog.
If the directory does not exist, the required catalog.cfg
is not there, or Interchange
detects any other problem, catalog configuration will be skipped and the
catalog
won't be activated.
Third argument is the so called SCRIPT_NAME
of the
link program. It is a webserver path by which the catalog can be
accessed. It can be followed by different
aliases, all allowing access to
the same catalog. For example, this is useful when calling an SSL
server or a
members-only alias that requires a Basic HTTP authorization using the
username/password pair. All subsequently generated links would be called using
the aliased URL.
The script name must be unique among CGI program paths that run on the
Interchange server, unless the FullUrl
directive is specified. In this case,
hostnames can be added to differentiate otherwise same paths; as usual, see
the section called “EXAMPLES” for clarification.
It is also possible to define catalog-specific configuration directives
from the global interchange.cfg
file. Again, see the section called “EXAMPLES”.
Example: Using FullUrl to differentiate same-named catalogs on different hosts
FullUrl yes Catalog simple1 /home/catalogs/simple1 www.company1.com/cgi-bin/ic/simple Catalog simple2 /home/catalogs/simple2 www.company2.com/cgi-bin/ic/simple
Make sure to read the FullUrl
directive reference page before just
including it in your configuration.
Example: Elaborate Catalog directive definition
Given the nature of the Catalog
directive, a catalog can be registered somewhat
verbosely with:
Catalog simple directory /home/catalogs/simple Catalog simple script /cgi-bin/ic/simple Catalog simple alias /simple
Example: Defining catalog-specific directives in the global config file
Re-using the elaborate example from just above, it is also possible to define
catalog-specific directives in the global interchange.cfg
file.
This is most useful to do with the ErrorFile
and DisplayErrors
directives:
Catalog simple directive ErrorFile /var/log/interchange/simple-error.log
Catalog
is one of the basic Interchange configuration directives.
makecat, the catalog creation helper script,
automatically inserts
the Catalog
line in the interchange.cfg
file as part of the standard procedure.
If the catalog.cfg
file, expected in the catalog base directory, is not found, or is
unreadable by the Interchange server, somewhat misguiding error message will be reported.
Instead of the appropriate permissions-problem message, the mandatory
VendURL
directive will be reported as undefined.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4147 (context shows lines 4147-4248)
sub parse_catalog { my ($var, $setting) = @_; my $num = ! defined $Global::Catalog ? 0 : $Global::Catalog; return $num unless (defined $setting && $setting); my($name,$base,$dir,$script, @rest); ($name,@rest) = Text::ParseWords::shellwords($setting); my %remap = qw/ base base alias alias aliases alias directory dir dir dir script script directive directive fullurl full_url full full_url /; my ($cat, $key, $value); if ($Global::Catalog{$name}) { # already defined $cat = $Global::Catalog{$name}; $key = shift @rest; $value = shift @rest; } elsif( $var =~ /subcatalog/i and @rest > 2 and file_name_is_absolute($rest[1]) ) { $cat = { name => $name, base => $rest[0], dir => $rest[1], script => $rest[2], }; splice(@rest, 0, 3); $cat->{alias} = [ @rest ] if @rest; } elsif( file_name_is_absolute($rest[0]) ) { $cat = { name => $name, dir => $rest[0], script => $rest[1], }; splice(@rest, 0, 2); $cat->{alias} = [ @rest ] if @rest; } else { $key = shift @rest; $value = shift @rest; $cat = { name => $name }; } $key = $remap{$key} if $key && defined $remap{$key}; if(! $key) { # Nada } elsif($key eq 'alias' or $key eq 'server') { $cat->{$key} = [] if ! $cat->{$key}; push @{$cat->{$key}}, $value; push @{$cat->{$key}}, @rest if @rest; } elsif($key eq 'global') { $cat->{$key} = $Global::AllowGlobal->{$name} = is_yes($value); } elsif($key eq 'directive') { no strict 'refs'; my $p = $value; my $v = join " ", @rest; $cat->{$key} = {} if ! $cat->{$key}; my $ref = set_directive($p, $v, 1); if(ref $ref->[1] =~ /HASH/) { if(! $cat->{$key}{$ref->[0]} ) { $cat->{$key}{$ref->[0]} = { %{"Global::$ref->[0]"} }; } for (keys %{$ref->[1]}) { $cat->{$key}{$ref->[0]}{$_} = $ref->[1]->{$_}; } } else { $cat->{$key}{$ref->[0]} = $ref->[1]; } } else { $cat->{$key} = $value; } #::logDebug ("parsing catalog $name = " . uneval_it($cat)); $Global::Catalog{$name} = $cat; # Define the main script name and array of aliases return ++$num; }
CatalogUser — specify catalog-specific usernames to use when accessing files with absolute pathnames
The directive specifies catalogs and the corresponding usernames
which will be used in accessing files with absolute pathnames.
Actually, the file access itself is still performed under the Interchange
server username, but the CatalogUser
values are used for
a "would-be" kind of check.
This directive is only honored when NoAbsolute
is enabled.
Then, the situation is as follows:
Interchange allows the file to be read or written if the absolute pathname
points somewhere in the catalog directory (CATROOT) or
TemplateDir
.
Interchange allows the file to be read if the appropriate catalog's
CatalogUser
is file owner, or belongs to a user group that
can read the file. (The same analogy is used for write access).
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
CategoryField — specify name of the "category" field in the Interchange database
By default, Interchange expects item category to be in the category field in the database, if a system of categories is used. This directive allows modification of the default name.
CheckHTML — check the generated HTML code with an external program
Defines the name of an external program which will be invoked to check the generated page HTML code for correctness (/usr/bin/weblint, for example).
Note that you need to put [flag checkhtml]
on your page,
(or wrap only a block of HTML code to check in
[tag flag checkhtml]...[/tag]
)
to trigger the actual invocation of the specified external command.
The output of the HTML checker program will be included in the output page, so you might want to wrap it in HTML comments (<!-- ... -->). Then you can check it out by viewing the HTML page source in your browser.
If you want a quick way to enable or disable this feature, without
modifying each HTML page individually, put __CHECK_HTML__
on every page (or ideally, in a template). Then, to enable the
checker, define Variable CHECK_HTML [flag checkhtml]
in
interchange.cfg
. To disable it, leave the variable value empty.
Leaving this directive enabled on a production server usually leads to unnecessary performance degradation. The additional process spawn (and the time it takes to complete) every time a page is visited is costly.
Additionally, this directive currently appears to be broken (it simply never gets called).
ChildLife — define maximum child process lifetime
Interchange page servers are, by default, periodically restarted to make sure there are no problems arising from long-running processes (such as memory leaks).
In general, restarting is handled by the
MaxRequestsPerChild
configuration directive.
However, when PreFork
ic run mode is used, some page servers
never win the page server "selection battle"; they never get to serve a page
request and consequently they are never restarted by MaxRequestsPerChild
.
This is why the ChildLife
directive restarts
a page server on an unconditional, periodic basis to make sure all servers
are re-started from time to time.
If ChildLife
is not set, the "starved" page servers will act just
like they did before; get stuck in an internal loop forever until
kill -9 on the process happens.
This should clear up the problem where people see with a growing number of servers over time.
The directive should only be used when Interchange is in PreFork
ic run mode.
The directive value can be any Interchange interval.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4115 (context shows lines 4115-4127)
sub parse_time { my($var, $value) = @_; my($n); return $value unless $value; # $C->{Source}->{$var} = [$value]; $n = time_to_seconds($value); config_error("Bad time format ('$value') in the $var directive\n") unless defined $n; $n; }
CodeDef — generic subroutine mapper
A generic Perl subroutine mapper which allows mapping of subroutines to
ActionMaps,
CoreTags, UserTag
s,
filters,
form actions,
GlobalSub
s,
ItemActions,
SearchOps,
LocaleChanges,
OrderChecks,
and Widgets.
SearchOp definition needs to be a function that creates and returns a
search function. The search function will receive the data to match
and should return 1
if the value matches.
Example: Defining a custom SearchOp
Here's an exemplary "find_hammer
" SearchOp that
should be placed in interchange.cfg
:
CodeDef find_hammer SearchOp find_hammer CodeDef find_hammer Routine <<EOR sub { # Called with: # $self - search object # $i - index into coordinated search array # $string - data to match # $opname - name of the specified mv_column_op my($self, $i, $string, $opname); #::logDebug("Calling fake SearchOp"); return sub { #::logDebug("testing with fake SearchOp"); my $string = shift; $string =~ /hammer/i; }; } EOR
The above simple function does not honor mv_negate
or other
variables. See Vend::Search::create_text_query
for an example of how to create a proper search routine and honor
various associated search parameters.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5065 (context shows lines 5065-5126)
sub parse_mapped_code { my ($var, $value) = @_; return {} if ! $value; ## Can't give CodeDef a default or this will be premature get_system_code() unless defined $SystemCodeDone; my($tag,$p,$val) = split /\s+/, $value, 3; # Canonicalize $p = $tagCanon{lc $p} || '' or ::logDebug("bizarre mapped code line '$value'"); $tag =~ tr/-/_/; $tag =~ s/\W//g and config_warn("Bad characters removed from '%s'.", $tag); my $repos = $C ? ($C->{CodeDef} ||= {}) : ($Global::CodeDef ||= {}); if ($tagSkip{$p}) { return $repos; } my $dest = $valid_dest{lc $p} || $current_dest{$tag} || $CodeDest; if(! $dest) { config_warn("no destination for %s %s, skipping.", $var, $tag); return $repos; } $current_dest{$tag} = $dest; $repos->{$dest} ||= {}; my $c = $repos->{$dest}; if($Compiled{$p}) { $c->{$Compiled{$p}} ||= {}; parse_action($var, "$tag $val", $c->{$Compiled{$p}} ||= {}); } elsif(defined $tagAry{$p}) { my(@v) = Text::ParseWords::shellwords($val); $c->{$p}{$tag} = [] unless defined $c->{$p}{$tag}; push @{$c->{$p}{$tag}}, @v; } elsif(defined $tagHash{$p}) { my(%v) = Text::ParseWords::shellwords($val); $c->{$p}{$tag} = {} unless defined $c->{$p}{$tag}; for (keys %v) { $c->{$p}{$tag}{$_} = $v{$_}; } } elsif(defined $tagBool{$p}) { $c->{$p}{$tag} = 1 unless defined $val and $val =~ /^[0nf]/i; } else { config_warn("%s %s scalar parameter %s redefined.", $var, $tag, $p) if defined $c->{$p}{$tag}; $c->{$p}{$tag} = $val; } return $repos; }
CodeRepository — specify directory containing code that can be included in the running installation when needed
There is a huge base of Interchange code (collection of UserTag
s and
CodeDef
s) included in the default installation.
Much of it is not needed for the usual installations,
causing a larger process memory profile than necessary.
Furthermore, it is hard to manually determine what subset of code is required,
especially when an ITL tag calls
$Tag->
which calls some filter which calls some sort of an action —
you get the idea.
TAGNAME
()
CodeRepository
allows building catalogs with a more optimal
set of code than just "everything".
CodeRepository
depends on a related directive, AccumulateCode
.
If AccumulateCode
is disabled, operation is traditional and everything
gets loaded at Interchange startup time. (There have
been some code initialization changes and routine calling changes,
but the data structures are identical and no difference in operation
should be seen).
It's when you remove the
ICROOT/code/
directory and
enable AccumulateCode
that things get interesting.
Interchange starts looking into CodeRepository
for pieces it finds
missing (ITL tags, ActionMaps, filters, widgets, etc.)
and compiles these as needed, in runtime!
The code is sent to the master process for compilation and
incorporation, so that on the next page access (or in the worst case,
after HouseKeeping
seconds), Interchange will find the code already compiled
and ready to go.
Fetched code blocks are copied to
.
When you restart Interchange the next time, these code blocks will be found,
read normally and need not be recompiled and loaded on the fly again.
$Global::TagDir
/Accumulated/
Over time, as you access pages and routines, a full set of tags
will be developed and you can then disable AccumulateCode
.
(In fact, AccumulateCode
is recommended only for development and should
really be turned off in production systems).
Example: Setting up CodeRepository
Put the following in interchange.cfg
:
AccumulateCode Yes CodeRepository /usr/interchange/code.pool/
To prepare the code.pool/
directory, you can do something like this:
$ mkdir /usr/interchange/code.pool/ $ mv /usr/interchange/code/* /usr/interchange/code.pool/
There can be failures due to calling $Tag->
from within
embedded
Perl for the first time, particularly when it uses a "MapRoutine" or
calls another TAGNAME
()$Tag->
within. This is due to
TAGNAME
()Safe
, and there is probably
not much to be done about it. The good news is that the error should
go away after HouseKeeping
seconds, when the tag gets compiled by the
master.
area
, tmp
, tmpn
, and image
are examples of tags known
to fail in this manner.
Tags that are frequently called
in this fashion should probably be manually placed in directory
code/Vital/
and not
be accumulated "by chance".
Anyway, this temporary failure could be avoided by listing catalog in the
AllowGlobal
directive, and it
might also be possible to make a directive that allows AllowGlobal
for
a catalog automatically, when in AccumulateCode
mode.
(If you don't want to trade immediate code loading for the lack of
AllowGlobal
protection, then just set HouseKeeping
to
something like 20 seconds
— and
only do it on your development system!)
One convenient side-effect is that you can easily load new code (such as new
Interchange tags) "on the fly" by simply adding files to the CodeRepository
directory. This alleviates the need for Interchange server restart.
It might also be possible to dynamically remove and
load code from the server in this manner, but this has yet
to be looked at.
![]() | Warning |
---|---|
Nice features are often dangerous! Don't run this in production — you have been warned!
"OrderCheck"
Not fully tested in
Defining multiple tags or code blocks ( This feature only applies to global code — catalog-based code is not affected and behaves as usual. |
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3925 (context shows lines 3925-3932)
sub parse_root_dir { my($var, $value) = @_; return '' unless $value; $value = "$Global::VendRoot/$value" unless file_name_is_absolute($value); $value =~ s./+$..; return $value; }
CommonAdjust — define default settings for a flexible, chained item pricing scheme
CommonAdjust
is used to define the default settings for a flexible,
chained item pricing scheme.
The whole pricing idea and the explanation of CommonAdjust strings can be found under the price glossary entry. Make sure you read it, or you'll have only a limited success with the section called “EXAMPLES”.
Example: The pricing database
Most of the practical setups will use a separate (outboard) database to define pricing-related options. This could be all done in the products database as well, but let's stick to a visually cleaner implementation. (This database is used by other examples above!)
An example pricing database looks like this:
code common q1 q5 q10 XL S red 99-102 10 9 8 1 -0.50 0.75 00-343 2 red 0.75
Example: Adjusting item price based on size
Let's say we had a product, a t-shirt for example, and we wanted to define
a pricing adjustment based on product's size
attribute. The
price field in the
products database should have the following value
to achieve the effect:
10.00, ==size:pricing
You see, the base price of 10.00
will be adjusted
according to the size
attribute. If we had a t-shirt
with SKU 99-102
and size XL
,
then an amount of 1.00
would be added and form a total
price of 11.00
(according to the
pricing table above). The same product in size
S
(small) would have a "bonus" of -0.50
and result in 9.50
total. For any other size, the base
price would stay as-is because no matching column
would be found in pricing.
If we entered the above price specified in the
price field for item
00-343
, then an adjustment of +2
would
be made only for size variant XL
.
Example: Adjusting item price based on size and color
Let's say we had a t-shirt from previous example, and we wanted to define a pricing adjustment based on color attribute (in addition to size which we already implemented). The price field in the products database should have the following value to achieve the effect:
10.00, ==size:pricing, ==color:pricing
You see, the base price of 10.00
will be adjusted
according to both size
and color
attributes. For item SKU 99-102
, additional
0.75
would be added for a specific red
color (according to the pricing table above).
Example: Adjusting item attributes based on a common column
Let's say we had a bunch of t-shirt products and the red
color always added an additional 0.75
to the corresponding
base price.
What we know by now is that to achieve that effect, we could create a column
named red
in the pricing database.
In the same database, we would then add an entry for all t-shirt items
and put a value of 0.75
in the
red field. This approach, however,
is error-prone and of linear complexity — more t-shirt models you have,
more work is needed to catalog them properly.
The solution to this problem is elegant. Instead of defining the
red column, define one column of a
common name (common
itself is one good name for that
column), and add red
as an entry in the database.
Refer to the first example in which we show a sample
pricing database and where we did that (in the last row).
You can then instruct Interchange to search for a row in the table with item color
as key. Here's how to modify the previous example:
10.00, ==size:pricing, ==color:pricing:common
What's more, if you ever wanted to define an adjustment for another color, the only thing you'd have to do would be to add one entry in the pricing database:
blue 0.50
Example: Adjusting item price based on quantity
The price glossary entry explained the format of CommonAdjust strings. To enable quantity based pricing, we need to name the columns that will participate in the process (remember, numerical portions of the column names denote minimal quantity levels). Just in case, we can also specify a default price which will be applied only if the lookup in the pricing database returns blank or zero value. In this example, after the base price gets determined based on quantity, the size and color attributes will proceed with further price adjustment as usual:
pricing:q1,q5,q10:, ;10.00, ==size:pricing, ==color:pricing:common
In the above example, the product (a t-shirt in our example) with SKU
99-102
would have a base price of
8.00
each, if ordered in quantity of 10 or more
(again, according to the pricing table from the
beginning of the section called “EXAMPLES”).
Example: Terminating the price adjustment chain
Let's say we defined a fallback price (the same way as in the example above),
and wanted to terminate the pricing chain (skip any further adjustments
— size- and color-based adjustment in our case) if the fallback price
was applied. The code needed looks almost the same
as above, except that the colon (,
) does
not follow the fallback price:
pricing:q1,q5,q10:, ;10.00 ==size:pricing, ==color:pricing:common
In the above example, the product (a t-shirt in our example) with SKU
99-102
would have a base price of
8.00
each, if ordered in quantity of 10 or more
(again, according to the pricing table from the
beginning of the section called “EXAMPLES”).
Example: Using the "mix-and-match" feature
As mentioned in the price glossary entry, you can have quantities of different items (but which belong to the same product group) added together to determine the appropriate price class. With a pricing table of:
sku price_group q5 q10 q25 os28004 group_a 10 9 8 os28008 group_a 20 18 17
and a CommonAdjust
setting of:
pricing:price_group,q5,q10,q25
the price for six items os28004 would be 9.00
each, and
the price for three items os28008 would be 18.00
each.
(No, this is not a mistake in the text, take another look at the description).
ConfDir — specify catalog "config" directory
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3975 (context shows lines 3975-3989)
sub parse_relative_dir { my($var, $value) = @_; if (absolute_or_relative($value)) { config_error('Path %s not allowed in %s directive', $value, $var); } $C->{Source}{$var} = $value; $value = "$C->{VendRoot}/$value" unless file_name_is_absolute($value); $value =~ s./+$..; $value; }
ConfigAllAfter — specify config files to read as part of every catalog's configuration, after all its files are read in first
Specify configuration files to read as a part of every catalog's configuration, after all other corresponding catalog config files are processed.
This is useful to catch user configuration errors, supply missing values, or force your settings over user's configuration.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3934 (context shows lines 3934-3950)
sub parse_root_dir_array { my($var, $value) = @_; return [] unless $value; no strict 'refs'; my $c = ${"Global::$var"} || []; my @dirs = grep /\S/, Text::ParseWords::shellwords($value); foreach my $dir (@dirs) { $dir = "$Global::VendRoot/$dir" unless file_name_is_absolute($dir); $dir =~ s./+$..; push @$c, $dir; } return $c; }
ConfigAllBefore — specify config files to read as part of every catalog's configuration, before any of its files are read in
Specify configuration files to read as a part of every catalog's configuration, before any other corresponding catalog config files are processed.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3934 (context shows lines 3934-3950)
sub parse_root_dir_array { my($var, $value) = @_; return [] unless $value; no strict 'refs'; my $c = ${"Global::$var"} || []; my @dirs = grep /\S/, Text::ParseWords::shellwords($value); foreach my $dir (@dirs) { $dir = "$Global::VendRoot/$dir" unless file_name_is_absolute($dir); $dir =~ s./+$..; push @$c, $dir; } return $c; }
ConfigDatabase — specify database holding definitions usually found in catalog.cfg
The directive allows one to keep the usual catalog.cfg
definitions in a
database table.
By using the special option LOAD
, it is also possible to
instruct Interchange to fill the database with initial data found in your
catalog.cfg
— just make sure to remove that option on subsequent restarts.
Example: Defining ConfigDatabase
You first need to create the table in an SQL database that you will use to store config directives. Here's the SQL code needed:
create table config ( code varchar(32) NOT NULL PRIMARY KEY, directive varchar(64) NOT NULL, value varchar(255), extended text );
Just for the record, once you have the above database table, sample database contents of:
code|directive|value|extended C0001|VariableDatabase|variable C0002|SessionExpire|2 hours| C0003|Variable|foo| bar
will correspond to the usual catalog.cfg
definitions:
VariableDatabase variable SessionExpire 2 hours Variable foo <<EOF bar EOF
Example: Automatically populating ConfigDatabase with initial data from catalog.cfg
ConfigDatabase config config.txt dbi:mysql:config ConfigDatabase config LOAD 1
Even though this appears to be both global and catalog configuration directive, it is only implemented on catalog level.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4284 (context shows lines 4284-4427)
sub parse_config_db { my($name, $value) = @_; my ($d, $new); unless (defined $value && $value) { $d = {}; return $d; } if($C) { $d = $C->{ConfigDatabase}; } else { $d = $Global::ConfigDatabase; } my($database,$remain) = split /[\s,]+/, $value, 2; $d->{'name'} = $database; if(!defined $d->{'file'}) { my($file, $type) = split /[\s,]+/, $remain, 2; $d->{'file'} = $file; if( $type =~ /^\d+$/ ) { $d->{'type'} = $type; } elsif( $type =~ /^(dbi|sql)\b/i ) { $d->{'type'} = 8; if($type =~ /^dbi:/) { $d->{DSN} = $type; } } # LDAP elsif( $type =~ /^ldap\b/i) { $d->{'type'} = 9; if($type =~ /^ldap:(.*)/i) { $d->{LDAP_HOST} = $1; } } # END LDAP elsif( "\U$type" eq 'TAB' ) { $d->{'type'} = 6; } elsif( "\U$type" eq 'PIPE' ) { $d->{'type'} = 5; } elsif( "\U$type" eq 'CSV' ) { $d->{'type'} = 4; } elsif( "\U$type" eq 'DEFAULT' ) { $d->{'type'} = 1; } elsif( $type =~ /[%]{1,3}|percent/i ) { $d->{'type'} = 3; } elsif( $type =~ /line/i ) { $d->{'type'} = 2; } else { $d->{'type'} = 1; $d->{DELIMITER} = $type; } } else { my($p, $val) = split /\s+/, $remain, 2; $p = uc $p; if(defined $Explode_ref{$p}) { my($ak, $v); my(@v) = Text::ParseWords::shellwords($val); @v = grep defined $_, @v; $d->{$p} = {} unless defined $d->{$p}; for(@v) { my ($sk,$v) = split /\s*=\s*/, $_; my (@k) = grep /\w/, split /\s*,\s*/, $sk; for my $k (@k) { if($d->{$p}->{$k}) { config_warn( qq{Database %s explode parameter %s redefined to "%s", was "%s".}, $d->{name}, "$p --> $k", $v, $d->{$p}->{$k}, ); } $d->{$p}->{$k} = $v; } } } elsif(defined $Hash_ref{$p}) { my($k, $v); my(@v) = Vend::Util::quoted_comma_string($val); @v = grep defined $_, @v; $d->{$p} = {} unless defined $d->{$p}; for(@v) { ($k,$v) = split /\s*=\s*/, $_; if($d->{$p}->{$k}) { config_warn( qq{Database %s hash parameter %s redefined to "%s", was "%s".}, $d->{name}, "$p --> $k", $v, $d->{$p}->{$k}, ); } $d->{$p}->{$k} = $v; } } elsif(defined $Ary_ref{$p}) { my(@v) = Text::ParseWords::shellwords($val); $d->{$p} = [] unless defined $d->{$p}; push @{$d->{$p}}, @v; } else { defined $d->{$p} and ! defined $C->{DatabaseDefault}{$p} and config_warn( qq{Database %s scalar parameter %s redefined to "%s", was "%s".}, $d->{name}, $p, $val, $d->{$p}, ); $d->{$p} = $val; } } #::logDebug("d object: " . uneval_it($d)); if($d->{ACTIVE} and ! $d->{OBJECT}) { my $name = $d->{'name'}; $d->{OBJECT} = Vend::Data::import_database($d) or config_error("Config database $name failed import.\n"); } elsif($d->{LOAD} and ! $d->{OBJECT}) { my $name = $d->{'name'}; $d->{OBJECT} = Vend::Data::import_database($d) or config_error("Config database $name failed import.\n"); if( $d->{type} == 8 ) { $d->{OBJECT}->set_query("delete from $name where 1 = 1"); } } return $d; }
ConfigDir — specify default "include" directory for "<file" notation
Specify the default "include" directory for files that are specified
using the <filename
notation and have a relative
pathname. See the section called “EXAMPLES” for clarification.
Example: Setting directive value from a file
In combination with the above example, the following would read the
directive value from file variables/mailorderto
(relative to the CATROOT, of course).
MailOrderTo <mailorderto
See the configuration glossary entry for complete information on Interchange config file syntax.
Make sure you don't get confused by the existence of all
DirConfig
, ConfDir
and ConfigDir
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3975 (context shows lines 3975-3989)
sub parse_relative_dir { my($var, $value) = @_; if (absolute_or_relative($value)) { config_error('Path %s not allowed in %s directive', $value, $var); } $C->{Source}{$var} = $value; $value = "$C->{VendRoot}/$value" unless file_name_is_absolute($value); $value =~ s./+$..; $value; }
ConfigParseComments — (obsolete) treat config meta-directives as plain comments
When disabled (set to No
),
configuration meta-directives such as
#include
,
#ifdef
and
#ifndef
,
are treated as pure comments with no specific meaning.
However, since those were originally borrowed from the C preprocessor,
and, true to their C heritage, they started with an '#
'
(hash) character in Interchange versions up to and including 4.6.
This was inconvenient for newcomers who were easily misguided by thinking those were just comments, so Interchange versions 4.7 and up were changed to use the meta-directives without the hash prefix.
Example: Config parser behavior with ConfigParseComments disabled
ConfigParseComments No #include comment # This, and the above line, are pure comments. # You better prepare the file named 'comment' for the following one: include comment
This directive is obsolete as of Interchange 5.5.0, and the behavior is
as if ConfigParseComments No
was specified.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2994 (context shows lines 2994-3006)
sub parse_warn { my($name, $val) = @_; return '' unless $val; ::logGlobal({level => 'info'}, errmsg("Directive %s no longer supported at line %s of %s.", $name, $., $configfile, ) ); }
CookieDomain — set domain common to all servers providing Interchange content
The directive specifies the domain common to all servers providing Interchange content.
By default, the session ID cookie domain is set to the hostname
you're accessing. For example, if you access the catalog using
server myhost.mydomain.local
, then cookie will be set by
myhost.mydomain.local
.
Things, however, go bad if you use more Interchange servers
(in a non-transparent way for the user) to provide content.
For example, if SSL content was served from host
ssl.mydomain.local
, then users would have one
session for myhost.mydomain.local
and another for
ssl.mydomain.local
. This is undesired, of course.
To fix the described problem, we need to find part of the
FQDN that is common to all servers (mydomain.local
in our example), and add it as the
domain=
parameter to the
Set-Cookie
directive that we send off to users'
browsers. That's what the CookieDomain
does.
CookieDomain
accepts a space-separated list of domains to set
cookies for, in which case the Set-Cookie: ...
is sent to the client for each of the specified domains. Due to the cookie
restrictions described in the section called “NOTES”,
specifying multiple domains is only rarely (if ever?) needed and
possible to implement.
The cookie specification mandates that the domain part must contain
at least two fields (or 1 dot lying in between). The value
of .mydomain.local
is valid, but .local
wouldn't be.
Furthermore, cookie source can only be the FQDN of the host itself, or
some of the subdomains, or domain it belongs to. Browsers will ignore
all cookies that do not satisfy this requirement. Host
myhost.mydomain.local
can set a cookie for itself or the
domain mydomain.local
, but it cannot set a cookie
for say, mydomain.local2
. It is very fortunate we
have this protection, or unrelated sites would read and set each other's
cookies — something we definitely don't want to happen!
At least in Mozilla-like browsers, the domain is prefixed with a
dot even if you omit it in the CookieDomain
specification
(mydomain.local
ends up being the same as
.mydomain.local
).
For a complete discussion on cookies, see cookie glossary entry.
CookieLogin — allow autologin based on username and password stored in a client cookie
The directive allows Interchange to save users' authentication info (username/password)
in a cookie. Cookie expiration time is set by SaveExpire
and is
renewed each time they log in.
If the login and password information can be read from a cookie, then users can be logged in to the site automatically as they visit it.
To cause the cookie to be generated originally,
mv_cookie_password
and/or mv_cookie_username
must be set
to a true value.
The former causes both username and password to be saved; the latter just
the username.
For a complete discussion on cookies, see cookie glossary entry.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
CookieName — specify Interchange session cookie name
The directive sets the name of the Interchange cookie that
will be used to retrieve session ID information in users' browsers.
The default value is MV_SESSION_ID
.
The default should never be changed, but this configuration directive can save the day if you need to use cookies issued by programs other than Interchange itself.
By default, Interchange cookie planted in user's browser consists of a session ID followed by a colon followed by an IP address, username or domain name.
If the cookie is generated by another program and CookieName
is set appropriately, Interchange will take it over without modification.
For a complete discussion on cookies, see cookie glossary entry.
CookiePattern — specify regular expression to extract session ID out of a client cookie
The directive sets the regular expression that Interchange will use to extract the session ID out of the client browser's cookie.
This is useful in extracting session IDs out of cookies generated by programs other than Interchange.
Example: Setting CookiePattern
The default regular expression pattern used for CookiePattern
might work sometimes, but I find it unsuitable if you just want to change
the CookieName
, because it then breaks the usual behavior.
Here's a better value for common setups:
CookiePattern \w{8,32}
In general, however, you should only modify CookiePattern
default
value if you somehow change the content
that Interchange stores in browser cookies (by say, letting other program create
the cookie).
For a complete discussion on cookies, see cookie glossary entry.
By default, Interchange cookie planted in user's browser consists of a session ID followed by a colon followed by an IP address, username or domain name.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3891 (context shows lines 3891-3903)
sub parse_regex { my($var, $value) = @_; eval { my $never = 'NeVAirBE'; $never =~ m{$value}; }; if($@) { config_error("Bad regular expression in $var."); } return $value; }
Cookies — specify whether Interchange will try to send session cookies to client browsers
The directive determines whether Interchange will send cookie to the client and read it back to keep track of session ID.
For a complete discussion on cookies, see cookie glossary entry.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
CountrySubdomains — honor ccTLD domains in IP qualification
This directive enables Interchange to take ccTLDs into account when
DomainTail
is enabled.
For example, if a visit comes from an address like
"machine.example.co.uk
" and co.uk
is listed as ccTLD, then, with
CountrySubdomains
, "example.co.uk
" would be used
as domain tail instead of just "co.uk
".
CountrySubdomains
accepts a list of country codes and their
subdomains. A predefined, ready for use configuration
block can be found in file
dist/subdomains.cfg in Interchange source and
should be included from interchange.cfg
.
Example: Appending or overwriting entries in CountrySubdomains list
CountrySubdomains <<EOC ae "ac gov mil name net org pro sch" af "bank com edu gov hotel law music net org tv" ag "co com org net nom" al "com edu gov net org" ao "co ed gv it og pb" EOC CountrySubdomains ar "com edu gov int mil net org" at "ac co gv or priv"
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
CreditCardAuto — encrypt credit card information automatically
The directive enables automatic encryption and saving of credit card information.
The EncryptProgram
directive must be configured and working first.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
CustomShipping — specify SQL query to use in obtaining shipping costs data
DNSBL — specify real-time DNS blocklist servers
The directive allows definition of realtime blocklist servers (special-purpose DNS servers) that should be contacted in order to verify client IP address "validity". This way, you can deny access to known-bad clients (such as ones coming in from open proxy servers).
Many fraudulent credit card orders are placed from open proxy machines to hide the actual identity of the criminal, so denying access to open-proxy visitors might be a good idea.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3780 (context shows lines 3780-3800)
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; }
DataTrace — trace DBI calls with variable granularity
Trace Perl DBI calls with variable granularity. As this tends to produce large amounts of output, only use it if there's a strong chance that your problem is related to DBI.
Setting of 0
disables tracing.
Setting of 1
traces DBI method calls with return values (or errors).
Setting of 2
traces as (1) plus the parameters used in method calls.
Setting of 3
traces as (2) plus some high-level information from the driver, and some internal information from the DBI
Setting of 4
traces as (3) plus more detailed information from the driver. Also includes DBI mutex information when using threaded Perl
Setting of 5
traces as (4) plus more and more obscure information.
Trace level of 1
is suitable in most situations.
Keep in mind that, since the trace output is directed to the debug file,
you need to have the DEBUG
global variable
defined, and DebugFile
properly set.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
Database — register existing database table for use with Interchange
The directive registers a database table for use with Interchange.
table_name
specifies an arbitrary name — name
that will be used to refer to the table within Interchange. Names can be composed
of alphanumeric characters including underscore, and we recommend they're in
all lower- or upper-case.
source_file
specifies the initial database text
source file, and type
specifies database format.
For more about Interchange and databases, and supported formats, see database glossary entry.
Example: Automatically configure all tables from an existing PostgreSQL database
DatabaseAutoIgnore ^sql_ DatabaseAuto __SQLDSN__ NoImportExternal Yes
For further discussion, see DatabaseAuto
.
Example: Definition of a Postgres database table
# # Required for PostgreSQL # Require module DBI Require module DBD::Pg Variable SQLDSN dbi:Pg:dbname=database_name Variable SQLUSER username Variable SQLPASS password Variable SOME_DATABASE 1 <ParseVariables Yes> DatabaseDefault USER __SQLUSER__ DatabaseDefault PASS __SQLPASS__ DatabaseDefault NO_ASCII_INDEX 1 Message -i -n Using PostgreSQL, DSN=__SQLDSN__... # # Individual database table definitions # Database table_name table_name.txt __SQLDSN__ </ParseVariables> # # Optional table descriptions # Database table_name LENGTH_EXCEPTION_DEFAULT truncate_log Database table_name DEFAULT_TYPE varchar(255) Database table_name KEY sku Database table_name HIDE_FIELD inactive Database table_name COLUMN_DEF "sku=varchar(64) NOT NULL PRIMARY KEY" Database table_name COLUMN_DEF "description=varchar(128)" Database table_name COLUMN_DEF "price=varchar(12)" Database table_name INDEX description Database table_name INDEX price
For the above example to work, you will need file
present within table_name.txt
ProductDir
, containing the initial data set for the table. If there's no initial data set and the table should be empty, the file still needs to contain a single line with three column names, separated by a TAB:
sku description price
In Interchange, words table
and database
are used to refer to the same thing — database table.
Defining databases on an Interchange (global) level
won't work. If you want to share
databases among catalogs, define them in each catalog.cfg
separately (possibly
by including the generic file with Database
definitions).
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4442 (context shows lines 4442-4639)
sub parse_database { my ($var, $value) = @_; my ($c, $new); if (! $value) { $c = {}; return $c; } $c = $C ? $C->{Database} : $Global::Database; my($database,$remain) = split /[\s,]+/, $value, 2; if( ! defined $c->{$database} ) { $c->{$database} = { 'name' => $database, included_from => $configfile }; $new = 1; } my $d = $c->{$database}; if($new) { my($file, $type) = split /[\s,]+/, $remain, 2; $d->{'file'} = $file; if($file eq 'AUTO_SEQUENCE') { # database table missing for AUTO_SEQUENCE directive config_error('Missing database %s for AUTO_SEQUENCE %s.', $database, $type); return $c; } if( $type =~ /^\d+$/ ) { $d->{'type'} = $type; } elsif( $type =~ /^(dbi|sql)\b/i ) { $d->{'type'} = 8; if($type =~ /^dbi:/) { $d->{DSN} = $type; } } # LDAP elsif( $type =~ /^ldap\b/i) { $d->{'type'} = 9; if($type =~ /^ldap:(.*)/i) { $d->{LDAP_HOST} = $1; } } # END LDAP elsif( $type =~ /^ic:(\w*)(:(.*))?/ ) { my $class = $1; my $dir = $3; $d->{DIR} = $dir if $dir; if($class =~ /^default$/i) { # Do nothing } elsif($class) { $class = uc $class; if(! $Vend::Data::db_config{$class}) { config_error("unrecognized IC database class: %s (from %s)", $class, $type); } $d->{Class} = $class; } $d->{'type'} = 6; } elsif( "\U$type" eq 'TAB' ) { $d->{'type'} = 6; } elsif( "\U$type" eq 'PIPE' ) { $d->{'type'} = 5; } elsif( "\U$type" eq 'CSV' ) { $d->{'type'} = 4; } elsif( "\U$type" eq 'DEFAULT' ) { $d->{'type'} = 1; } elsif( $type =~ /[%]{1,3}|percent/i ) { $d->{'type'} = 3; } elsif( $type =~ /line/i ) { $d->{'type'} = 2; } else { $d->{'type'} = 1; $d->{DELIMITER} = $type; } if ($d->{'type'} eq '8') { $d->{Class} = 'DBI' } elsif ($d->{'type'} eq '9') { $d->{Class} = 'LDAP' } else { $d->{Class} ||= $Global::Default_database } if($C and $C->{DatabaseDefault}) { while ( my($k, $v) = each %{$C->{DatabaseDefault}}) { $d->{$k} = $v; } } $d->{HOT} = 1 if $d->{Class} eq 'MEMORY'; #::logDebug("parse_database: type $type -> $d->{type}"); } else { my($p, $val) = split /\s+/, $remain, 2; $p = uc $p; #::logDebug("parse_database: parameter $p = $val"); if(defined $Explode_ref{$p}) { my($ak, $v); $val =~ s/,+$//; $val =~ s/^,+//; my(@v) = Text::ParseWords::shellwords($val); @v = grep length $_, @v; $d->{$p} = {} unless defined $d->{$p}; for(@v) { my ($sk,$v) = split /\s*=\s*/, $_; my (@k) = grep /\w/, split /\s*,\s*/, $sk; for my $k (@k) { if($d->{$p}->{$k}) { config_warn( qq{Database %s explode parameter %s redefined to "%s", was "%s".}, $d->{name}, "$p --> $k", $v, $d->{$p}->{$k}, ); } $d->{$p}->{$k} = $v; } } } elsif(defined $Hash_ref{$p}) { my($k, $v); my(@v) = Vend::Util::quoted_comma_string($val); @v = grep defined $_, @v; $d->{$p} = {} unless defined $d->{$p}; for(@v) { ($k,$v) = split /\s*=\s*/, $_; if($d->{$p}->{$k}) { config_warn( qq{Database %s hash parameter %s redefined to "%s", was "%s".}, $d->{name}, "$p --> $k", $v, $d->{$p}->{$k}, ); } $d->{$p}->{$k} = $v; } } elsif(defined $Ary_ref{$p}) { my(@v) = Text::ParseWords::shellwords($val); $d->{$p} = [] unless defined $d->{$p}; push @{$d->{$p}}, @v; } elsif ($p eq 'COMPOSITE_KEY') { ## Magic hardcode if($d->{type} == 8) { $d->{Class} = 'DBI_CompositeKey'; $d->{$p} = $val; } else { config_warn( 'Database %s parameter in type with no handling. Ignored.', $p, ); } } elsif ($p eq 'CLASS') { $d->{Class} = $val; } elsif ($p =~ /^(MEMORY|SDBM|GDBM|DB_FILE|LDAP)$/i) { $d->{Class} = uc $p; } elsif ($p eq 'ALIAS') { if (defined $c->{$val}) { config_warn("Database '%s' already exists, can't alias.", $val); } else { $c->{$val} = $d; } } elsif ($p =~ /^MAP/) { Vend::Table::Shadow::_parse_config_line ($d, $p, $val); } else { defined $d->{$p} and ! defined $C->{DatabaseDefault}{$p} and config_warn( qq{Database %s scalar parameter %s redefined to "%s", was "%s".}, $d->{name}, $p, $val, $d->{$p}, ); $d->{$p} = $val; } $d->{HOT} = 1 if $d->{Class} eq 'MEMORY'; } return $c; }
DatabaseAuto — register database tables for use with Interchange automatically
The directive automatically registers database tables found for use with Interchange.
This only works for SQL databases, and the parameters provided to
DatabaseAuto
are used to establish the connection to the database.
For example, a setting of
DatabaseAuto dbi:mysql:test_foundation interch pass
would do the equivalent of:
NoImportTABLENAME
DatabaseTABLENAME
TABLENAME
.txt dbi:mysql:test_foundation
DatabaseTABLENAME
USERinterch
DatabaseTABLENAME
PASSpass
for every table (and not view, by default) found in the database test_foundation.
Any additional space-separated arguments are passed to DBI's
table_info
method as the catalog
, schema
,
name
, and type
(optionally quoted in
shell syntax). Since order is significant, you could use ''
to skip values.
Currently, the catalog
argument is not used by any
database driver, but it
may be in the future. The other options (schema
,
name
and type
) are database-specific;
see the DBI manual, appropriate DBD manual and
the section called “EXAMPLES” for details and examples.
If the Perl module DBIx::DBSchema
was found,
it would also dump the specification needed to re-create the table structures
(just like the CREATE_SQL
parameter to Database
):
DatabaseTABLENAME
CREATE_SQL CREATE TABLETABLENAME ( ...)
This information is available in $Vend:Cfg
(global
context) or $Config
(catalog context) and it is
trivial to dump it to the screen or file.
See the section called “EXAMPLES”.
Example: Standard DatabaseAuto definition, a standalone example
First, make sure MySQL is installed, then connect to it as root (using the mysql command-line tool), and issue the following commands to both create a sample database and allow access to it:
create database interchange; use interchange; create table table1(code INT, price INT, description VARCHAR(60)); create table table2(code INT, price INT, description VARCHAR(60)); create table table3(code INT, price INT, description VARCHAR(60)); create table table4(code INT, price INT, description VARCHAR(60)); grant all privileges on interchange.* to interchange@localhost identified by 'pass';
Add the following to your catalog.cfg
:
DatabaseAuto dbi:mysql:interchange interchange pass
At Interchange restart or catalog reconfiguration time, Interchange should discover the tables in the database and make them available for use.
Example: Getting a dump of $Vend::Cfg and extracting table creation commands
If DBIx::DBSchema
Perl module is installed, Interchange
is able to produce the commands that you need to run to recreate the structure
of the database tables. This can be useful for backup purposes and remote
copying, or just to get the layout, tune it to your needs, insert literally in
catalog.cfg
and finally turn off DatabaseAuto
.
So first of all, implement the above base example.
Then make sure the DBIx::DBSchema
module is
installed by making Interchange fail to configure the catalog if it's missing —
add the following to your catalog.cfg
:
Require module DBIx::DBSchema
Then, to dump CREATE_TABLE
sequence for say,
table1, add the following to a separate Interchange page:
Creation sequence: <pre> [perl] $Config->{Database}->{table1}->{CREATE_SQL}; [/perl] </pre>
Alternatively, to dump the complete $Vend::Cfg
structure,
you could create a "cfgdump
" usertag (see
dump-vend-structure
).
Then you could simply restart Interchange and call
<pre>[cfgdump]</pre>
in any Interchange page, and search
for table1 in the output.
Example: Specifying PostgreSQL schema
The following setting for PostgreSQL would make Interchange only see the tables
in the public
schema of a database, and not in
any other schemas.
DatabaseAuto dbi:Pg:dbname=DBNAME USERNAME PASSWORD '' public
Example: Making Interchange recognize views
DatabaseAuto dbi:Pg:dbname=DBNAME USERNAME PASSWORD '' public '' VIEW
(The VIEW
argument should be passed as shown
— literally and in uppercase).
Example: Automatically configure all tables from an existing PostgreSQL database
Variable SQLDSN dbi:Pg:dbname=DATABASE_NAME DatabaseAutoIgnore ^sql_ DatabaseAuto __SQLDSN__ NoImportExternal Yes
For more about Interchange and databases, and supported formats, see database glossary entry.
The schema
argument to this directive can be specified when
you want to avoid using the DatabaseAutoIgnore
directive (it's drawback
is that it could easily ignore more tables than you really intended).
Also be aware that it is possible to make some confusing configuration mistakes
here, if the schema you specify is not in the database user's
SEARCH_PATH
session variable,
or comes after some other schema that has tables with the same names.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4429 (context shows lines 4429-4440)
sub parse_dbauto { my ($var, $value) = @_; return '' unless $value; my @inc = Vend::Table::DBI::auto_config($value); my %noed; for(@inc) { my ($t, $thing) = @$_; parse_boolean('NoImport', $t) unless $noed{$t}++; parse_database('Database', "$t $thing"); } return 1; }
DatabaseAutoIgnore — prevent DatabaseAuto from configuring tables whose names match regex pattern
The directive allows regexp specification of an "ignore list" that
prevents DatabaseAuto
from automatically configuring
all tables found. (For example, you will want
to exclude tables in non-default schemas.)
A loose regex specification can easily ignore more tables than you
intended, and if the goal is just using tables from the public schema, you
might prefer specifying schema
argument to
DatabaseAuto
directly.
Example: Specifying DatabaseAutoIgnore
This prevents Interchange from bringing in tables in non-default schemas in PostgreSQL 7.4 and newer.
DatabaseAutoIgnore ^sql_ DatabaseAuto dbi:Pg:dbname=DBNAME;host=PGHOST
This directive must be set before DatabaseAuto
to have a meaningful
effect.
For more about Interchange and databases, and supported formats, see database glossary entry.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3891 (context shows lines 3891-3903)
sub parse_regex { my($var, $value) = @_; eval { my $never = 'NeVAirBE'; $never =~ m{$value}; }; if($@) { config_error("Bad regular expression in $var."); } return $value; }
DatabaseDefault — specify default settings for Database directives
The directive defines default parameters for a database.
For a list of possible parameters (keys), see the Database
directive.
DatabaseDefault
accepts scalar keys, which actually
means all from the list above except:
ALTERNATE_*
BINARY
COLUMN_DEF
DEFAULT
FIELD_ALIAS
FILTER_*
NAME
NUMERIC
POSTCREATE
WRITE_CATALOG
Example: Specify default SQL connection username and password
Most Interchange applications use only one SQL database. In that case,
it is handy to specify the default SQL username and password once, instead of
repeating it for each table separately.
Here's a possible catalog.cfg
setting:
DatabaseDefault USER interchange DatabaseDefault PASS nevairbe
Example: Specifying WRITE_CONTROL and WRITE_TAGGED defaults
DatabaseDefault WRITE_CONTROL 1 DatabaseDefault WRITE_TAGGED 1
Example: Specifying defaults in here-document style
DatabaseDefault <<EOD WRITE_CONTROL 1 WRITE_TAGGED 1 HIDE_AUTO_FILES 1 EOD
Those default settings are made when the table is initially defined, so explicit settings for the database itself override the defaults, of course.
To have the intended effect, this directive must be set before the appropriate
databases are defined with the Database
directive.
For a way to clear definitions, use the Replace
directive.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
DebugFile — specify Interchange debug output filename
Specify the Interchange debug output file. If the filename is not absolute, it is treated relative to the Interchange root directory (ICROOT).
When enabled, the debug file will gather output of the
::logDebug()
Interchange statements and Perl warnings
(if they are enabled).
Keep in mind that
you need to have the DEBUG
global variable
defined.
Also, as the ::logDebug()
statements are disabled
(commented)
by default in Interchange sources, you'll probably want to use a special
script for managing debug statements, or manually uncomment parts of
debugging code in question (and restart Interchange, of course —
see Q: ).
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3925 (context shows lines 3925-3932)
sub parse_root_dir { my($var, $value) = @_; return '' unless $value; $value = "$Global::VendRoot/$value" unless file_name_is_absolute($value); $value =~ s./+$..; return $value; }
DebugHost — restrict debug mode to requests originating from specific hosts
The DebugHost
configuration directive restricts
debug mode to only selected list of client hosts.
DebugHost accepts a list of IP addresses and IP address ranges.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3905 (context shows lines 3905-3920)
sub parse_ip_address_regexp { my ($var, $value) = @_; return '' unless $value; my @atoms = split /[\s,\0]/, $value; eval { require Net::IP::Match::Regexp; }; $@ and config_error("$var directive requires module: $@"); my $re = Net::IP::Match::Regexp::create_iprange_regexp(@atoms) or config_error("Improper IP address range for $var"); return $re; }
DebugTemplate — specify format of debug messages
[time_spec
] | {CALLER0}
... {CALLER9}
| {CATALOG}
| {HOST}
| {MESSAGE}
| {PAGE}
| {REMOTE_ADDR}
| {TAG}
...
DebugTemplate
, a global directive, allows you to change the
format of debug messages.
time_spec
-
POSIX::strftime() format specifiers. Take
a look at the time glossary entry for a complete list. Since the
character %
is treated as the beginning of a specifier,
use %%
to insert a literal %
.
{CALLER0}
... {CALLER9}
-
members of the caller() list (see caller() Perl function).
{CATALOG}
- catalog name
{HOST}
- remote hostname or IP address
{MESSAGE}
- actual debug message
{PAGE}
- current page name (MV_PAGE
)
{REMOTE_ADDR}
- remote IP address
{TAG}
- current tag name
(from Vend::Parse
)
DefaultLocale — specify default locale
Example: Achieving effect of DefaultLocale using Locale directive
Exactly the same effect as in the above example can be produced with:
Locale hr_HR default 1
DefaultShipping — specify default shipping method
The directive specifies the default shipping method by
initializing the mv_shipmode
variable.
It defaults to a value "default
".
DeleteDirective — disable use of specified configuration directive in catalog.cfg
This directive specifies the directives which are to be disabled during parse
of the catalog.cfg
files.
This can be effectively used to both save some memory on servers with many catalogs and prevent catalogs from setting some of the directives.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 411 (context shows lines 401-407)
['DeleteDirective', sub { my $c = $Global::DeleteDirective || {}; shift; my @sets = map { lc $_ } split /[,\s]+/, shift; @{$c}{@sets} = map { 1 } @sets; return $c; }, ''],
DeliverImage — allow delivery of images through Interchange
The directive specifies whether images can be fetched directly over the link program.
If the requested file is present and the MimeType for the file's
extension begins with image/
, the path will be adjusted
to add ImageDir
or ImageDirSecure
, and a
status 302
("Moved temporarily") issued. At that point, the image should
be visible on users' screens.
This whole thing happens before database or session opens, and is quite fast.
$Vend::tmp_session
is set so no cookie is issued.
Example: Enabling DeliverImage
Put the following in catalog.cfg
:
DeliverImage Yes
Now to request an image, instead of the usual page (such as
index.html
), ask Interchange for say,
interchange.png
(given that the file is present in
ImageDir
or ImageDirSecure
, of course).
This feature was introduced to help cope with the unpleasant behavior of the Mozilla HTML editor.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
DescriptionField — specify name of the "description" field in the Interchange database
By default, Interchange expects the product description to be in the description field in the products database. This directive allows modification of the default name.
The field is accessed implicitly when you call say,
[item-description]
in ITL.
Example: Setting DecriptionField depending on current locale
# Establish the default at startup DecriptionField description # Establish locale-specific description field Locale fr_FR DecriptionField desc_fr
To fully understand the example and implicitly presented Interchange features, make sure you're familiar with internationalization and locale glossary entries.
It's useful to set this directive based on locale, allowing for locale-specific product descriptions.
DirConfig — batch-set a bunch of variables (or values in general) from files
The directive allows you to batch-set a bunch of variables from files.
is usually
directive_name
Variable
, but can practically be any hash-based directive.
is a filespec
that can encompass multiple directories (files are ignored).
directory_glob
The specified directories are read for file names that
contain only word characters, i.e. something that would be a valid
Variable
. (This alone might make
it unsuitable for some other uses, but picking up the junk from the
in-directory-backup-file people would be intolerable.)
Then the contents of the found files are used to set the variables (or other
values) named after file names.
The source file name is kept in
$Vend::Cfg->{DirConfig}{Variable}{
if <pragma>dynamic_variables</pragma> pragma is set.
<pragma>dynamic_variables</pragma> enables dynamic
updating of variables from files.
<pragma>dynamic_variables_files_only</pragma> restricts dynamic variables to
files only — otherwise variables are dynamically read from the
VARNAME
}VariableDatabase
definition as well.
With dynamic variables, all
@_
and
VARIABLE
_@__
calls are checked
first to see if their source file is defined. If they are — if there is
a hash key present for the source file — even if its contents are blank,
it is returned as the value.
VARIABLE
__
Example: Setting DirConfig
DirConfig Variable templates/foundation/regions
If the file NOLEFT_TOP
is present at catalog config time
at the specified location, code __NOLEFT_TOP__
encountered on
a page will mimic
[include templates/foundation/regions/NOLEFT_TOP]
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4735 (context shows lines 4735-4767)
sub parse_dirconfig { my ($var, $value) = @_; return '' if ! $value; $value =~ s/(\w+)\s+//; my $direc = $1; #::logDebug("direc=$direc value=$value"); my $ref = $C->{$direc}; unless(ref($ref) eq 'HASH') { config_error("DirConfig called for non-hash configuration directive."); } my $source = $C->{$var} || {}; my $sref = $source->{$direc} || {}; my @dirs = grep -d $_, glob($value); foreach my $dir (@dirs) { opendir(DIRCONFIG, $dir) or next; my @files = grep /^\w+$/, readdir(DIRCONFIG); for(@files) { next unless -f "$dir/$_"; #::logDebug("reading key=$_ from $dir/$_"); $ref->{$_} = readfile("$dir/$_", $Global::NoAbsolute, 0); $ref->{$_} = substitute_variable($ref->{$_}) if $C->{ParseVariables}; $sref->{$_} = "$dir/$_"; } } $source->{$direc} = $sref; return $source; }
DirectiveDatabase — specify database to read configuration directives from
The DirectiveDatabase
configuration directive makes it possible to
read all configuration directives from a database, instead of
from the usual catalog.cfg
configuration file.
The database can (but does not have to) be previously defined with
the Database
directive. When it is, then just the table name
is required and honored. When it is not, then the Database
directive
will be automatically invoked first to register the new table, possibly with
custom text source file and table type.
table_source_filename
defaults to
, and
table_name
.txttable_source_type
defaults to TAB
.
(The arguments are the same as for the Database
directive itself,
they are passed to it directly.)
Example: Defining DirectiveDatabase, two-step
Database catalog catalog.txt TAB DirectiveDatabase catalog
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4769 (context shows lines 4769-4815)
sub parse_dbconfig { my ($var, $value) = @_; my ($file, $type); return '' if ! $value; local($Vend::Cfg) = $C; my ($db, $table); eval { ($db, $table) = get_configdb($var, $value); }; return '' if ! $db; my ($k, @f); # key and fields my @l; # refs to locale repository my @n; # names of locales my @h; # names of locales @n = $db->columns(); shift @n; my $extra; for(@n) { my $real = $CDname{lc $_}; if (! ref $Vend::Cfg->{$real} or $Vend::Cfg->{$real} !~ /HASH/) { # ignore non-existent directive, but put in hash my $ref = {}; push @l, $ref; push @h, [$real, $ref]; next; } push @l, $Vend::Cfg->{$real}; } my $i; while( ($k, undef, @f ) = $db->each_record) { #::logDebug("Got key=$k f=@f"); for ($i = 0; $i < @f; $i++) { next unless length($f[$i]); $l[$i]->{$k} = $f[$i]; } } for(@h) { $Vend::Cfg->{Hash}{$_->[0]} = $_->[1]; } $db->close_table(); return $table; }
DirectoryIndex — specify the default page in a directory
Specify the default page to show in a directory.
When the location requested does not exist, and this directive is set, Interchange will try to append the specified filename to the URL, and re-test for the page existence.
This directive sets the default page for all directories
except the catalog entry point.
(In other words, this directive won't help you make
http://myhost.mydomain.local/
show
http://myhost.mydomain.local/index.html
-
see the SpecialPage
for that).
Although the name for this directive was borrowed from the Apache Web Server project, it only accepts one filename (unlike Apache which supports multiple filenames to look for in sequential order).
DiscountSpaceVar — specify names of CGI variables to check for discount space definition
DiscountSpaceVar
is a configuration directive with the
default value of 'mv_discount_space
'. It is a list of
names of CGI variables to check per page process, such that a CGI
variable can be used to specify the discount space.
For this directive to have any effect, the DiscountSpacesOn
directive
must be enabled.
The default value, mv_discount_space
,
is likely to suffice for most purposes, but people could want to tie the
discount space
to other things, such as the cart name, by including other variable
names in
this array (for instance, mv_cartname
would tie the
discount space to the cart name, which could be convenient in some situations).
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3780 (context shows lines 3780-3800)
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; }
DiscountSpacesOn — enable "discount spaces" feature
This directive enables the "discount spaces" feature.
When DiscountSpacesOn
is enabled, then on a per-page
before-autoload basis, this routine initializes the
current discount space to 'main
', and then checks
all CGI variables defined with the DiscountSpaceVar
configuration directive to see if an alternate discount space has
been specified.
When DiscountSpacesOn
is not enabled, then the behavior is
compatible to how it was before the feature was added to Interchange —
all "discount space" functions become a no-operation; any attempts
to specify an alternate discount space will have no effect, and will
result in an error message in the catalog's error log.
See glossary entry discount for a complete discussion.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
DisplayErrors — display eventual errors directly in the client session
All Interchange errors are reported in the error log, but errors can also be
displayed directly in the client browser. This is convenient while testing
a configuration. To allow catalog-specific settings of DisplayErrors
the global directive needs to be enabled.
This directive changes the operation of $SIG{__DIE__}
and
may have other effects on program operation.
This should never be used for normal
operation.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
DomainTail — honor only the toplevel domain in IP qualification
The directive simply specifies that only the toplevel domain
should be used in IP qualification for session IDs.
If, for example, an IP was ri01-053.dialin.iskon.hr
,
only iskon.hr
would be used.
Interchange also supports taking various ccTLDs into account;
see CountrySubdomains
.
This directive is a compromise on security, but it allows browsers that do not accept cookies to use multiple proxy servers in the same domain. Note that this directive is enabled by default.
If you are encrypting credit cards with PGP/GPG or using payment services,
then look at the WideOpen
directive, which
enables even more browser compatibility, again at the cost of some
security.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
DowncaseVarname
DumpAllCfg — dump global Interchange server configuration
Instruct Interchange to dump the complete server configuration (with "includes"
expanded) to allconfigs.cfg
in the Interchange run
directory.
The dump file does not contain catalog configurations.
Interchange "run directory" is /usr/local/interchange/etc/
on
tarball installs, and /var/run/interchange
on
LSB setups.
DumpAllCfg
was previously known as "OutputAllCfg
", but
was renamed to ideologically match DumpStructure
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
DumpStructure — dump Interchange server and catalog structure for each catalog
Instruct Interchange to dump the structure of catalogs and the Interchange server to files named
. Use this to see how directives have been set.
catalog_name
.structure
The catalog structure files are dumped relative to catalog roots (CATROOTs).
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
EnableJSONPost
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
EncryptKey — specify default key to use for encryption
Specify default key to use for encryption.
GnuPG accepts both a key identifier or a part of user identifier.
EncryptProgram — specify default encryption program
Specify default encryption program, and a template to call it. The encryption program will be called to perform tasks such as encrypting credit card numbers (if they are stored on the server).
Two placeholders can be used, %p
and
%f
. At encryption time,
%p
expands to a password, and
%f
to a temporary file name.
If Interchange can found a variant of gpg/pgp
on your system, it is the default. Setting of none
disables
encryption.
Specifying command line options for the encryption program isn't required, as Interchange automatically adds the following options, depending on the program recognized:
gpg --batch --always-trust -e -a -r
KEY
pgpe -fat -r
KEY
pgp -fat -
KEY
Example: Specifying EncryptProgram with full path and arguments
EncryptProgram /usr/local/bin/gpg --batch --always-trust -e -a -r orders@mydomain.local
Example: Specifying EncryptProgram with full path and arguments
EncryptProgram /usr/bin/pgpe -fat -r orders@mydomain.local
This directive is different from PGP
, which is used to encrypt
complete orders and not just part of their contents.
If the order Route
method of sending orders is used (default in the
standard demo), then this directive sets the default value of
the encrypt_program
attribute.
Since Interchange 4.7.7, specifying program filename only is enough — no arguments are needed, although they will still work as expected.
If the encrypt program is in your path, avoid using full pathname to ease the eventual switch to a platform with different binary file locations.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4057 (context shows lines 4057-4113)
sub parse_executable { my($var, $initial) = @_; my($x); my(@tries); if(ref $initial) { @tries = @$initial; } else { @tries = $initial; } TRYEXE: foreach my $value (@tries) { #::logDebug("trying $value for $var"); my $root = $value; $root =~ s/\s.*//; return $value if $Global::Windows; if( ! defined $value or $value eq '') { $x = ''; } elsif( $value eq 'none') { $x = 'none'; last; } elsif( $value =~ /^\w+::[:\w]+\w$/) { ## Perl module like Net::SMTP eval { eval "require $value"; die if $@; $x = $value; }; last if $x; } elsif ($root =~ m#^/# and -x $root) { $x = $value; last; } else { my @path = split /:/, $ENV{PATH}; for (@path) { next unless -x "$_/$root"; $x = $value; last TRYEXE; } } } config_error( errmsg( "Can't find executable (%s) for the %s directive\n", join('|', @tries), $var, ) ) unless defined $x; #::logDebug("$var=$x"); return $x; }
Environment — specify environment variables to inherit from the calling CGI link program
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3780 (context shows lines 3780-3800)
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; }
ErrorDestination — route error messages to different files, based on message content or arbitrary tag
The directive allows routing error messages to different files, based on either message content or an arbitrary tag.
This allows us to add message "routing" information at a single place in the catalog configuration, instead of having to provide file attribute to each invocation of error-related tags of functions.
Example: Routing error messages based on error message
ErrorDestination "Attempt to order missing product code: %s" logs/missing_products.log ErrorDestination "search error: %s" logs/search_errors.log
Example: Routing error messages based on an arbitrary tag
ErrorDestination missing_code logs/missing_product.log
Example: Logging in Perl and specifying a custom tag
::logError( 'Bad search column ' . $_, { tag => 'search' } );
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
ErrorFile — specify error log filename
Specify the error log file location.
The Interchange daemon must have the permission to create and write to the specified file.
When using the directive on a catalog level, specifying absolute
filenames might not be allowed due to NoAbsolute
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3925 (context shows lines 3925-3932)
sub parse_root_dir { my($var, $value) = @_; return '' unless $value; $value = "$Global::VendRoot/$value" unless file_name_is_absolute($value); $value =~ s./+$..; return $value; }
Source: lib/Vend/Config.pm
Line 3975 (context shows lines 3975-3989)
sub parse_relative_dir { my($var, $value) = @_; if (absolute_or_relative($value)) { config_error('Path %s not allowed in %s directive', $value, $var); } $C->{Source}{$var} = $value; $value = "$C->{VendRoot}/$value" unless file_name_is_absolute($value); $value =~ s./+$..; $value; }
ExecutionLocale — specify lowest-level locale
The directive specifies the "lowest-level" locale; the one that will be re-set on every page so that the daemon cannot even accidentally be left with a bad locale.
ExecutionLocale
defaults to "C
" and you'll probably
never want to change it. There is the need to change
locale while Interchange is
running, of course, but this is done only for critical code sections and not
for the majority of other, "locale-independent" code.
To see the list of code "groups" that require a locale adjustment, run
locale and man locale on your Unix
system.
External — enable dump of selected global and catalog values for use by external programs
The directive enables dump of selected global and catalog information for use by external programs, possibly written in languages such as PHP, Python or Ruby.
Dump file format is a direct Perl memory dump, internally most often
produced by invoking Perl's Storable
methods.
The dump takes place at time of catalog (re)configuration.
Global External
must be enabled first to allow individual catalogs
to use External
themselves and dump their information.
Example: Defining External
Put the following in both global interchange.cfg
and the specific
catalog.cfg
s:
External yes
Example: PHP connector for accessing the structure file
<?php $interchange_base = '/usr/lib/interchange'; $interchange_lib = "$interchange_base/lib"; $interchange_struct = "/var/run/interchange/external.structure"; putenv("PERL_SIGNALS=unsafe"); umask(7); $perl = new Perl(); $perlstring = " use lib '$interchange_lib'; \$ENV{EXT_INTERCHANGE_FILE} = '$interchange_struct'; \$ENV{EXT_INTERCHANGE_DIR} = '$interchange_base'; "; $perl->eval($perlstring); $perl->require("Vend/External.pm"); $origsid = $sid = $_COOKIE["MV_SESSION_ID"]; if(! $sid) { $_REQUEST["mv_session_id"]; } $cat = 'standard'; $catback = $perl->catalog($cat); $out = "sid=$sid<br>"; $out .= "parm is debug=" . $_REQUEST["debug"] . "<br>"; $out .= "catalog is $catback<br>"; $out .= "now sid=$sid<br>"; $remote = $_SERVER['REMOTE_ADDR']; $perl->remote_addr($remote); $new = $perl->session($sid); if($new) { $sid = $perl->session_name(); $out .= "new session, now sid=$sid<br>"; } if($sid != $origsid) { setcookie('MV_SESSION_ID', $sid, 0 , '/'); } ## Can print now that cookie is set print $out; $fname = $perl->value("values","fname"); $lname = $perl->value("values","lname"); print "Well what do you know, we have a '$fname $lname'!<br>"; $cart = $perl->value('carts', 'main'); $nitems = count($cart); if($nitems) { print "We have a cart with $nitems items</br>"; for($i = 0; $i < $nitems; $i++) { $code = $cart[$i]["code"]; $quantity = $cart[$i]["quantity"]; print "Item $code is in cart, quantity $quantity.<br>"; } } ?>
For discussion and examples of connecting Interchange to external programs, see glossary entry external.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
ExternalExport — specify Perl variables to dump to external file
The directive specifies Perl variables to dump to ExternalFile
.
On global level, using the equal sign ("=
") it is possible
to specify original Perl structure and the resulting "translated" name in the
output file. Global elements appear directly under each catalog hash in the
output file.
On catalog level, it is not possible to "translate" names, but you can use
the notation "->
" to dump specific elements from array
or hash structures. Catalog elements appear under hash key
"external_config
" under each catalog hash in the
output file.
See the section called “EXAMPLES” for clarification.
Example: Defining ExternalExport
Here's a complete example and the expected result:
In interchange.cfg
:
External yes ExternalExport Global::Catalog=number_of_catalogs ExternalFile /tmp/external
In catalog.cfg
:
External yes ExternalExport <<EOD CatalogName ScratchDefault ValuesDefault ScratchDir SessionDB Sess sionDatabase SessionExpire VendRoot VendURL SecureURL Variable->SQLDSN Variable->SQLPASS Variable->SQLUSER EOD
After restarting Interchange, file /tmp/external
will
be created with the following contents (shown here in human-readable
format):
{ 'number_of_catalogs' => 4, 'Catalogs' => { 'catalog1' => { 'external_config' => { 'VendRoot' => '/home/interchange/catalog1', 'ValuesDefault' => {}, 'CatalogName' => 'catalog1', 'SessionExpire' => 3600, 'ScratchDefault' => { 'mv_no_session_id' => '1', 'mv_no_count' => '1', 'mv_add_dot_html' => '1' }, 'SessionDB' => '', 'ScratchDir' => '/home/interchange/catalog1/tmp', 'VendURL' => 'http://myhost.mydomain.local/cgi-bin/catalog1', 'SessionDatabase' => '/home/interchange/catalog1/session', 'SecureURL' => 'http://myhost.mydomain.local/cgi-bin/catalog1', 'Variable' => { 'SQLUSER' => 'interch', 'SQLDSN' => 'dbi:Pg:dbname=catalog1', 'SQLPASS' => 'interch' } } } } }
For discussion and examples of connecting Interchange to external programs, see glossary entry external.
ExternalFile — specify external dump filename
Specify "external" output filename. Default is
external.structure
in global RunDir
.
For the directive to have any effect, External
must be enabled.
For discussion and examples of connecting Interchange to external programs, see glossary entry external.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 523
['ExternalFile', 'root_dir', "$Global::RunDir/external.structure"],
Source: lib/Vend/Config.pm
Line 3925 (context shows lines 3925-3932)
sub parse_root_dir { my($var, $value) = @_; return '' unless $value; $value = "$Global::VendRoot/$value" unless file_name_is_absolute($value); $value =~ s./+$..; return $value; }
ExtraSecure — disallow unencrypted access to pages which are listed under AlwaysSecure
Disallow access to pages which are listed under AlwaysSecure
unless
the browser is in HTTPS mode.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
FallbackIP —
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
Feature — specify Interchange "feature" for activation in the catalog
Specify Interchange "feature" for inclusion in the current catalog.
For an introduction to Interchange "features", please see the feature glossary entry.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2274 (context shows lines 2274-2392)
sub parse_feature { my ($var, $value) = @_; my $c = $C->{$var} || {}; return $c unless $value; $value =~ s/^\s+//; $value =~ s/\s+$//; my $fdir = Vend::File::catfile($Global::FeatureDir, $value); unless(-d $fdir) { config_warn("Feature '%s' not found, skipping.", $value); return $c; } # Get the global install files and remove them from the config list my @gfiles = glob("$fdir/*.global"); my %seen; @seen{@gfiles} = @gfiles; # Get the init files and remove them from the config list my @ifiles = glob("$fdir/*.init"); @seen{@ifiles} = @ifiles; # Get the uninstall files and remove them from the config list my @ufiles = glob("$fdir/*.uninstall"); @seen{@ufiles} = @ifiles; # Any other files are config files my @cfiles = grep ! $seen{$_}++, glob("$fdir/*"); # directories are for copying my @cdirs = grep -d $_, @cfiles; # strip the directories from the config list, leaving catalog.cfg stuff @cfiles = grep -f $_, @cfiles; # Don't install global more than once @gfiles = grep ! $Global::FeatureSeen{$_}++, @gfiles; # Place the catalog configuration in the config list unshift @include, @cfiles; my @copy; my $wanted = sub { return unless -f $_; my $n = $File::Find::name; $n =~ s{^$fdir/}{}; my $d = $File::Find::dir; $d =~ s{^$fdir/}{}; push @copy, [$n, $d]; }; if(@cdirs) { File::Find::find({ wanted => $wanted, follow => 1 }, @cdirs); } #::logDebug("gfiles=" . ::uneval(\@gfiles)); #::logDebug("cfiles=" . ::uneval(\@cfiles)); #::logDebug("ifiles=" . ::uneval(\@ifiles)); #::logDebug("ufiles=" . ::uneval(\@ufiles)); #::logDebug("cdirs=" . ::uneval(\@cdirs)); #::logDebug("copy=" . ::uneval(\@copy)); for(@copy) { my ($n, $d) = @$_; my $tf = Vend::File::catfile($C->{VendRoot}, $n); next if -f $tf; my $td = Vend::File::catfile($C->{VendRoot}, $d); unless(-d $td) { File::Path::mkpath($td) or do { config_warn("Feature %s not able to make directory %s", $value, $td); next; }; } File::Copy::copy("$fdir/$n", $tf) or do { config_warn("Feature %s not able to copy %s to %s", $value, "$fdir/$n", $tf); next; }; } for(@gfiles) { global_chunk($_); } if(@ifiles) { my $initdir = Vend::File::catfile($C->{ConfDir}, 'init', $value); File::Path::mkpath($initdir) unless -d $initdir; my $unfile = Vend::File::catfile($initdir, 'uninstall'); ## Feature was previously uninstalled, we *do* need to run init my $ignore = -f $unfile; if($ignore) { unlink $unfile or die errmsg("Couldn't unlink $unfile: $!"); } for(@ifiles) { my $fn = $_; $fn =~ s{^$fdir/}{}; if($ignore) { unlink "$initdir/$fn" or die errmsg("Couldn't unlink $fn: $!"); } next if -f "$initdir/$fn"; $C->{Init} ||= []; push @{$C->{Init}}, [$_, "$initdir/$fn"]; } } #::logDebug("Init=" . ::uneval($C->{Init})); $c->{$value} = 1; return $c; }
FeatureDir — specify "feature" directory
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3925 (context shows lines 3925-3932)
sub parse_root_dir { my($var, $value) = @_; return '' unless $value; $value = "$Global::VendRoot/$value" unless file_name_is_absolute($value); $value =~ s./+$..; return $value; }
FileControl — specify page names and Perl subroutines that implement access control
The FileControl
directive allows you to control access
to Interchange pages by using an arbitrary decision method, implemented
as a Perl function. Perl functions may be provided in-place,
as Sub
s, or as GlobalSub
s.
The function is called with three parameters: the filename, write flag, and Perl caller information. The return value should be a boolean, specifying whether access is allowed (a true value) or not (a false value).
Example: Specifying FileControl routine in-place
FileControl test_page <<EOR sub { my ($fn, $write, @caller) = @_; # Allow write to files containing "foo" in filename if( $write ) { return $fn =~ /foo/; } # Allow read for files NOT containing "bar" in filename return $fn !~ /bar/; } EOR
Example: Specifying FileControl routine as a Sub or GlobalSub
Sub <<EOF sub filecontrol_access { my ($fn, $write, @caller) = @_; # Allow write to files containing "foo" in filename if( $write ) { return $fn =~ /foo/; } # Allow read for files NOT containing "bar" in filename return $fn !~ /bar/; } EOF FileControl test_directory/test_page filecontrol_access
Example: Specifying FileControl as a mapped routine name
In interchange.cfg
, you can use mapped routine names:
FileControl test_page Vend::YourModule::file_control
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2161 (context shows lines 2161-2258)
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; $name =~ s/-/_/g; ## Determine if we are in a catalog config, and if ## perl should be global and/or strict my $nostrict; my $perlglobal = 1; if($C) { $nostrict = $Global::PerlNoStrict->{$C->{CatalogName}}; $perlglobal = $Global::AllowGlobal->{$C->{CatalogName}}; } # Untaint and strip this pup $sub =~ s/^\s*((?s:.)*\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 ($perlglobal) { package Vend::Interpolate; if($nostrict) { no strict; $c->{$name} = eval $sub; } else { $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; }
FileDatabase — specify table and column to look up in search for file contents
Besides retrieving file contents from files on the filesystem (as usual), Interchange has the ability to retrieve file contents from the database.
The standard FileDatabase
setting includes the appropriate
table and column names.
In case the column is unspecified, it defaults
to the current value of global variable LANG
. In case
the column named after LANG
value does not exist, Interchange
finally tries with the column default.
Filter — specify variables and filters through which they should be run through automatically
The directive specifies one or more filters that should automatically be applied to CGI variables.
That way, by the time you get to call cgi
, the
variable value is already filtered and ready for use.
Example: Automatically filtering "mail_lists" variable
Some variables submitted by the user come back null-separated, such as
values from multi-select boxes where the selected items are separated
by null (\0
) characters. To automatically change those
nulls to spaces, you could use this directive:
Filter mail_lists null_to_space
You could also use the filter
tag, but in the long
run the Filter
approach reduces typing and minimizes the chance
of omission.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
FormAction — define or override form action
The directive allows definition of form actions. Some pre-defined
actions that you might already be familiar with are
return
,
submit
or
refresh
.
Example: Checkout Action
This action can be used on the shopping cart page to update the cart and go to the checkout page with an image button.
FormAction checkout <<EOR sub { $Tag->update('quantity'); $CGI->{mv_nextpage} = 'checkout'; return 1; } EOR
Catalog version of the directive is protected by Safe
.
For a complete discussion, please see the form action glossary entry.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2161 (context shows lines 2161-2258)
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; $name =~ s/-/_/g; ## Determine if we are in a catalog config, and if ## perl should be global and/or strict my $nostrict; my $perlglobal = 1; if($C) { $nostrict = $Global::PerlNoStrict->{$C->{CatalogName}}; $perlglobal = $Global::AllowGlobal->{$C->{CatalogName}}; } # Untaint and strip this pup $sub =~ s/^\s*((?s:.)*\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 ($perlglobal) { package Vend::Interpolate; if($nostrict) { no strict; $c->{$name} = eval $sub; } else { $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; }
FormIgnore — specify variables that should not be propagated from CGI to Values space
The directive specifies variables that should not be propagated from the
CGI into values space, when a call such as
[update values]
is made.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3013 (context shows lines 3013-3030)
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; }
FractionalItems — allow fractional quantities in the shopping cart
The directive specifies whether
the quantity of items in the shopping cart could be fractional,
such as 2.5
or 1.25
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
FullUrl — use full URLs (those including hostnames) in catalog definition lines
When a page request comes to Interchange, the catalog to invoke is
determined from CGI value SCRIPT_NAME
.
For example,
if a request for www.example.com/cat1
comes in,
SCRIPT_NAME
will be "/cat1
".
If a request for www.example.com
comes in,
SCRIPT_NAME
will be "/
".
By default, hostnames are not honored, so different catalogs cannot use the
same SCRIPT_NAME
under the same Interchange server. This prevents
multiple domains from serving their Interchange pages directly from www.HOSTNAME.com
(as there can only be one "/
" script name).
With FullUrl
enabled, catalog selection includes the hostname
and it becomes possible to uniquely determine catalog name based on both
hostname and script name.
See the Catalog
directive for further discussion and concrete
examples.
Example: Catalog definition example with FullUrl enabled
An example from interchange.cfg
:
FullUrl yes Catalog standard /path/to/catalogs/standard/ myhost.mydomain.local/cgi-bin/standard
If FullUrl
is defined, you must modify all
Catalog
lines in your interchange.cfg
to include the hostname —
FullUrl
and non-FullUrl
Catalog
specifications
are not compatible.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
FullUrlIgnorePort
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
Glimpse — specify program path and options for the Glimpse search engine
The directive specifies pathname for the glimpse command, used if glimpse
searches are to be enabled.
To use glimpseserver, the
-C
, -J
and -K
options must be
specified.
Glimpse was once-popular search engine in the Linux world, but its non-free status and other things called for its replacement. We suggest you use Swish-e which is supported by Interchange as well.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4057 (context shows lines 4057-4113)
sub parse_executable { my($var, $initial) = @_; my($x); my(@tries); if(ref $initial) { @tries = @$initial; } else { @tries = $initial; } TRYEXE: foreach my $value (@tries) { #::logDebug("trying $value for $var"); my $root = $value; $root =~ s/\s.*//; return $value if $Global::Windows; if( ! defined $value or $value eq '') { $x = ''; } elsif( $value eq 'none') { $x = 'none'; last; } elsif( $value =~ /^\w+::[:\w]+\w$/) { ## Perl module like Net::SMTP eval { eval "require $value"; die if $@; $x = $value; }; last if $x; } elsif ($root =~ m#^/# and -x $root) { $x = $value; last; } else { my @path = split /:/, $ENV{PATH}; for (@path) { next unless -x "$_/$root"; $x = $value; last TRYEXE; } } } config_error( errmsg( "Can't find executable (%s) for the %s directive\n", join('|', @tries), $var, ) ) unless defined $x; #::logDebug("$var=$x"); return $x; }
GlobalSub — define global Perl functions for use within Interchange
Define a global subroutine for use within perl
, mvasp
, or
embedded Perl languages.
The use of "here document" syntax in Interchange makes subroutine definitions visually convenient.
Example: Defining a global subroutine
GlobalSub <<EOF sub count_orders { my $counter = new File::CounterFile "tmp/count_orders", '1'; my $number = $counter->inc(); return "There have been $number orders placed.\n"; } EOF
The above code would be called from an Interchange page in the following way:
[perl tables=products subs='count_orders'] return count_orders(); [/perl]
As with Perl "here documents," the "EOF
" (or arbitrarily
named end marker) must be the only thing on the line,
without leading or trailing white space. Also, do not append a semicolon to the
opening marker (as you would in Perl).
Global subroutines are not subject to Safe
security
checks. They can do most anything!
Therefore, scratch or catalog subroutines (Sub
s) are
preferred in most cases to protect the innocent.
HTMLsuffix — specify filename extension for files in the PageDir and TemplateDir directories
Specify extension (suffix) to use with filenames when looking for the
source files in the pages/
directory.
If a page with the configured suffix does not exist on the disk, Interchange will
unconditionally try the usual ".html
" variant.
Note that
this setting applies strictly to the disk file lookup —
page names in the users' browsers will always appear as
".html
".
The way Interchange looks for pages is locale-sensitive. Besides the default
HTML suffix which is set using this HTMLsuffix
directive, you can
set locale-dependent suffixes using Locale
.
HammerLock — number of seconds after which a locked session is considered lost due to malfunction
The directive specifies an interval after which a locked session could be considered lost due to malfunction. This will also clean up the session lock.
This directive is only present to monitor session hand-offs. If a message generated by this directive shows up in error logs, the system setup should be examined.
When file-based sessions are used, this directive mostly does not apply.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4115 (context shows lines 4115-4127)
sub parse_time { my($var, $value) = @_; my($n); return $value unless $value; # $C->{Source}->{$var} = [$value]; $n = time_to_seconds($value); config_error("Bad time format ('$value') in the $var directive\n") unless defined $n; $n; }
History — how many most-recent user clicks should be saved in session history
The directive specifies how many of the most recent user clicks should be stored in the session history.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
HitCount — increment a counter on every catalog access
Specify whether the catalog counter file should be increased on every access to the catalog.
The counter filename will be hits.
, placed in the catalog_name
ICROOT/etc/
directory.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
HostnameLookups — perform hostname lookups (DNS resolving)
The directive specifies whether to perform DNS lookups to resolve
remote users' hostname from their IP address. Hostnames are required
for some facilities, such as RobotHost
(use RobotIP
if you
want to keep DNS lookups off).
If the web server is configured to perform hostname lookups itself, then this directive should remain disabled.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
HotDBI — specify catalogs that should use persistent database connections
Specify catalogs that should use persistent database connections. When a connection is persistent, it will be maintained and cached without reconnecting for every page request.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3013 (context shows lines 3013-3030)
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; }
HouseKeeping — specify number of seconds between periodic "house keeping" jobs
Specify periodic time interval at which the Interchange server should
wake up and
look for user reconfiguration requests and hung processes. On some
systems, this wakeup is the only time the server will terminate in response
to a -stop
command.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4115 (context shows lines 4115-4127)
sub parse_time { my($var, $value) = @_; my($n); return $value unless $value; # $C->{Source}->{$var} = [$value]; $n = time_to_seconds($value); config_error("Bad time format ('$value') in the $var directive\n") unless defined $n; $n; }
HouseKeepingCron — define Interchange-aware crontab entries
HouseKeepingCron
is an Interchange-equivalent of the usual Unix "cron"
(periodic execution) facility.
Time specifications (first six fields) behave exactly like
with the traditional Vixie cron.
That includes numbers, ranges and '*
';
see crontab(5) manual page.
Additional features are provided by the Set::Crontab
Perl module:
The '<
' and
'N
>
' select
elements smaller and larger than N
N
.
!
excludes
N
N
from the set. "!3
"
with a range of "1-10
" corresponds to
"1-2,4-10
", and ">3,!7
"
in the same range means "4-6,8-10
".
Target specification, provided in form of everything after the 6th field,
consists of the catalog name and action. Catalog name can be prefixed
with >
, <
and
=
.
Name prepended with '>
' will make the
commands run after the
reconfig/restart/jobs/pid management cycle (usually they run before).
Interchange-specific things you can run include
everything you can put into execution over
Vend::Dispatch::run_macro
function.
That means GlobalSub
s, Sub
s and anything
else that is suitable for interpolation (all ITL code).
Bear in mind, though, that there is no catalog context; everything is executing on the global level.
In addition to the above, two special targets exist,
:reconfig
and :jobs
.
They define the intervals for processing
catalog reconfiguration and batch job requests.
The reconfig
and
jobsqueue
files in RunDir
are ignored
if HouseKeepingCron
is specified and these targets not included.
In that case, a warning will be issued because, without the two
entries, catalog reconfiguration or job execution requests are
ignored — something you almost never want in regular operation.
Example: Running :restart and :jobs every 5 minutes
The basic entry to implement HouseKeeping 300
would be:
HouseKeeping 1 minute HouseKeepingCron <<EOC */5 * * * * * :restart */5 * * * * * :jobs EOC
Example: Running batch jobs
HouseKeepingCron <<EOC 0 0 * * * * =standard hourly 0 1 2 * * * =standard daily 0 2 4 * * 7 =standard weekly 0 0 3 1 * * =standard monthly EOC
Example: Warning message when :reconfig entry is not present
The warning message would look like this:
WARNING: suggested cron entry ':reconfig' not present.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4129 (context shows lines 4129-4144)
sub parse_cron { my($var, $value) = @_; return '' unless $value =~ /\s/ and $value =~ /[a-zA-Z]/; unless($Vend::Cron::Loaded) { config_warn( "Cannot use %s unless %s module loaded%s", 'crontab', 'Vend::Cron', ' (missing Set::Crontab?)', ); return ''; } return Vend::Cron::read_cron($value); }
IPCsocket — specify IPC socket filename
The directive specifies the filename IC; should create to enable IPC socket communication. The filename must be writable by the Interchange daemon.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3925 (context shows lines 3925-3932)
sub parse_root_dir { my($var, $value) = @_; return '' unless $value; $value = "$Global::VendRoot/$value" unless file_name_is_absolute($value); $value =~ s./+$..; return $value; }
ImageAlias — specify alias location for all image files
The directive specifies an alias for the base images location, which is
set by ImageDir
and related directives.
It is similar in effect to the "alias" feature of Web servers such as
Apache or NCSA, and applies to <body background=
,
table elements background=
and all
src=
specifications.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
ImageDir — specify base location for all image files
ImageDir
is one of quite basic settings in every catalog.cfg
.
The directive specifies a base location, accessible over the web, where Interchange should look for image files, when just relative image filename is given. Automatically "translated" are image locations mentioned in <img src="">, <input src="">, <body background="">, <table background=""> and table subelements (<th>, <tr> and <td>).
A setting of ImageDir
/images/
and a specification
of <img src="test/test.png">
would be
translated to <img src="/images/test/test.png">
.
ImageDirInternal — (obsolete)
The directive actually specifies value of ImageDir
directive, for cases
when Interchange's internal HTTP server is in use.
It must have a trailing /
to work, and should always begin
with a fully-qualified path (http://
).
ImageDirSecure — specify base location for all IMG and INPUT src= files served over HTTPS
The directive specifies a base location, accessible over the web,
where Interchange should look for IMG and INPUT HTML
src=
file specifications,
when the originating page is being served
over a secure connection (HTTPS).
This setting applies to image locations mentioned in <img src="">, <input src="">, <body background="">, <table background=""> and table subelements (<th>, <tr> and <td>).
This is useful if you are using separate HTTPS and HTTP servers, and cannot
make the image directory paths match. If ImageDirSecure
is
unspecified, it defaults to ImageDir
.
Inet_Mode — specify whether Interchange server should open an INET socket and listen on a port
Specify whether the Interchange server should open an INET-domain socket and
listen on some port (7786
by default). The port can be
changed with the TcpMap
directive.
This configuration directive can be overridden using
interchange -i
switch on the command line.
In general, you will need Interchange INET mode when the Web and Interchange server are not the same machine.
The default port number, 7786
, was chosen since it
represents the ASCII numbers of letters M
and
V
. (Interchange was once called MiniVend).
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 418 (context shows lines 408-413)
['Inet_Mode', 'yesno', ( defined $Global::Inet_Mode || defined $Global::Unix_Mode ) ? ($Global::Inet_Mode || 0) : 'No'],
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
InternalCookie
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 663
['InternalCookie', 'yesno', 'No'], ## Allows CookieName \ to be change yet still handle IP address in cookie
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
IpHead — use only part of the IP to qualify user sessions
The directive affects the domain/IP session qualifying method. When enabled,
only the first IpQuad
dot-quads of the IP address are used to qualify
the user session (along with, of course, the session ID).
This is a slight compromise on security, but it allows non-cookie-accepting browsers, like AOL's V2.0, to use multiple proxy servers.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
IpQuad — specify number of dot-quads to honor when IpHead is enabled
The directive simply specifies the number of dot-quads
the session qualifier will look at, if IpHead
is enabled.
In other words, with an IPv4 address (32 bit address, consisting of
four dot-quads) of value
127.0.0.1
and IpQuad
of
3
,
127.0.0.
would be enough to qualify the user session.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
ItemAction — specify subroutine to invoke when users' electronic cart contents change
The directive specifies name of the Perl subroutine to be invoked when users' electronic cart contents change. The subroutine can be defined on both global and catalog level.
The subroutine executes whenever the contents of users' cart are changed via the standard means available through the CGI variable space.
The subroutine will be executed per-change, such that any page process resulting in multiple alterations to the cart will potentially call this function multiple times.
The specified function is invoked with the reference to the cart item in question. The function's return value is not used.
It must be noted that the Interchange cart subsystem is based on arrayrefs of hashrefs (all Perl programming terms) — there is no object encapsulation for limiting or monitoring program access to the contents of any cart. Consequently, direct manipulation of the cart from within Perl will not cause this function to be invoked. The triggers only fire when the cart contents are modified through the standard Interchange CGI-based variable processing. Therefore, it is assumed that any programmer sufficiently comfortable or confident to manipulate cart contents directly can also be given the responsibility of deciding whether or not it is appropriate to manually invoke this function.
This configuration directive is very similar to CartTrigger
and CartTriggerQuantity
, the two more recent and flexible options.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2161 (context shows lines 2161-2258)
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; $name =~ s/-/_/g; ## Determine if we are in a catalog config, and if ## perl should be global and/or strict my $nostrict; my $perlglobal = 1; if($C) { $nostrict = $Global::PerlNoStrict->{$C->{CatalogName}}; $perlglobal = $Global::AllowGlobal->{$C->{CatalogName}}; } # Untaint and strip this pup $sub =~ s/^\s*((?s:.)*\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 ($perlglobal) { package Vend::Interpolate; if($nostrict) { no strict; $c->{$name} = eval $sub; } else { $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; }
Jobs — define parameters for batch jobs
This directive configures Interchange batch jobs facility. For detailed discussion, please see the jobs glossary entry.
The directive accepts a list of key/value pair and can be specified at both global and catalog level.
The available keys for the global directive are:
Key | Default | Description |
---|---|---|
MaxLifetime | 600 | The maximum time in seconds that a job will be allowed to run |
MaxServers | 1 | The maximum number of servers processing jobs. Excess jobs will be queued |
UseGlobal | false | Always search for global job definitions? |
The available keys for the catalog directive are:
Key | Default | Description |
---|---|---|
add_session | false | Add session dump to job output? |
autoend | None | A macro to execute after each invidiual file in the job |
autoload | None | A macro to execute before each invidiual file in the job |
base_directory | etc/jobs | Directory to search for batch jobs. |
email | None | Email job output to this address |
extra_headers | None | Additional email headers |
from | MailOrderTo | "From" address in emails |
ignore_errors | false | Excludes fatal errors from job output |
filter | Filters applied to job output | |
initialize | None | A macro executed before the job commences |
log | None | Write job output to this logfile |
subject | Interchange results for job: %s | Subject for emails, including placeholder for job name |
suffix | None | Restrict job to files matching the specified suffix |
trackdb | None | Table for tracking jobs |
use_global | false | Search for global job definitions? |
For more information about Interchange batch jobs see jobs glossary entry.
Example: Define catalog-level Jobs directive
Jobs <<EOJ log logs/jobs.log base_directory jobs email root@myhost.mydomain.local EOJ
Example: Run jobs manually
Invoke from the command line:
su -c '/PATH/TO/interchange --quiet --runjobs=CATALOG_NAME=DIRECTORY_NAME' USERNAME
Example: Run jobs automatically from Unix crontab
12 2 * * * su -c '/PATH/TO/interchange --quiet --runjobs=CATALOG_NAME=DIRECTORY_NAME' USERNAME
Files in the jobs directory that end in HTMLsuffix
will be silently ignored.
The invocation of jobs from the command line will only queue them for execution and will return the shell prompt before the jobs have actually started executing.
In that case, a common temporary session (mv_tmp_session
== true)
will be created for use by all of the files
in the job queue. The session will be closed when the jobs complete.
The remote IP address will be set to none
and the
user agent string will be set to commandline
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
Levies — specify levy sections to apply
Example: Defining Levies
Levy salestax description "Sales Tax (%s)" Levy salestax keep_if_zero 1 Levy salestax type salestax Levy salestax sort 002 Levy shipping keep_if_zero 0 Levy shipping type shipping Levy shipping mode_variable mv_shipmode Levy shipping mode USPS Levies salestax shipping
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3780 (context shows lines 3780-3800)
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; }
Levy — define levy section (levy key)
add_to
-
check_status
-
description
-
exclude_if
-
include_if
-
free_message
-
keep_if_zero
-
label_value
-
mode
-
mode_from_scratch
-
mode_from_values
-
multi
-
part_number
-
sort
-
tax_fields
-
tax_type
-
type
-
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3071 (context shows lines 3071-3135)
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 Vend::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; }
Limit — set or modify various limits
Table 1.
Name | Default | Overview |
---|---|---|
cart_quantity_per_line | none | maximum quantity per item in cart |
chained_cost_levels | 32 | |
dbm_open_retries | 10 | number of retries opening DBM file |
file_lock_retries | 5 | number of retries on file locking |
ip_session_expire | 60 minutes | see RobotLimit |
no_ship_message | ||
list_text_overflow | ||
list_text_size | - | maximum length of text in lists |
lockout_reset_seconds | 30 | see RobotLimit |
logdata_error_length | - | |
option_list | 5000 | |
override_tag | ||
robot_expire | 1 day | see RobotLimit |
session_id_length | 8 | length of session identifier, see session |
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 558
['Limit', 'hash', 'option_list 5000 chained_cost_levels 32 robot_expire 1'],
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
Locale — specify locale definitions
The directive specifies the default locale definitions for a number of items:
currency_symbol
- default currency symbol. Can be a simple value like "$
" or " E
", or a more flexible setting such as '<img src="euro.png" />
'.
frac_digits
-
int_curr_symbol
-
int_currency_symbol
- currency symbol for plain text display
int_frac_digits
-
mon_decimal_point
-
mon_grouping
-
price_picture
-
mon_thousands_sep
-
n_cs_precedes
-
negative_sign
-
p_cs_precedes
- whether currency symbol precedes price or vice versa
p_sep_by_space
- number of spaces between currency symbol and price
positive_sign
-
Example: Defining Locale by individual keys
Put the following in interchange.cfg
:
Locale <localedata
The actual file localedata
could be composed
of the keys listed in the section called “DESCRIPTION”.
Example: Price displayed as 1.000,00 EUR
Locale de_DE currency_symbol EUR Locale de_DE p_cs_precedes 0 Locale de_DE mon_decimal_point , Locale de_DE mon_thousands_sep . [currency]1000[/currency]
If two locales are set "default" using Locale
, and no
DefaultLocale
is specified, the behavior is undefined as the first
"default" found will be set as the actual default.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3071 (context shows lines 3071-3135)
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 Vend::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; }
LocaleDatabase — specify database that contains locale settings
Example: LocaleDatabase table structure
code en_US en_GB fr_FR de_DE nl_NL color color colour couleur Farbe kleur
Settings from LocaleDatabase
add on to (and override)
any that are already defined in the catalog configuration files through
the use of Locale
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4683 (context shows lines 4683-4733)
sub parse_configdb { my ($var, $value) = @_; my ($file, $type); return '' if ! $value; local($Vend::Cfg) = $C; my ($db, $table); eval { ($db, $table) = get_configdb($var, $value); }; ::logGlobal("$var $value: $@") if $@; return '' if ! $db; my ($k, @f); # key and fields my @l; # refs to locale repository my @n; # names of locales my @h; # names of locales my $base_direc = $var; $base_direc =~ s/Database$//; my $repos_name = $base_direc . '_repository'; my $repos = $C->{$repos_name} ||= {}; @n = $db->columns(); shift @n; my $i; if($Columnar{$base_direc}) { my @l; for(@n) { $repos->{$_} ||= {}; push @l, $repos->{$_}; } my $i; while( ($k , undef, @f ) = $db->each_record) { for ($i = 0; $i < @f; $i++) { next unless length($f[$i]); $l[$i]->{$k} = $f[$i]; } } } else { while( ($k, undef, @f ) = $db->each_record) { for ($i = 0; $i < @f; $i++) { next unless length($f[$i]); $repos->{$k}{$n[$i]} = $f[$i]; } } } $db->close_table(); return $table; }
LockType — specify file locking method to use
The directive specifies the file locking method to use.
flock
is the default and works well with standard
setups.
fcntl
is used with NFS. In case of NFS, both
the NFS client and server need to run the lock daemon
(lockd).
none
can be used to turn off locking completely. This
is never recommended, unless you only want to see if the locking
is causing system hangs.
Although this directive was added in Interchange 4.7, due to an error later discovered, the directive started working properly with the release of Interchange 4.8.6.
If you are only accessing sessions on an NFS-mounted directory, but the rest
of Interchange is on the local filesystem, you can set the SessionType
directive to NFS
instead. That would enable
fcntl
locking for sessions on a per-catalog basis only.
LockoutCommand — specify command to run in order to lock a client out of the site
The directive specifies the command (as it would be entered from the shell) that will somehow prevent the remote IP from accessing the Interchange catalog, or the whole system.
The IP address will be substituted for the first occurrence of the string
%s
(which might remind you of printf
format specifiers). The command will be executed under the Interchange user ID,
so you'll have to fine-tune the system privileges, or use
sudo-like tools.
Example: Preventing access to the system with ipfwadm
Put the following in interchange.cfg
:
LockoutCommand ipfwadm -I -i deny -S %s
Note that the ipfwadm filtering system was used in Linux 2.0.* kernels, and is now largely obsolete.
A script could be written which would modify the appropriate access control
files, such as .htaccess
(Web server-level)
or /etc/hosts.deny
(TCP Wrappers-level), to do another
level of lockout.
Even a simple command line along the lines of
perl -0777 -npi -e 's/deny/deny from %s\ndeny/'
/path/to/cgi-bin/.htaccess
would work as well.
LogFile — specify Interchange log output filename
Specify catalog log file. If the filename is not absolute, it is treated relative to the catalog root directory (CATROOT).
The file will gather output of the
::logData()
function (including the tag log
).
Logging — specify log granularity treshold
This directive is currently largely unused in the code. The only two
priority_integer
s used are 4
and
5
.
When Logging
is set to a value greater than
4
, HTTP headers are logged.
When Logging
is set to a value greater than
5
, contents of the POST HTML form submission
are logged as well.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
MailOrderTo — specify e-mail address that completed orders should be sent to
The directive specifies
an e-mail address that completed orders should be sent to.
With a setting of 'none
', no e-mail order reports
would be sent.
MailOrderTo
is one of the basic Interchange configuration
directives.
If the catalog.cfg
file, expected in the catalog base directory, is not found, or is
unreadable by the Interchange server, somewhat misguiding error message will be reported.
Namely, instead of the appropriate permissions-problem message, this mandatory
MailOrderTo
directive will be reported undefined.
Mall — issue cookies only for the current catalog, and not the base domain
Issue cookies only for the current catalog's script. By default, when Interchange issues a cookie, it does so for the whole base domain.
This setting will allow multiple catalogs to operate on the same domain without interfering with each others session ID.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
MasterHost — specify regular expression that client IP must match to access protected directories
This directive specifies the hostname or IP regexp that the incoming requests must match in order to be allowed access to protected directories (see gate glossary entry), databases and administrative functions.
MaxQuantityField — specify tables and columns containing maximum allowed quantity for an item
The MaxQuantityField
directive specifies databases
and database columns containing the maximum allowed order quantity
for an item.
If the argument contains a colon ":
", it is treated
as a
specification.
Otherwise it indicates the name of the column and the table
defaults to the first TABLE:COLUMN
ProductFiles
database.
The record with the matching product SKU must exist in the target database, or the quantity will be unlimited.
It is possible to specify multiple database fields (separated by commas or spaces), in which case the maximum quantity allowed is set to the sum of all quantities found.
As of Interchange 5.7.0, a field prefixed with =
overrides
any previous value, while a field prefixed with ?
overrides previous value only if the new value is greater than zero.
Example: Setting MaxQuantityField
MaxQuantityField inventory:quantity, products:in_stock products:on_hand
Notice we can use commas and whitespace interchangeably to separate fields.
Example: Setting MaxQuantityField
Override any previous value with products:on_hand, if it contains a value greater than zero.
MaxQuantityField inventory:quantity ?products:on_hand
MaxRequestsPerChild — define maximum number of per-server page deliveries before respawn
The MaxRequestsPerChild
directive defines the maximum number
of page deliveries that each server instance will carry out before
closing down and respawning.
The whole point of a periodic respawn is to prevent accumulation of eventual memory leaks.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
MaxServers — define maximum number of spawned servers
The MaxServers
directive specifies the maximum number
of Interchange server processes to keep running at any one time.
If more requests are pending, they will be queued within the defined capability of the Operating System (usually 5 pending requests) until the server's "usage count" drops.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
Member — override catalog variables for logged-in users
The directive overrides values of catalog variables for logged-in users (usually members of the site).
The override functionality is available when the catalog variable is
accessed using the var
tag.
Example: Overriding a variable
Put the following in catalog.cfg
:
Variable GREETING Hello, Guest! Member GREETING Hello, Member!
Put the following on an Interchange page:
[var GREETING]
The above will return Hello, Guest!
or
Hello, Member!
, depending on whether
the user is logged in or not.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5295 (context shows lines 5295-5317)
sub parse_variable { my ($var, $value) = @_; my ($c, $name, $param); # Allow certain catalogs global subs unless (defined $value and $value) { $c = { 'save' => {} }; return $c; } if(defined $C) { $c = $C->{$var}; } else { no strict 'refs'; $c = ${"Global::$var"}; } ($name, $param) = split /\s+/, $value, 2; chomp $param; $c->{$name} = $param; return $c; }
Message — write custom message to console and Interchange log
This configuration directive displays a specified message on the console and in the Interchange log.
If the "option" -n
is present, Interchange strips leading and
trailing whitespace before display. If -i
is present
and Interchange is running in the foreground (that is, without detaching from the
controlling terminal), then the message is only output to the console,
avoiding the log.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2957 (context shows lines 2957-2990)
sub parse_message { my($name, $val) = @_; return '' unless $val; return 1 if $Vend::Quiet; my $strip; my $info_only; ## strip trailing whitespace if -n beins message while($val =~ s/^-([ni])\s+//) { $1 eq 'n' and $val =~ s/^-n\s+// and $strip = 1 and $val =~ s/\s+$//; $info_only = 1 if $1 eq 'i'; } my $msg = errmsg($val, $name, $., $configfile, ); if($info_only and $Global::Foreground) { print $msg; } else { logGlobal({level => 'info', strip => $strip }, errmsg($val, $name, $., $configfile, ) ); } }
MimeType — specify MIME types
The directive defines MIME types.
The argument extension
is the filename extension,
or a special value "default
" to apply to unknown
content.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
MinQuantityField — specify table and/or column containing minimum allowed quantity for an item
The MinQuantityField
directive specifies the database
and database column containing the minimum allowed order quantity
for an item.
When two arguments are supplied (concatenated by a colon, :
),
they indicate the appropriate database table and column name.
When only one argument is supplied, it indicates the name of the column;
table defaults to the products database.
The code of the item in question must be present in the database (code column), or there will be no minumum quantity enforced.
MoreDB — enable saving of search paging files into users' DBI sessions
This directive enables saving of search paging files into users' sessions.
This eliminates the need to have a ScratchDir
directory
between all Interchange server nodes.
This directive can only be used with DBI (database) sessions; trying to use it with non-database sessions will cause errors.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
NoAbsolute — deny catalogs to read absolute filenames on the system
The directive specifies whether to prevent commands and tags (such as
file
) to read absolute filenames (any files) on the system.
In cases where the Interchange daemon has no permission to read the file , this
directive — of course — has no influence.
This should be enabled in multiuser environments to minimize security problems.
Note that this does not apply to tests for whether a file exists (as one
would do with [if file ...]
or similar). Such operations are
allowed regardless of NoAbsolute
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
NoExport — specify databases not to re-export
The directive specifies external database tables that should never be exported back to the text source files.
Invocations of backup-database
are not affected
by this setting, and export
can force the export by specifying
force=1
.
Example: Disabling 'products' and 'inventory' table export
Put the following in catalog.cfg
:
NoExportExternal yes NoExport products inventory
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3013 (context shows lines 3013-3030)
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; }
NoExportExternal — enable use of the NoExport directive
The directive disables automatic export of internal database formats (SQL and LDAP) back to the text source files.
Invocations of backup-database
are not affected
by this setting, and export
can force the export by specifying
force=1
.
For an introduction to "exporting" and the times it can occur, see
database glossary entry and the NoExport
configuration
directive.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
NoImport — specify databases not to re-import, unless the database completely disappears
The directive specifies database tables that should never be automatically imported from the text source files.
Example: Disabling 'products' and 'inventory' table import
Put the following in catalog.cfg
:
NoImport products inventory
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3013 (context shows lines 3013-3030)
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; }
NoImportExternal — do not re-import external databases
The directive specifies that all external database tables should not be reimported from text source files.
For an introduction to "importing" and the times it can occur, see
database glossary entry and the NoImport
configuration
directive.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
NoSearch — specify databases on which Interchange-style searches cannot be performed
Specify database names or globs that will be matched against the databases used in any attempted search. You may separate multiple match strings with whitespace, and may include shell-style wildcards (globs).
The default setting is userdb
, which
means that, by default, you cannot use Interchange-style searches on the
userdb table.
Example: Defining NoSearch
Disable searching on userdb, and other databases
beginning with ".
" or ending in ".secret
".
NoSearch userdb .* *.secret
Example: Overriding NoSearch setting on a specific page
[calc] $Config->{NoSearch} = '' [/calc]
For a discussion on why this example works (and works per-page), see configuration glossary entry.
This directive only disables Interchange file/database-based searches; pure SQL searches still work.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3866 (context shows lines 3866-3886)
sub parse_wildcard { my($var, $value) = @_; return '' if ! $value; $value =~ s/\./\\./g; $value =~ s/\*/.*/g; $value =~ s/\?/./g; $value =~ s[({(?:.+?,)+.+?})] [ local $_ = $1; tr/{,}/(|)/; $_ ]eg; $value =~ s/\s+/|/g; eval { my $never = 'NeVAirBE'; $never =~ m{$value}; }; if($@) { config_error("Bad regular expression in $var."); } return $value; }
NonTaxableField — specify name of the non-taxable field in the products database
NotRobotUA — specify user-agents that will NOT be classified as crawler bots (search engines)
The NotRobotUA
directive defines a list of useragent strings which will
never be classified as crawler robots
(search engines) visiting the site.
This directive has priority over RobotUA
.
If the user agent matches NotRobotUA
, then the check for
RobotUA
is not performed and the client is not treated
as an unattended robot.
For more details regarding web spiders/bots and Interchange, see robot glossary entry.
For more details regarding user sessions, see session glossary entry.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3853 (context shows lines 3853-3857)
sub parse_list_wildcard { my $value = get_wildcard_list(@_,0); return '' unless length($value); return qr/$value/i; }
OfflineDir — specify directory to use for "offline" files
Specify directory to use for the offline database files, which are generated by the offline database build command.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3975 (context shows lines 3975-3989)
sub parse_relative_dir { my($var, $value) = @_; if (absolute_or_relative($value)) { config_error('Path %s not allowed in %s directive', $value, $var); } $C->{Source}{$var} = $value; $value = "$C->{VendRoot}/$value" unless file_name_is_absolute($value); $value =~ s./+$..; $value; }
OnFly — enable on-fly additions to client shopping cart
If the directive is enabled, it enables on-the-fly item additions to the client shopping cart. If set to a name of an existing ITL tag, the tag definition will be used to parse and format the item with the following call:
$item = Vend::Parse::do_tag($Vend::Cfg->{OnFly}, $code, $quantity, $fly[$j], );
In other words, your custom tag will be invoked with four arguments,
of which the first three are the tag name, item code and item quantity
respectively,
and the last argument is the value of mv_order_fly
mv
variable for the item.
The default onfly
tag that you can use in place of
ITL_tag_name
is already provided in Interchange.
Example: Configuring OnFly with a custom ITL tag
OnFly my_onfly_tag
For your custom tag, use the existing onfly
tag as a starting
point, whose
CVS source is available online in code/SystemTag/onfly.coretag.
Options
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3071 (context shows lines 3071-3135)
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 Vend::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; }
OptionsAttribute
OrderCleanup
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3802 (context shows lines 3802-3836)
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; }
OrderCounter — specify file that keeps and increments order count
Specify filename where the simple order number template is kept (and, of course, incremented with every new order). Within the template, the right-most number is found and incremented, preserving zero padding, if any.
If the counter file is unset, then the order number will be
assigned a string in form of
.
session_id
.unix_time
Bear in mind that Interchange provides this order number counter only as a convenience for display, and that no internal functions depend on it. Custom order number routines may be defined and used without fear of consequences.
If Route
is set to supplant
and the
counter
attribute is set there, this directive is ignored.
See order glossary entry for complete discussion of Interchange's ordering process.
OrderLineLimit — specify maximum number of items the user is allowed to place in the shopping cart
Specify maximum number of items that the user is allowed to place in the shopping cart.
Some poorly-mannered robots may "attack" a site by following
all links one after another. Some even ignore any
robots.txt
file that may have been created. If one of
these bad robots orders several dozen or more items, the time required to
save and restore the shopping cart from the user session may become excessive.
When the OrderLineLimit
is
exceeded, the command defined in LockoutCommand
will be executed and
the shopping cart will be emptied.
Set the directive to a number greater than the number of line items a user is ever expected to order.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
OrderProfile — specify files containing order profile definitions
Example: Dedicated directory for profile definitions
A wildcard can be used instead of listing the files individually. Beware of editor working files, backup files, etc., that would be included with a broad file-matching glob of * even though that would be easiest. It's safer to use something like a uniform .profile suffix as in this example:
OrderProfile profiles/*.profile
The actions defined in order profiles can also be used for
mv_click
actions
if the actions are not defined in scratch space. They are accessed by
setting the mv_order_profile
variable to the name of the order
profile.
For the complete discussion, please see the profile glossary entry.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4817 (context shows lines 4817-4858)
sub parse_profile { my ($var, $value) = @_; my ($c, $ref, $sref, $i); if($C) { $C->{"${var}Name"} = {} if ! $C->{"${var}Name"}; $sref = $C->{Source}; $ref = $C->{"${var}Name"}; $c = $C->{$var} || []; } else { no strict 'refs'; $sref = $Global::Source; ${"Global::${var}Name"} = {} if ! ${"Global::${var}Name"}; $ref = ${"Global::${var}Name"}; $c = ${"Global::$var"} || []; } $sref->{$var} = $value; my (@files) = glob($value); for(@files) { next unless $_; config_error( "No leading / allowed if NoAbsolute set. Contact administrator.\n") if m.^/. and $Global::NoAbsolute; config_error( "No leading ../.. allowed if NoAbsolute set. Contact administrator.\n") if m#^\.\./.*\.\.# and $Global::NoAbsolute; push @$c, (split /\s*[\r\n]+__END__[\r\n]+\s*/, readfile($_)); } for($i = 0; $i < @$c; $i++) { if($c->[$i] =~ s/(^|\n)__NAME__\s+([^\n\r]+)\r?\n/$1/) { my $name = $2; $name =~ s/\s+$//; $ref->{$name} = $i; } } return $c; }
OutputCookieHook
PGP — encrypt complete order reports automatically
The directive enables automatic encryption of complete order reports sent to the store owner or an e-mail processing system.
The PGP key ring must be in the Interchange daemon user's home directory,
or defined in the environment variable PGPPATH
.
The target user's public key must be present in the keyring, of course.
If this directive is non-null, the PGP command string will be used as-given
to encrypt the entire order, in addition to any encryption done as a result
of the CreditCardAuto
directive. If, for some reason, an error comes
from PGP, the customer will see special page
"failed
".
If the Route
directive is set up to "supplant
",
the PGP
directive is ignored.
PIDcheck — check running Interchange processes during the HouseKeeping routine
If set to a positive non-zero value, enables check of running
Interchange processes during the HouseKeeping
routine.
If a process has been running (or is hung) for longer than the
specified interval, then kill -9
will
be issued and the server count decremented.
Interchange also logs this incident in the global error log file. The log line looks like this example: hammered PID 21429 running 312 seconds.
If you have long-running database builds, this directive needs to stay
disabled, or set to a high value (of perhaps 600
, or
10 minutes
), or use the bin/offline
script.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4115 (context shows lines 4115-4127)
sub parse_time { my($var, $value) = @_; my($n); return $value unless $value; # $C->{Source}->{$var} = [$value]; $n = time_to_seconds($value); config_error("Bad time format ('$value') in the $var directive\n") unless defined $n; $n; }
PIDfile — PID filename
Specify the filename that will contain Interchange server process ID. As with most Unix daemons, this is an elegant way to determine which process should be sent a signal for stopping or reconfiguring the server.
The location must be writable by the Interchange daemon.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3925 (context shows lines 3925-3932)
sub parse_root_dir { my($var, $value) = @_; return '' unless $value; $value = "$Global::VendRoot/$value" unless file_name_is_absolute($value); $value =~ s./+$..; return $value; }
PageDir — specify directory containing catalog pages
Specify the directory containing catalog pages. The default for this
directive is pages
.
Speaking of internationalization, it can be useful to set this directive to different values, depending on current locale.
Example: Setting PageDir depending on current locale
To use a different page directory for different locales, say French and
English, help yourself with the robust Locale
directive:
# Establish the default at startup PageDir english # Establish locale-dependent directories Locale fr_FR PageDir francais Locale en_US PageDir english
To fully understand the example and implicitly presented Interchange features, make sure you're familiar with internationalization and locale glossary entries.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3975 (context shows lines 3975-3989)
sub parse_relative_dir { my($var, $value) = @_; if (absolute_or_relative($value)) { config_error('Path %s not allowed in %s directive', $value, $var); } $C->{Source}{$var} = $value; $value = "$C->{VendRoot}/$value" unless file_name_is_absolute($value); $value =~ s./+$..; $value; }
PageSelectField — specify products database column used to select the flypage
The directive sets a products database column
which can be used to
select the on-the-fly template page (the flypage). This allows
multiple flypages to be defined and selected automatically. If the field
is empty (no spaces!), the default, flypage
, will be used.
PageTableMap — map field names for page lookup tables
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 564 (context shows lines 554-560)
['PageTableMap', 'hash', qq{ expiration_date expiration_date show_date show_date page_text page_text base_page base_page code code }],
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
PageTables
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3838 (context shows lines 3838-3851)
sub parse_array_complete { my($item,$settings) = @_; return '' unless $settings; my(@setting) = grep /\S/, split /[\s,]+/, $settings; my $c = []; for (@setting) { check_legal($item, $_); push @{$c}, $_; } $c; }
ParseVariables — parse (interpolate) config file variables
Specify whether the configuration directives should have their values parsed (interpolated).
This applies to all configuration directives except Variable
.
Of variables, only those in ALL CAPS are interpolated.
Example: Defining a variable containing parse-needing data
Variable STORE_ID topshop ParseVariables Yes StaticDir /home/__STORE_ID__/www/cat ParseVariables No
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
Password — specify password for RemoteUser
Password that will cause internal authorization checks for RemoteUser
to allow access.
The password must be encrypted, unless MV_NO_CRYPT
is
enabled.
Example: Setting Password with an encrypted string corresponding to a blank password
Password bAWoVkuzphOX.
The encrypted password is a standard Unix crypt, which you can obtain either
using makepasswd --crypt or indirectly
using htpasswd, or invoking
perl -le'print crypt("mypasswd","AA")',
where mypasswd
is the desired password and
AA
are two random characters called
the salt.
See MV_NO_CRYPT
and crypt
for more discussion.
See crypt glossary entry for complete information on crypto
algorithms used and ways to generate encrypted strings.
PerlAlwaysGlobal
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3013 (context shows lines 3013-3030)
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; }
PerlNoStrict
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3013 (context shows lines 3013-3030)
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; }
PermanentDir — specify directory containing temporary files for permanent searches
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3975 (context shows lines 3975-3989)
sub parse_relative_dir { my($var, $value) = @_; if (absolute_or_relative($value)) { config_error('Path %s not allowed in %s directive', $value, $var); } $C->{Source}{$var} = $value; $value = "$C->{VendRoot}/$value" unless file_name_is_absolute($value); $value =~ s./+$..; $value; }
PostURL — specify URL for POST requests
The directive specifies a catalog URL for POST form submissions.
This allows an automatically different path for GET and POST
requests, presuming you use the process
tag as
form action target.
Example: Setting PostURL
Put the following lines in catalog.cfg
:
VendURL http://myhost.mydomain.local/ SecureURL https://myhost.mydomain.local/ PostURL http://myhost.mydomain.local/cgi-bin/standard SecurePostURL https://myhost.mydomain.local/cgi-bin/standard
PostURL
value can also be a relative path, with or without the
protocol and hostname specification.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4002 (context shows lines 4002-4006)
sub parse_url { my($var, $value) = @_; $value =~ s,/+$,,; $value; }
Pragma — specify pragma's default value
The directive enables specified Interchange pragma by
setting it to "1
" or a user-supplied value.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3033 (context shows lines 3033-3058)
sub parse_boolean_value { my($item,$settings) = @_; my(@setting) = split /[\s,]+/, $settings; my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } for (@setting) { my ($k,$v); if(/=/) { ($k,$v) = split /=/, $_, 2; } else { $k = $_; $v = 1; } $c->{$k} = $v; } return $c; }
PreFork — specify whether Interchange server should pre-fork processes that wait for client connections
For each new client connection, Interchange must spawn a new process that will
handle communication with the client.
By using PreFork
, it is possible to pre-fork
(or in other words, "start ahead of time") some number of Interchange servers
that will be ready to serve client requests immediately as they come in.
If you're running PreFork, you should use it in combination with
PreForkSingleFork
, to create the absolute minimal number of forks
necessary. Only turn PreForkSingleFork
off
if it causes zombie processes to pile up.
This method reduces system overhead due to forking and is the fastest and best way to run a busy Interchange server.
Regardless of the PreFork
setting, each spawned server will serve
MaxRequestsPerChild
requests, before being shut down and respawned.
(This technique is used to prevent any memory leaks).
For an introduction to Interchange run modes and practical implications, please see the ic run mode glossary entry.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
PreForkSingleFork — perform one instead of two forks in PreFork mode
This directive affects Interchange behavior in conjunction with
PreFork
, by using one instead of two fork()
calls to prefork a server.
If you are running Interchange in prefork mode, you should use it in combination with
this directive. Only turn PreForkSingleFork
off if it causes zombie
processes to pile up on your system.
This method reduces system overhead when forking and is the fastest and best way to run a busy Interchange server.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
Preload — specify macro to be executed at the very beginning of every request
This is just like Autoload
as it executes an Interchange macro
but runs at the earliest possible stage of request processing, which
allows tweaking the session, path, robot status, cookie handling,
authorization, etc.
Example: Simple Preload example
This example shows how to not create a session for any but explicitly listed URL prefixes.
Put the following in interchange.cfg
:
GlobalSub <<EOR sub skip_session { $CGI::values{mv_tmp_session} = 1 if $CGI::path_info =~ m{\A/(?:aboutus|contact|info)}; return; } EOR
Put the following in catalog.cfg
:
Preload skip_session
For diagnostic purposes, you can put a footer in your bottom page template to show the current session ID:
session ID=[data session id]
Restart Interchange, then visit various pages. Whenever you visit a page whose path starts with "aboutus", "contact", or "info", no session will be assigned, which you can verify by looking at your diagnostic output at the bottom of the page. This can be useful if you require cookies for session access, and don't want to incur the overhead of session access on pages that don't need it.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3802 (context shows lines 3802-3836)
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; }
PriceCommas — show thousands separator in price pictures
The directive specifies whether mon_thousands_sep
(specified as part of Locale
) will be used in currency formatting
for display.
If no commas are desired in price numbers (for the item-price
tag etc.),
disable this directive.
Despite the possibly misleading directive name, Interchange does not always insert
a comma (",
") but a proper locale-equivalent of it.
Example: Setting PriceCommas depending on current locale
# Establish a default PriceCommas 1 # Establish locale-specific price commas Locale fr_FR PriceCommas 0 Locale en_US PriceCommas 1
To fully understand the example and implicitly presented Interchange features, make sure you're familiar with internationalization and locale glossary entries.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
PriceDefault — specify default price field in chained pricing schemes
When chained price scheme is used and a specification of
is given without explicit
table
:field
:key
:
, the value in
field
PriceDefault
will be used.
The default value is price
.
PriceDivide — specify number to divide the price by, to obtain price in units
The number the price should be divided by, to get the price in base units (dollars or such).
For example, if you keep your prices specified in pennies (100th part of a
dollar), set the directive to 100
.
Example: Setting PriceDivide depending on current locale
# (Default is PriceDivide 1, so no special setting required) #PriceDivide 1 # Establish locale-specific price division Locale fr_FR PriceDivide .20
The following would make prices expressed in French francs five times higher than corresponding dollar amounts.
To fully understand the example and implicitly presented Interchange features, make sure you're familiar with internationalization and locale glossary entries.
PriceField — specify name of the "price" field in the Interchange database
By default, Interchange expects item price to be in the price field in the database. This directive allows modification of the default name.
The field is accessed implicitly when you call say,
[item-price]
in ITL.
Example: Setting PriceField depending on current locale
# Establish the default at startup PriceField price # Establish locale-specific price field Locale fr_FR PriceField prix
With the above example, if is enabled, the prix field from the pricing database will be used to develop quantity-based pricing.
To fully understand the example and implicitly presented Interchange features, make sure you're familiar with internationalization and locale glossary entries.
ProcessPage — specify "virtual" location of the form processor page
The directive specifies the name of the process
page
(the Interchange form processor page). The process page does not really
exist on the disk — it is defined as an ActionMap
.
ProductDir — specify directory containing database files
Specify the directory containing database files.
The directory cannot be absolute, unless NoAbsolute
is disabled.
The specified location is, unless absolute, treated relative to CATROOT.
This directive is also available through an alias
DataDir
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3975 (context shows lines 3975-3989)
sub parse_relative_dir { my($var, $value) = @_; if (absolute_or_relative($value)) { config_error('Path %s not allowed in %s directive', $value, $var); } $C->{Source}{$var} = $value; $value = "$C->{VendRoot}/$value" unless file_name_is_absolute($value); $value =~ s./+$..; $value; }
ProductFiles — specify all databases containing products that form one big "products" database
Specify database tables that should be, all together, logically seen as one bigger products database.
For example, when doing product searches, all ProductFiles
databases
will be searched.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3838 (context shows lines 3838-3851)
sub parse_array_complete { my($item,$settings) = @_; return '' unless $settings; my(@setting) = grep /\S/, split /[\s,]+/, $settings; my $c = []; for (@setting) { check_legal($item, $_); push @{$c}, $_; } $c; }
Profile
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3071 (context shows lines 3071-3135)
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 Vend::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; }
Profiles — specify files containing OrderProfile definitions on a global level
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4817 (context shows lines 4817-4858)
sub parse_profile { my ($var, $value) = @_; my ($c, $ref, $sref, $i); if($C) { $C->{"${var}Name"} = {} if ! $C->{"${var}Name"}; $sref = $C->{Source}; $ref = $C->{"${var}Name"}; $c = $C->{$var} || []; } else { no strict 'refs'; $sref = $Global::Source; ${"Global::${var}Name"} = {} if ! ${"Global::${var}Name"}; $ref = ${"Global::${var}Name"}; $c = ${"Global::$var"} || []; } $sref->{$var} = $value; my (@files) = glob($value); for(@files) { next unless $_; config_error( "No leading / allowed if NoAbsolute set. Contact administrator.\n") if m.^/. and $Global::NoAbsolute; config_error( "No leading ../.. allowed if NoAbsolute set. Contact administrator.\n") if m#^\.\./.*\.\.# and $Global::NoAbsolute; push @$c, (split /\s*[\r\n]+__END__[\r\n]+\s*/, readfile($_)); } for($i = 0; $i < @$c; $i++) { if($c->[$i] =~ s/(^|\n)__NAME__\s+([^\n\r]+)\r?\n/$1/) { my $name = $2; $name =~ s/\s+$//; $ref->{$name} = $i; } } return $c; }
Promiscuous — allow output of HTML code in value variables
By default, when this directive is disabled, the characteristic HTML characters (< and >), are encoded to < and >.
This catalog-wide directive is equivalent in effect to passing
enable_html=1
attribute to the individual value
tags.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
QueryCache
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
ReadPermission — affect file mode (read permissions, specifically) on Interchange-generated files
By default, only the user account that Interchange runs under, can read and read files created by Interchange. The specified option allows adjustment of file read permissions.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5448 (context shows lines 5448-5457)
sub parse_permission { my($var, $value) = @_; $_ = $value; tr/A-Z/a-z/; if ($_ ne 'user' and $_ ne 'group' and $_ ne 'world') { config_error("Permission must be one of 'user', 'group', or 'world' for the $var directive\n"); } $_; }
RedirectCache — use Interchange to generate static web server pages
This directive, along with AcceptRedirect
, allows
the web server to route requests for missing static HTML pages to Interchange.
Interchange processes the requests and saves the produced static content
to the directory pointed by RedirectCache
. On next web server
page access, the pages are found and served as static content by the
web server directly.
Requests routed to Interchange in this way use a temporary session (mv_tmp_session
).
In case the Interchange page is not found, the usual SpecialPage
"missing"
is shown and no writing to the web server HTML directory takes place.
RemoteUser — specify required value of the REMOTE_USER environment variable
Replace — reset directive to a new value, or to its default
Cause configuration directive's value to be emptied and reset to the specified value, or to its default.
This is useful primarily for resetting configuration directives which append to existing data, so there's no other convenient way to reset them to initial values.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2944 (context shows lines 2944-2952)
sub parse_replace { my($name, $val) = @_; return {} unless $val; $C->{$val} = get_catalog_default($val); $C->{$name}->{$val} = 1; $C->{$name}; }
Require — require existence of a capability
Just like Capability
or Suggest
, this directive checks for
a feature or capability. When the tested feature is missing, a
catalog is not configured and not included in global configuration.
This is useful to ensure that needed facilities are present, especially if you run the catalog on different locations.
"Capabilities" you can require are:
globalsub
— existence of a GlobalSub
sub
— existence of a Sub
taggroup
— existence of a TagGroup
usertag
— existence of a UserTag
module (or perlmodule)
— existence of a Perl module. Optional additional argument is the custom Perl module path.
include (or perlinclude)
— prepend specified path to Perl's @INC
include path (makes most sense with Require
, not with Suggest
or Capability
even though it can be called that way for equivalent effect)
file
— existence of a readable file
executable
— existence of an executable file
Example: Requiring existence of all supported items
Require globalsub my_global_sub Require sub my_sub Require taggroup :group1,:group2 :group3 Require usertag my_global_usertag Require usertag my_catalog_usertag Require module Archive::Zip Require module Set::Crontab /usr/local/perl/modules/ Require file /etc/syslog.conf Require file relative-dir/file Require executable /usr/local/bin/gfont Require executable bin/gfont
Example: Requiring features
Require module Archive::Zip Require usertag table_editor Require globalsub file_info
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2690 (context shows lines 2690-2863)
sub parse_require { my($var, $val, $warn, $cap) = @_; return if $Vend::ExternalProgram; return if $Vend::ControllingInterchange; my $carptype; my $error_message; my $pathinfo; if($val =~ s/\s+"(.*)"//s) { $error_message = "\a\n\n$1\n"; } if($val =~ s%\s+((/[\w.-]+)+)%%) { $pathinfo = $1; } if($cap) { $carptype = sub { return; }; } elsif($warn) { $carptype = sub { return parse_message('', @_) }; $error_message = "\a\n\nSuggest %s %s for proper catalog operation. \ Not all functions will work!\n" unless $error_message; } else { $carptype = \&config_error; $error_message ||= 'Required %s %s not present. Aborting ' . ($C ? 'catalog' : 'Interchange daemon') . '.'; } my $nostrict; my $perlglobal = 1; if($C) { $nostrict = $Global::PerlNoStrict->{$C->{CatalogName}}; $perlglobal = $Global::AllowGlobal->{$C->{CatalogName}}; } my $vref = $C ? $C->{Variable} : $Global::Variable; my $require; my $testsub = sub { 0 }; my $name; if($val =~ s/^globalsub\s+//i) { $require = $Global::GlobalSub; $name = 'GlobalSub'; } elsif($val =~ s/^sub\s+//i) { $require = $C->{Sub}; $name = 'Sub'; } elsif($val =~ s/^taggroup\s+//i) { $require = $Global::UserTag->{Routine}; my @groups = grep /\S/, split /[\s,]+/, $val; my @needed; my $ref; for (@groups) { if($ref = $Global::TagGroup->{$_}) { push @needed, @$ref; } else { push @needed, $_; } } $name = "TagGroup $val member"; $val = join " ", @needed; } elsif($val =~ s/^usertag\s+//i) { $require = {}; $name = 'UserTag'; $testsub = sub { my $name = shift; my @tries = ($Global::UserTag->{Routine}); push(@tries,$C->{UserTag}->{Routine}) if $C; foreach (@tries) { return 1 if defined $_->{$name}; } return 0; }; } elsif($val =~ s/^(?:perl)?module\s+//i) { $require = {}; $name = 'Perl module'; $testsub = sub { my $module = shift; my $oldtype = ''; if($module =~ s/\.pl$//) { $oldtype = '.pl'; } $module =~ /[^\w:]/ and return undef; if($perlglobal) { if ($pathinfo) { unshift(@INC, $pathinfo); unshift(@INC, "$pathinfo/$Config{archname}"); } eval "require $module$oldtype;"; my $error = $@; if ($pathinfo) { shift(@INC); shift(@INC); } ::logGlobal("while eval'ing module %s got [%s]\n", $module, $error) if $error; return ! $error; } else { # Since we aren't safe to actually require, we will # just look for a readable module file $module =~ s!::!/!g; $oldtype = '.pm' if ! $oldtype; my $found; for(@INC) { next unless -f "$_/$module$oldtype" and -r _; $found = 1; } return $found; } }; } elsif ($val =~ s/^(?:perl)?include\s+//i) { my $path = Vend::File::make_absolute_file($val, 1); $require = {}; $name = 'Perl include path'; $testsub = sub { if (-d $path) { unshift @INC, $path; return 1; } return 0; }; } elsif ($val =~ s/^file\s*//i) { $require = {}; $name = 'Readable file'; $val = $pathinfo unless $val; $testsub = sub { my $path = Vend::File::make_absolute_file(shift, $C ? 0 : 1); if ($C && $path =~ s:^/+::) { $path = "$C->{VendRoot}/$path"; } return -r $path; }; } elsif ($val =~ s/^executable\s*//i) { $require = {}; $name = 'Executable file'; $val = $pathinfo unless $val; $testsub = sub { my $path = Vend::File::make_absolute_file(shift, $C ? 0 : 1); if ($C && $path =~ s:^/+::) { $path = "$C->{VendRoot}/$path"; } return -x $path; }; } my @requires = grep /\S/, split /\s+/, $val; my $uname = uc $name; $uname =~ s/.*\s+//; for(@requires) { $vref->{"MV_REQUIRE_${uname}_$_"} = 1; next if defined $require->{$_}; next if $testsub->($_); delete $vref->{"MV_REQUIRE_${uname}_$_"}; $carptype->( $error_message, $name, $_ ); } return ''; }
RobotHost — specify hostnames that will be classified as crawler bots (search engines) visiting the site
The RobotHost
directive defines a list of hostnames which will be
classified as crawler robots (search engines), and cause Interchange to alter its
behavior to improve the chance of Interchange-served content being crawled
and indexed.
Note that this directive (and all other work done to identify robots) only serves to improve the way in which Interchange pages are indexed, and to reduce server overhead for clients that don't require our full attention in the way humans do (for example, session information is not kept around for spider bots). Using this to "tune" the actual page content depending on a crawler visiting does not earn you extra points, and may in fact be detected by the robot and punished.
It's important to note that the directive accepts a wildcard list similar
to globbing —
*
represents any number of characters, while
?
represents a single character.
Example: Defining RobotHost
RobotHost <<EOR *.crawler*.com, *.excite.com, *.googlebot.com, *.infoseek.com, *.inktomi.com, *.inktomisearch.com, *.lycos.com, *.pa-x.dec.com, add-url.altavista.com, westinghouse-rsl-com-usa.NorthRoyalton.cw.net, EOR
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3859 (context shows lines 3859-3863)
sub parse_list_wildcard_full { my $value = get_wildcard_list(@_,1); return '' unless length($value); return qr/^($value)$/i; }
RobotIP — specify IP numbers or ranges that will be classified as crawler bots (search engines)
The RobotIP
directive defines a list of IP numbers which will be
classified as crawler robots (search engines), and cause Interchange to alter its
behavior to improve the chance of Interchange-served content being crawled
and indexed.
Note that this directive (and all other work done to identify robots) only serves to improve the way in which Interchange pages are indexed, and to reduce server overhead for clients that don't require our full attention in the way humans do (for example, session information is not kept around for spider bots). Using this to "tune" the actual page content depending on a crawler visiting does not earn you extra points, and may in fact be detected by the robot and punished.
It's important to note that the directive accepts a wildcard list similar
to globbing —
*
represents any number of characters, while
?
represents a single character.
Example: Defining RobotIP
RobotIP <<EOR 202.9.155.123, 204.152.191.41, 208.146.26.19, 208.146.26.233, 209.185.141.209, 209.185.141.211, 209.202.148.36, 209.202.148.41, 216.200.130.207, 216.35.103.6?, 216.35.103.*, EOR
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3859 (context shows lines 3859-3863)
sub parse_list_wildcard_full { my $value = get_wildcard_list(@_,1); return '' unless length($value); return qr/^($value)$/i; }
RobotLimit — specify maximum number of pages a user can visit without a short pause
Specify maximum number of consecutive pages a user may access without a short pause.
When the RobotLimit
is
exceeded, the command defined in LockoutCommand
will be executed and
the catalog URLs will be rewritten to
127.0.0.1
, effectively pointing the robot back to itself.
The short pause amounts to 30 seconds and can be configured using the Limit
directive's lockout_reset_seconds
setting.
If a remote client gets assigned a new session with every visit, rather than
maintaining a single session, then this directive sets the limit for the
number of sessions that may be assigned to the individual IP address over a
one hour period. The one hour period can be overridden using the Limit
directive's ip_session_expire
setting. If a lockout is triggered it will
remain in effect for 1 day. The one day period can be overridden with the
Limit
directive's robot_expire
setting.
Set the directive to a number greater than the number of pages users are ever expected to visit in a short time frame.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
RobotUA — specify user-agents that will be classified as crawler bots (search engines)
The RobotUA
directive defines a list of useragent strings which will be
classified as crawler robots (search engines), and cause Interchange to alter its
behavior to improve the chance of Interchange-served content being crawled
and indexed.
Note that this directive (and all other work done to identify robots) only serves to improve the way in which Interchange pages are indexed, and to reduce server overhead for clients that don't require our full attention in the way humans do (for example, session information is not kept around for spider bots). Using this to "tune" the actual page content depending on a crawler visiting does not earn you extra points, and may in fact be detected by the robot and punished.
It's important to note that the directive accepts a wildcard list similar
to globbing —
*
represents any number of characters, while
?
represents a single character.
Example: Defining RobotUA
RobotUA <<EOR ATN_Worldwide, AltaVista, Arachnoidea, Aranha, Architext, Ask, Atomz, BackRub, Builder, CMC, Contact, Digital*Integrity, Directory, EZResult, Excite, Ferret, Fireball, Google, Gromit, Gulliver, Harvest, Hubater, H?m?h?kki, INGRID, IncyWincy, Jack, KIT*Fireball, Kototoi, LWP, Lycos, MegaSheep, Mercator, Nazilla, NetMechanic, NetResearchServer, NetScoop, ParaSite, Refiner, RoboDude, Rover, Rutgers, Scooter, Slurp, Spyder, T-H-U-N-D-E-R-S-T-O-N-E, Toutatis, Tv*Merc, Valkyrie, Voyager, WIRE, Walker, Wget, WhizBang, Wire, Wombat, Yahoo, Yandex, ZyBorg, appie, asterias, bot, contact, crawl, collector, fido, find, gazz, grabber, griffon, archiver, legs, marvin, mirago, moget, newscan, seek, speedy, spider, suke, tarantula, agent, topiclink, whowhere, winona, worm, xtreme, EOR
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3853 (context shows lines 3853-3857)
sub parse_list_wildcard { my $value = get_wildcard_list(@_,0); return '' unless length($value); return qr/$value/i; }
Route — specify order and payment routes
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3071 (context shows lines 3071-3135)
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 Vend::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; }
RouteDatabase
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4683 (context shows lines 4683-4733)
sub parse_configdb { my ($var, $value) = @_; my ($file, $type); return '' if ! $value; local($Vend::Cfg) = $C; my ($db, $table); eval { ($db, $table) = get_configdb($var, $value); }; ::logGlobal("$var $value: $@") if $@; return '' if ! $db; my ($k, @f); # key and fields my @l; # refs to locale repository my @n; # names of locales my @h; # names of locales my $base_direc = $var; $base_direc =~ s/Database$//; my $repos_name = $base_direc . '_repository'; my $repos = $C->{$repos_name} ||= {}; @n = $db->columns(); shift @n; my $i; if($Columnar{$base_direc}) { my @l; for(@n) { $repos->{$_} ||= {}; push @l, $repos->{$_}; } my $i; while( ($k , undef, @f ) = $db->each_record) { for ($i = 0; $i < @f; $i++) { next unless length($f[$i]); $l[$i]->{$k} = $f[$i]; } } } else { while( ($k, undef, @f ) = $db->each_record) { for ($i = 0; $i < @f; $i++) { next unless length($f[$i]); $repos->{$k}{$n[$i]} = $f[$i]; } } } $db->close_table(); return $table; }
RunDir — specify directory containing runtime files
Specify the directory containing "runtime" information.
This directory is similar to /var/run/
in the Unix filesystem. Examples of files that you will encounter in there
are the global .structure
file (see
DumpStructure
), .pid
and
mode.
files and Interchange cronjob files (see Jobs
).
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3925 (context shows lines 3925-3932)
sub parse_root_dir { my($var, $value) = @_; return '' unless $value; $value = "$Global::VendRoot/$value" unless file_name_is_absolute($value); $value =~ s./+$..; return $value; }
Source: lib/Vend/Config.pm
Line 3975 (context shows lines 3975-3989)
sub parse_relative_dir { my($var, $value) = @_; if (absolute_or_relative($value)) { config_error('Path %s not allowed in %s directive', $value, $var); } $C->{Source}{$var} = $value; $value = "$C->{VendRoot}/$value" unless file_name_is_absolute($value); $value =~ s./+$..; $value; }
SOAP — enable handling of SOAP RPC requests
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
SOAP_Action — define SOAP actions
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2161 (context shows lines 2161-2258)
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; $name =~ s/-/_/g; ## Determine if we are in a catalog config, and if ## perl should be global and/or strict my $nostrict; my $perlglobal = 1; if($C) { $nostrict = $Global::PerlNoStrict->{$C->{CatalogName}}; $perlglobal = $Global::AllowGlobal->{$C->{CatalogName}}; } # Untaint and strip this pup $sub =~ s/^\s*((?s:.)*\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 ($perlglobal) { package Vend::Interpolate; if($nostrict) { no strict; $c->{$name} = eval $sub; } else { $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; }
SOAP_Control — control access to SOAP features
Example: Allow actions only
SOAP_Control Action always SOAP_Control Tag never SOAP_Control Values never SOAP_Control Database never SOAP_Control Scratch never
The global settings take precedence. For example, allowing actions in the
catalog configuration with SOAP_Control Action always
only
works when the global configuration permit this feature as well.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2161 (context shows lines 2161-2258)
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; $name =~ s/-/_/g; ## Determine if we are in a catalog config, and if ## perl should be global and/or strict my $nostrict; my $perlglobal = 1; if($C) { $nostrict = $Global::PerlNoStrict->{$C->{CatalogName}}; $perlglobal = $Global::AllowGlobal->{$C->{CatalogName}}; } # Untaint and strip this pup $sub =~ s/^\s*((?s:.)*\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 ($perlglobal) { package Vend::Interpolate; if($nostrict) { no strict; $c->{$name} = eval $sub; } else { $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; }
SOAP_Enable
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
SOAP_MaxRequests — define maximum number of per-server SOAP RPC response deliveries before respawn
The directive defines the maximum number of SOAP RPC responses each server instance will carry out before closing down and respawning.
The whole point of a periodic respawn is to prevent accumulation of eventual memory leaks.
The default value is 50
. In case the default value is
somehow cleared, the hard-coded default is 10
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
SOAP_Perms — specify SOAP RPC Unix socket permissions
Specify permissions (mode) for the Interchange SOAP RPC UNIX-domain socket.
Prepend a starting 0
to indicate an octal value.
The default value is 0660
, which allows only programs
running under your Interchange server UID or GID to access the socket.
Although not recommended in practice, it sometimes makes sense to
set the permissions to 0666
(world-writable) to
debug problems easier.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
SOAP_Socket — specify name of SOAP RPC socket file
The directive specifies the Inet and Unix sockets Interchange should listen on for SOAP RPC requests.
The list should be space-separated. Each entry is considered to be
an Unix socket if it contains "/
" somewhere in its
path. Any other specification is considered an Inet socket, and can be
in form of
, where the IP address and the colon are optional.
NNN
.NNN
.NNN
.NNN
:PPPP
The default value is Inet socket on port 7780
, if
SOAP
is enabled.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3780 (context shows lines 3780-3800)
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; }
SOAP_StartServers — specify number of servers which should be started to handle SOAP RPC requests
The directive specifies the number of servers which should be started to handle SOAP RPC requests.
The default is 1
. Setting the directive to more than
50
is unreasonable and produces an error.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
SafeTrap — specify operation codes to trap in Safe.pm compartments
The directive defines the opcodes that will be trapped in the
Safe
compartments, for use in
embedded Perl and conditional operations.
For a complete discussion and the opcodes list, see Opcode(3perl) manual page.
Please see the safe glossary entry for the introduction and guidelines
to programming under Safe.pm
restrictions.
The SafeUntrap
directive runs after
SafeTrap
and takes precedence. Make sure the opcodes you want
to trap are not later untrapped with SafeUntrap
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3780 (context shows lines 3780-3800)
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; }
SafeUntrap — specify operation codes to untrap in Safe.pm compartments
The directive defines the opcodes that will be untrapped in the
Safe
compartments, for use in
embedded Perl and conditional operations.
Define it as blank to prevent any operators but the default restrictive ones.
For a complete discussion and the complete list of opcodes, see Opcode(3perl) manual page.
Example: Allowing -s function to determine file size
The following code fails to work with the default SafeUntrap setting.
[set upload_repository]upload/[/set] [calcn]-s $Scratch->{upload_repository};[/calcn]
Adding ftsize
to SafeUntrap solves this problem:
SafeUntrap ftsize
Example: Allowing a group of file-related operations
[set data_file]products/biglist.txt[/set] [calcn]-r $Scratch->{data_file};[/calcn]
Adding :filesys_read
to SafeUntrap solves this problem:
SafeUntrap :filesys_read
See the Opcode(3perl) manual page for more information and the complete list of operation codes and groups.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3780 (context shows lines 3780-3800)
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; }
SalesTax — specifies sales tax calculation mode
This directive configures sales tax calculation.
The value
can be one of three types:
Type | Description |
---|---|
multi | Enables table-based lookup of tax rates, based upon form input values, by default the values used are country and state . |
ITL | If the value contains a square bracket, it is interpolated as ITL. The result is used as the amount of the salestax. This could be useful if you want to use a custom UserTag for sales tax calculations. |
name ... | A comma-separated list of form values in priority order. Enables look up of the tax rate "salestax.asc" file. |
SalesTaxFunction — specify custom tax calculation function
The directive specifies custom sales tax function.
The function return value has to be a Perl hash, just like other Interchange tax calculation methods would return. Make sure the "DEFAULT" value is returned, or the tax will unconditionally yield zero.
Example: Calculate tax amount based on vendor
SalesTaxFunction <<EOR my $vendor_id = $Session->{source}; my $tax_hash = $TextSearch->hash( { se => $vendor_id, fi => 'salestax.asc', sf => 'vendor_code', ml => 1000, } ); $tax_hash = {} if ! $tax_hash; $tax_hash->{DEFAULT} = 0; return $tax_hash; EOR
Example: Calculate tax
SalesTaxFunction <<EOR return { DEFAULT => 0.0, IL => 0.075, OH => 0.065, }; EOR
SaveExpire — specify the amount of time for which Interchange cookies should be valid (their expiry time)
Specify interval, an amount of time, that Interchange-issued cookies should be valid for.
This, of course, only applies to cookies other than session ID
cookie (MV_SESSION_ID
), which always lasts only for the
duration of the session.
The ones used in Interchange by default (and which are affected by this directive)
are MV_USERNAME
and MV_PASSWORD
, for
the CookieLogin
feature.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4115 (context shows lines 4115-4127)
sub parse_time { my($var, $value) = @_; my($n); return $value unless $value; # $C->{Source}->{$var} = [$value]; $n = time_to_seconds($value); config_error("Bad time format ('$value') in the $var directive\n") unless defined $n; $n; }
ScratchDefault — define default scratch variable values
The directive sets default scratch variable values. These are initialized and assigned every time a new uses session is created.
Example: Defining default scratch values
Make Interchange URLs elegant — do not include the session ID information
or the "counter", and append .html
to pages if it is
missing.
ScratchDefault mv_no_session_id 1 mv_no_count 1 ScratchDefault mv_add_dot_html 1
To understand this example, see scratch and session glossary
entries, and the HTMLsuffix
configuration directive.
Example: Using ScratchDefault to define default locale
It is recommended to use this directive for setting the catalog's default locale:
ScratchDefault mv_locale de_DE
To understand this example, see internationalization and locale glossary entries.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
ScratchDir — specify directory containing temporary files
Specify the directory containing temporary, runtime files.
The kind of files Interchange drops to the ScratchDir
directory include
cached searches and retired session IDs.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3975 (context shows lines 3975-3989)
sub parse_relative_dir { my($var, $value) = @_; if (absolute_or_relative($value)) { config_error('Path %s not allowed in %s directive', $value, $var); } $C->{Source}{$var} = $value; $value = "$C->{VendRoot}/$value" unless file_name_is_absolute($value); $value =~ s./+$..; $value; }
SearchProfile — specify files containing search profile definitions
The directive specifies filenames that contain search profile definitions.
An unlimited number of search profiles can be set up, performing complex searches on a single user click. At the same time, separately-defined search profiles keep your HTML pages cleaner.
As said,
multiple profiles can be defined, and within the same file.
In that case, profiles must be separated by __END__
tokens. Each opening __NAME__
token should be left-aligned,
and each __END__
should be on a line by itself,
with no leading or trailing whitespace.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4817 (context shows lines 4817-4858)
sub parse_profile { my ($var, $value) = @_; my ($c, $ref, $sref, $i); if($C) { $C->{"${var}Name"} = {} if ! $C->{"${var}Name"}; $sref = $C->{Source}; $ref = $C->{"${var}Name"}; $c = $C->{$var} || []; } else { no strict 'refs'; $sref = $Global::Source; ${"Global::${var}Name"} = {} if ! ${"Global::${var}Name"}; $ref = ${"Global::${var}Name"}; $c = ${"Global::$var"} || []; } $sref->{$var} = $value; my (@files) = glob($value); for(@files) { next unless $_; config_error( "No leading / allowed if NoAbsolute set. Contact administrator.\n") if m.^/. and $Global::NoAbsolute; config_error( "No leading ../.. allowed if NoAbsolute set. Contact administrator.\n") if m#^\.\./.*\.\.# and $Global::NoAbsolute; push @$c, (split /\s*[\r\n]+__END__[\r\n]+\s*/, readfile($_)); } for($i = 0; $i < @$c; $i++) { if($c->[$i] =~ s/(^|\n)__NAME__\s+([^\n\r]+)\r?\n/$1/) { my $name = $2; $name =~ s/\s+$//; $ref->{$name} = $i; } } return $c; }
SecurePostURL — specify URL for secure POST requests
The directive specifies a catalog URL for secure (HTTPS) POST form submissions.
This allows an automatically different path for GET and POST
requests, presuming you use the process
tag as
form action=
target.
Example: Setting SecurePostURL
Put the following lines in catalog.cfg
:
VendURL http://myhost.mydomain.local/ SecureURL https://myhost.mydomain.local/ PostURL http://myhost.mydomain.local/cgi-bin/standard SecurePostURL https://myhost.mydomain.local/cgi-bin/standard
SecurePostURL
value can also be a relative path, with or
without the protocol and hostname specification.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4002 (context shows lines 4002-4006)
sub parse_url { my($var, $value) = @_; $value =~ s,/+$,,; $value; }
SecureURL — specify base URL of the Interchange catalog link program, when pages are served over HTTPS
The directive specifies a base catalog URL, that is, it's entry point (usually a cgi-bin link program), when pages are served over a secure connection (HTTPS).
Example: Setting SecureURL
Put the following lines in catalog.cfg
:
SecureURL https://myhost.mydomain.local/cgi-bin/ic/tutorial
SecureURL
value can also be a relative path, with or without the
protocol and hostname specification.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4002 (context shows lines 4002-4006)
sub parse_url { my($var, $value) = @_; $value =~ s,/+$,,; $value; }
SendMailProgram — sendmail (or compatible) binary location
It is not required to specifically use the original sendmail with this directive. Probably all available sendmail replacements include the sendmail binary of their own, but which is completely compatible with the original implementation (regarding command line options).
If this directive is not defined (and none of the defaults are available at startup), it won't be possible to send any e-mails using standard Interchange facilities. In that case, you'll have to pick orders from a tracking file, logs, or some other means.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 436 (context shows lines 426-432)
['SendMailProgram', 'executable', [ $Global::SendMailLocation, '/usr/sbin/sendmail', '/usr/lib/sendmail', 'Net::SMTP', ] ],
Source: lib/Vend/Config.pm
Line 4057 (context shows lines 4057-4113)
sub parse_executable { my($var, $initial) = @_; my($x); my(@tries); if(ref $initial) { @tries = @$initial; } else { @tries = $initial; } TRYEXE: foreach my $value (@tries) { #::logDebug("trying $value for $var"); my $root = $value; $root =~ s/\s.*//; return $value if $Global::Windows; if( ! defined $value or $value eq '') { $x = ''; } elsif( $value eq 'none') { $x = 'none'; last; } elsif( $value =~ /^\w+::[:\w]+\w$/) { ## Perl module like Net::SMTP eval { eval "require $value"; die if $@; $x = $value; }; last if $x; } elsif ($root =~ m#^/# and -x $root) { $x = $value; last; } else { my @path = split /:/, $ENV{PATH}; for (@path) { next unless -x "$_/$root"; $x = $value; last TRYEXE; } } } config_error( errmsg( "Can't find executable (%s) for the %s directive\n", join('|', @tries), $var, ) ) unless defined $x; #::logDebug("$var=$x"); return $x; }
SeparateItems — treat items with quantity greater than 1 as separate items
The SeparateItems
directive changes the default behavior when ordering
item in quantity greater of 1. Instead of only increasing quantity information,
the items are treated as being separate and are listed just as different
products would be (one per line).
The directive is of little global use, but it allows item attributes to be easily set for different instances of the same part number (SKU), such as color or size.
The value can be overridden with both scratch and value
variable mv_separate_items
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
SessionCookieSecure
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
SessionDatabase — specify location of the file-based user sessions database
The SessionDatabase
directive defines the location
of the file-based user sessions database, and the path may be absolute.
For DBM sessions, an appropriate .db
or
.gdbm
suffix will be appended. For the default
file-based sessions, the directive specifies the name of a base
sessions directory.
It is possible for multiple catalogs to share the same session file, as well as for multiple Interchange servers to serve the same catalogs. If serving an extremely busy store, multiple parallel Interchange servers can share the same (NFS-based) file system, and serve users in a "ping-pong" fashion using file-based sessions. On huge systems, even the level of directory hashing may be changed to increase file look-up speeds. By default, only 48 * 48 hashing is done.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3975 (context shows lines 3975-3989)
sub parse_relative_dir { my($var, $value) = @_; if (absolute_or_relative($value)) { config_error('Path %s not allowed in %s directive', $value, $var); } $C->{Source}{$var} = $value; $value = "$C->{VendRoot}/$value" unless file_name_is_absolute($value); $value =~ s./+$..; $value; }
SessionExpire — specify a duration after which idle user sessions expire
Website visitors can close their browser or move to browsing other sites
without making the Web server aware of the fact.
This is a potential problem as new sessions would keep getting created,
but they'd never be removed, wasting system resources.
The way we can detect "closed" sessions is by measuring time
between user requests. We can expire sessions where no activity was
registered for more than the specified interval.
SessionExpire
specifies the maximum amount of time for which the
session information is preserved between two consecutive user requests.
If CookieLogin
is enabled, SessionExpire
can be a small value.
If the customer's browser has the Interchange session cookie stored, he or she will
be automatically logged back in with the next request. Note, however, that
the customer's cart and session values will be reset.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4115 (context shows lines 4115-4127)
sub parse_time { my($var, $value) = @_; my($n); return $value unless $value; # $C->{Source}->{$var} = [$value]; $n = time_to_seconds($value); config_error("Bad time format ('$value') in the $var directive\n") unless defined $n; $n; }
SessionHashLength — specify the number of characters to hash session directories
This directive combiles with SessionHashLevels to configure the number of levels and hash length for the directory structure of file-based sessions. Default is 1. This solves the problem of session IDs passed from CGI::Session or other modules that use a quasi-sequential session ID. You end up placing all sessions in the S/2 directory for a long time, followed by the S/3 directory, etc. A setting of: SessionHashLength 4 SessionHashLevels 1 would break sessions up into separate directories instead of putting all sessions in a huge directory.
Example: Setting SessionExpire
Put the following in catalog.cfg
:
SessionHashLength 4 SessionHashLevels 1
The default value of 1, combined with SessionHashLevels of 2, creates a directory structure like:
4 +----w 6 +----r D +----9 +----R r +----z s +----s X +----s z +----3
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
SessionHashLevels — specify the number of levels to hash session directories
This directive combiles with SessionHashLength to configure the number of levels and hash length for the directory structure of file-based sessions. Default is 1. This solves the problem of session IDs passed from CGI::Session or other modules that use a quasi-sequential session ID. You end up placing all sessions in the S/2 directory for a long time, followed by the S/3 directory, etc. A setting of: SessionHashLength 4 SessionHashLevels 1 would break sessions up into separate directories instead of putting all sessions in a huge directory.
Example: Setting SessionExpire
Put the following in catalog.cfg
:
SessionHashLevels 1 SessionHashLength 4
The default value of 2, combined with SessionHashLength of 1, creates a directory structure like:
4 +----w 6 +----r D +----9 +----R r +----z s +----s X +----s z +----3
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
SessionLockFile — specify the name of a lock file if DBM-based sessions are used
It is possible for multiple catalogs to share the same session file.
SessionDatabase
needs to be set appropriately if the database is
to be shared. This is only used with DBM-based sessions, and
the pathname can be absolute if desired.
SessionType — specify type of the user sessions database
The directive specifies the type of the user sessions database.
If you are planning on running Interchange servers with an NFS-mounted
filesystem as the session target, you must set SessionType
to
NFS
. The other requisites with NFS are usually
fcntl
supported in Perl,
a lock daemon running on NFS server system and
a lock daemon running on Interchange server.
SetGroup — specify primary Unix group to switch to, after catalog to invoke is determined
By default, the Interchange server and the individual catalogs it serves run under the same Unix user ID and user group (UID and GID).
This directive allows you to switch group at the catalog level.
To be able to switch group with SetGroup
, the Interchange user must
be a member of the target group.
On Linux, the number of secondary groups per user is 32, which means
you can serve a maximum of 31 catalogs using SetGroup
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4042 (context shows lines 4042-4055)
sub parse_valid_group { my($var, $value) = @_; return '' unless $value; my($name,$passwd,$gid,$members) = getgrnam($value); config_error("$var: Group name '$value' is not a valid group\n") unless defined $gid; $name = getpwuid($<); config_error("$var: Interchange user '$name' not in group '$value'\n") unless $members =~ /\b$name\b/; $gid; }
Shipping
Example:
Shipping Postal default_geo 45056 Shipping QueryUPS default_geo 45056 Shipping default dir products/ship
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3071 (context shows lines 3071-3135)
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 Vend::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; }
ShowTimes — insert timing information in debug output
The ShowTimes
directive makes Interchange include timing statistics
in debug output.
Debug output has to be enabled for this option to work
(see DEBUG
and DebugFile
).
Calls to the show_times()
function are commented out
in most of the Interchange source. To enable ShowTimes
, you also need to
search for occurrences of ShowTimes
in the actual source,
and un-comment the appropriate lines, then restart Interchange of course. You can
effectively search the source by executing
grep -r ShowTimes * within ICROOT.
Lines you're interested for will look like this:
lib/Vend/Server.pm:#show_times("begin response send") if $Global::ShowTimes;
and you will need to remove the "#
".
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
SocketFile — specify Unix socket filename
The directive specifies the filename which Interchange should create to enable Unix-domain socket communication. The filename must be writable by the Interchange daemon.
You would use SocketFile
in combination with the
vlink
link program.
The MINIVEND_SOCKET
environment variable
is not honored by Interchange, contrary to
what you can read in older Interchange documentation.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3934 (context shows lines 3934-3950)
sub parse_root_dir_array { my($var, $value) = @_; return [] unless $value; no strict 'refs'; my $c = ${"Global::$var"} || []; my @dirs = grep /\S/, Text::ParseWords::shellwords($value); foreach my $dir (@dirs) { $dir = "$Global::VendRoot/$dir" unless file_name_is_absolute($dir); $dir =~ s./+$..; push @$c, $dir; } return $c; }
SocketPerms — specify Unix socket permissions
Specify permissions (mode) for the Interchange UNIX-domain socket file.
Prepend a starting 0
to indicate an octal value. The
directive can be overridden from the command line using interchange
-r SocketPerms=
.
value
The default value is 0600
, which allows only programs
running under your Interchange server UID to access the socket.
Another possible value is 0666
. This is a bit
insecure setting, as it allows anyone on the system to access the socket.
It may come handy, however, if programs such as Apache need to access
the socket via mod_perl or our Interchange::Link
module.
You might want to try the discussed mode, 0666
,
when your Interchange installation isn't working and you quickly want to find out
whether it's just socket file permissions problem or something deeper.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
SocketReadTimeout — specify timeout on client sockets
The SocketReadTimeout
directive specifies the amount of time
Interchange will wait for data on client sockets.
The default is one second, which is the same as the previous unconfigurable value.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
SourceCookie
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 731
['SourceCookie', sub { &parse_ordered_attributes(@_, [qw(name expire \ domain path secure)]) }, '' ],
SourcePriority — specify list of CGI variables to check for source (affiliate) name
The directive specifies a prioritized list of CGI variables to check when looking for the source (affiliate) name. The first name found is used.
The directive also accepts the following special values:
mv_pc
— try reading affiliate name from the existing
mv_pc
variable, but don't interfere with mv_pc
's special values
(value "RESET
" or values containing only digits).
cookie-
— check the
cookie with label NAME
NAME
.
session
— stop processing if a session for
a visitor already exists.
This setting is useful for sending affiliate traffic to other sites but
preventing them from getting credit for sales made by customers following
their banner back to your site.
session-
— stop
processing if
NAME
NAME
session variable is set.
Example: Read affiliate name from "mv_pc", CGI variable and cookie
SourcePriority mv_pc mv_source cookie-MV_SOURCE
Example: Ignore source name for visitors returning back to your site
Use "session
" to prevent affiliate sites from getting
credit for sales when a customer follows a banner back to your site:
SourcePriority session mv_pc mv_source
Example: Special treatment for affiliates using variable "specialsource"
Make affiliates who use CGI variable specialsource
instead of mv_source
get special treatment by
overriding the "sessions
" check:
SourcePriority specialsource session mv_pc mv_source
Example: Setting SourcePriority
Allow affiliates to get credit from redirecting customers back to your site (there is already a session), but only if no other affiliate is already set:
SourcePriority session-source mv_pc mv_source
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3838 (context shows lines 3838-3851)
sub parse_array_complete { my($item,$settings) = @_; return '' unless $settings; my(@setting) = grep /\S/, split /[\s,]+/, $settings; my $c = []; for (@setting) { check_legal($item, $_); push @{$c}, $_; } $c; }
SpecialPage — specify location of special pages
Specify custom values for Interchange special pages.
Valid types are:
badsearch
—
Defaults to badsearch
, displayed if search initialization failed.
canceled
—
default page for the cancel
form action.
catalog
—
Defaults to .
failed
—
Standard handler for failed orders.
flypage
—
Defaults to flypage
.
interact
—
Called on various errors, including missing FormAction
s. Defaults to interact
.
missing
—
Defaults to missing
.
needfield
—
Defaults to .
order
—
Defaults to ord/basket
.
put_handler
—
Standard handler for PUT
operations.
receipt
—
Default page displayed as order receipt.
results
—
Defaults to results
.
salestax.asc
—
Defaults to salestax.asc
.
search
—
Defaults to results
.
shipping.asc
—
Defaults to shipping.asc
.
violation
—
Defaults to .
Example: Setting SpecialPage
SpecialPage catalog index SpecialPage violation special/violation SpecialPage put_handler admin_publish SpecialPage receipt ../etc/receipt SpecialPage badsearch special/badsearch SpecialPage catalog test SpecialPage canceled special/canceled SpecialPage failed special/failed SpecialPage interact special/interact SpecialPage missing special/missing SpecialPage needfield special/needfield SpecialPage order ord/basket SpecialPage search results SpecialPage violation special/violation
Example: Setting SpecialPage
SpecialPage catalog index SpecialPage target index SpecialPage missing not_found SpecialPage violation not_found SpecialPage order cart
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 573
['SpecialPage', 'special', 'order ord/basket results results search results flypage flypage'],
Source: lib/Vend/Config.pm
Line 3168 (context shows lines 3168-3180)
sub parse_special { my($item,$settings) = @_; return {} unless $settings; my(%setting) = grep /\S/, split /[\s,]+/, $settings; for (keys %setting) { if($Global::NoAbsolute and file_name_is_absolute($setting{$_}) ) { config_warn("Absolute file name not allowed: %s", $setting{$_}); next; } $C->{$item}{$_} = $setting{$_}; } return $C->{$item}; }
SpecialPageDir — specify directory containing special catalog pages
Specify the directory containing special catalog pages.
The default is special_pages
.
This directive can be set in locale settings to allow different page sets for different locales.
SpecialSub — specify Perl subroutines to handle certain events or conditions
The directive specifies Perl subroutines that should be called to handle certain events. The available events are described below.
request_init
)Event triggered on every request, right after catalog selection and before session assignment.
admin_init
)Event triggered on every request for users with administrator privileges, request, after initialization of embedded Perl objects. This allows catalog subroutines to be specified as request handlers and have properly initialized session variables by the time they run.
debug_qualify
)
Event triggered to determine whether debug mode should be
enabled for the incoming client connection. Have in mind that simple,
host-based decision can be made by using the DebugHost
configuration directive. The debug_qualify
specialSub is invoked only if DebugHost
is either undefined,
or the client host is found in the DebugHost
list.
See debug glossary entry for a complete discussion.
guess_cc_type
)
Event triggered at the time
of deriving credit card type, MV_CREDIT_CARD_TYPE
.
Interchange already recognizes
major credit card types but local areas might require you to
write custom recognition code.
The subroutine is called with the credit card number.
A true return value should contain the recognized credit card
type name.
A false value indicates that the number recognition did not
succeed, and that Interchange should proceed with its built-in detection
algorithm.
init_session
)Event triggered at new session creation time. The subroutine is called with the pointer to the newly created session variables space. Subroutine return value is not used.
lockout
)
Event triggered for locking out a bad web spider or misbehaving
client (see RobotLimit
). The subroutine is called without
parameters and is expected to perform all the necessary custom
steps. It should exit with an appropriate return value to signal
how the rest of the process should be handled.
A true return value indicates that no more handling is
needed. A false value indicates that Interchange should continue
and execute the default, built-in action lockout action, which
is specified by the LockoutCommand
config directive.
missing
)Event triggered when a requested Interchange page is missing. The subroutine is called with the name of the missing page and is expected to perform all the necessary custom handling. It should exit with an appropriate return value to signal how the rest of the process should be handled.
A true return
value will indicates that all actions (including the response to the client)
have been performed by your function and no more handling is needed.
You can also return an array, (1, PAGENAME
), where
PAGENAME
is the page to be displayed to the user.
A false return value indicates that Interchange should continue
and execute the default, built-in action, which
is displaying a page specified by "SpecialPage
missing
".
order_missing
)Event triggered when a missing product is been added to the shopping cart.
A true return value will suppress the log message about this event.
shipping_callout
)Event is triggered after shipping calculation, but before result is formatted and returned.
It's useful for the type of customization that would require modifying too many shipping table entries or using entirely custom shipping code, because it allows you to build on the powerful shipping features interchange already has.
weight_callout
)Event is triggered after weight is processed for shipping calculation.
The subroutine is called with the weight as parameter and expects the modified weight as return value.
It does not affect other calculations, such as done by the weight
usertag.
Example: Defining "SpecialSub missing"
In the event of a missing page, see if the "page name" could be understood as
"
". If it could, use the provided information to construct
the search specification and invoke the search results page.
(More about Interchange search facilities can be read in Interchange Guides: Search Tutorial).
If it couldn't, return a false value and proceed to display
"product group
/category
SpecialPage
missing
".
Put the following in catalog.cfg
:
SpecialSub missing check_category Sub check_category <<EOS sub { my ($name) = @_; return unless $name =~ m{^[A-Z]}; $name =~ s,_, ,g; my ($prod_group, $category) = split m{/}, $name; $CGI->{co} = 1; $CGI->{fi} = 'products'; $CGI->{st} = 'db'; $CGI->{sf} = join "\0", 'prod_group', 'category'; $CGI->{op} = join "\0", 'eq', 'eq'; $CGI->{se} = join "\0", $prod_group, $category; $CGI->{sp} = 'results'; $CGI->{mv_todo} = 'search'; $Tag->update('process'); return (1, 'results'); } EOS
Example: Defining SpecialSub init_session
If a client is coming from a "blacklisted" IP address, define variable "blacklist" in its session.
At a later stage, "blacklisted" sessions could be prevented from checking out and finalizing the order, as they are likely to be fraudulent.
SpecialSub init_session check_blacklist Sub check_blacklist <<EOS sub { my ($session) = @_; if ( grep { $CGI::remote_addr } @blacklisted_IPs ) { $session->{blacklist} = 1; } return; } EOS
Example: Defining SpecialSub guess_cc_type
If the credit card number starts with "41
",
recognize it as type "LOCAL_TYPE
". Otherwise,
return a false value and implicitly instruct Interchange to continue with
the built-in credit card type detection mechanism.
Put the following in catalog.cfg
:
SpecialSub guess_cc_type check_cc Sub check_cc <<EOS sub { my $num = shift; return 'LOCAL_TYPE' if $num =~ /^41/; return; } EOS
Example: Defining SpecialSub admin_init
Put the following in catalog.cfg
:
SpecialSub admin_init on_admin_init Sub on_admin_init <<EOS sub { unless ($Session->{username} eq 'foundation') { $Variable->{MV_MENU_DIRECTORY} = 'include/foundation/menus'; } } EOS
Example: Shipping discount for dealers with SpecialSub shipping_callout
Sub custom_shipping <<EOS sub { my ($final, $mode, $opt, $o) = @_; $final *= .90 if $Scratch->{dealer} and $mode =~ /UPS/i; return $final; } EOS SpecialSub shipping_callout custom_shipping
Example: Adjusting shipping weight with SpecialSub weight_callout
Sub custom_weight <<EOS sub { my ($normal_weight) = @_; my $new_weight = 0; for my $item (@$Items) { $new_weight += $item->{weight} * $item->{quantity} unless $item->{is_free_shipping}; } return $new_weight; } EOS SpecialSub weight_callout custom_weight
If the examples above, the Perl subroutines have been defined on a
catalog level, using Sub
configuration directive.
Interchange catalogs (and everything configured within them) are subject to
safe restrictions, so your Sub
blocks might have
insufficient permissions to execute all of your commands. To solve that
problem, either relax the restrictions by using SafeUntrap
,
or define the subroutines at the global level (in interchange.cfg
) using
unrestricted GlobalSub
s.
As a misnomer, SpecialSub catalog_init
was
renamed to request_init
in Interchange 5.5.2.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
StartServers — specify the number of Interchange servers to prefork when running in PreFork mode
The directive specifies the number of Interchange servers that should be
preforked when Interchange is run in PreFork
mode.
For an introduction to Interchange run modes and practical implications, please see the ic run mode glossary entry.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3992 (context shows lines 3992-3999)
sub parse_integer { my($var, $value) = @_; $value = hex($value) if $value =~ /^0x[\dA-Fa-f]+$/; $value = oct($value) if $value =~ /^0[0-7]+$/; config_error("The $var directive (now set to '$value') must be an integer\n") unless $value =~ /^\d+$/; $value; }
StaticDir — (obsolete) specify path of the directory which should be used as root for static pages
Sub — define Perl functions for use within a catalog
Define a catalog subroutine for use within perl
, mvasp
, or
embedded Perl languages.
The use of "here document" syntax in Interchange makes subroutine definitions visually convenient.
Example: Defining a subroutine
Sub <<EOF sub sort_cart_by_quantity { my($items) = @_; $items = $Items if ! $items; my $out = '<table border="1">'; @$items = sort { $a->{quantity} <=> $b->{quantity} } @$items; foreach $item (@$items) { my $code = $item->{code}; $out .= '<tr><td>'; $out .= $code; $out .= '</td><td>'; $out .= $Tag->data('products', 'name', $code); $out .= '</td><td>'; $out .= $Tag->data('products', 'price', $code); $out .= '</td></tr>'; } $out .= '</table>'; return $out; } EOF
The above code would be called from an Interchange page in the following way:
Items, sorted by quantity: [perl tables=products subs='sort_cart_by_quantity'] my $cart = $Carts->{main}; return sort_cart_by_quantity($cart); [/perl]
As with Perl "here documents," the "EOF
" (or arbitrarily
named end marker) must be the only thing on the line,
without leading or trailing white space. Do not append a semicolon to the
marker (as you would in Perl).
Catalog subroutines may not perform unsafe operations. The
Safe
module enforces this unless global operations are allowed for the
catalog. See safe glossary entry for more information.
SubCatalog — register subcatalog with the Interchange server
The directive allows definition of "subcatalogs" — catalogs that
share most of the characteristics of
another, "base" catalog.
In a SubCatalog
setup, the appropriate catalog.cfg
should only contain
directives that differ from definitions in the base catalog's catalog.cfg
.
Interchange's subcatalogs feature isn't used much, but primary reasons for its use would be memory savings, or some kind of chained-configuration catalogs.
Concerning the directive arguments, subcatalog_name
and
base_catalog_name
are the names of the new and existing
catalog respectively. catalog_directory
(CATROOT)
defines the catalog root directory, and can be the same for both the master-
and sub-catalog. Finally, the link program is a webserver path by
which the subcatalog can be accessed.
Example: Registering a sub catalog
Catalog simple /home/catalogs/simple /cgi-bin/ic/simple SubCatalog subsimple simple /home/catalogs/simple /cgi-bin/ic/subsimple
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4147 (context shows lines 4147-4248)
sub parse_catalog { my ($var, $setting) = @_; my $num = ! defined $Global::Catalog ? 0 : $Global::Catalog; return $num unless (defined $setting && $setting); my($name,$base,$dir,$script, @rest); ($name,@rest) = Text::ParseWords::shellwords($setting); my %remap = qw/ base base alias alias aliases alias directory dir dir dir script script directive directive fullurl full_url full full_url /; my ($cat, $key, $value); if ($Global::Catalog{$name}) { # already defined $cat = $Global::Catalog{$name}; $key = shift @rest; $value = shift @rest; } elsif( $var =~ /subcatalog/i and @rest > 2 and file_name_is_absolute($rest[1]) ) { $cat = { name => $name, base => $rest[0], dir => $rest[1], script => $rest[2], }; splice(@rest, 0, 3); $cat->{alias} = [ @rest ] if @rest; } elsif( file_name_is_absolute($rest[0]) ) { $cat = { name => $name, dir => $rest[0], script => $rest[1], }; splice(@rest, 0, 2); $cat->{alias} = [ @rest ] if @rest; } else { $key = shift @rest; $value = shift @rest; $cat = { name => $name }; } $key = $remap{$key} if $key && defined $remap{$key}; if(! $key) { # Nada } elsif($key eq 'alias' or $key eq 'server') { $cat->{$key} = [] if ! $cat->{$key}; push @{$cat->{$key}}, $value; push @{$cat->{$key}}, @rest if @rest; } elsif($key eq 'global') { $cat->{$key} = $Global::AllowGlobal->{$name} = is_yes($value); } elsif($key eq 'directive') { no strict 'refs'; my $p = $value; my $v = join " ", @rest; $cat->{$key} = {} if ! $cat->{$key}; my $ref = set_directive($p, $v, 1); if(ref $ref->[1] =~ /HASH/) { if(! $cat->{$key}{$ref->[0]} ) { $cat->{$key}{$ref->[0]} = { %{"Global::$ref->[0]"} }; } for (keys %{$ref->[1]}) { $cat->{$key}{$ref->[0]}{$_} = $ref->[1]->{$_}; } } else { $cat->{$key}{$ref->[0]} = $ref->[1]; } } else { $cat->{$key} = $value; } #::logDebug ("parsing catalog $name = " . uneval_it($cat)); $Global::Catalog{$name} = $cat; # Define the main script name and array of aliases return ++$num; }
Suggest — check existence of a capability
Just like Require
or Capability
, this directive checks for
a feature or capability. When the tested feature is missing, a
warning message is shown.
"Capabilities" you can suggest are:
globalsub
— existence of a GlobalSub
sub
— existence of a Sub
taggroup
— existence of a TagGroup
usertag
— existence of a UserTag
module (or perlmodule)
— existence of a Perl module. Optional additional argument is the custom Perl module path.
include (or perlinclude)
— prepend specified path to Perl's @INC
include path (makes most sense with Require
, not with Suggest
or Capability
even though it can be called that way for equivalent effect)
file
— existence of a readable file
executable
— existence of an executable file
Example: Suggesting existence of all supported items
Suggest globalsub my_global_sub Suggest sub my_sub Suggest taggroup :group1,:group2 :group3 Suggest usertag my_global_usertag Suggest usertag my_catalog_usertag Suggest module Archive::Zip Suggest module Set::Crontab /usr/local/perl/modules/ Suggest file /etc/syslog.conf Suggest file relative-dir/file Suggest executable /usr/local/bin/gfont Suggest executable bin/gfont
Example: Testing for features
Suggest module Archive::Zip Suggest usertag table_editor Suggest globalsub file_info Suggest module Business::UPS
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2686 (context shows lines 2686-2688)
sub parse_suggest { return parse_require(@_, 1); }
SuppressCachedCookies
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
SysLog — instruct Interchange to log to Unix system's log (syslog)
The directive configures syslog(8) logging for Interchange.
Besides just tuning syslog facility and priority settings, it is also possible to specify external command to invoke for sending syslog messages. This also means it is possible to hook into the message logging system and route messages where ever you want. For example, a custom wrapper can be created to log to a database. See an example of it in the section called “EXAMPLES”.
Example: Simple syslog setup
SysLog command /usr/bin/logger SysLog tag int1 SysLog alert local3.warn SysLog warn local3.info SysLog info local3.info SysLog debug local3.debug
The above would cause messages to be logged with the command
/usr/bin/logger -t int1 -p local3.alert ...
.
The generated system log entries would look somewhat like the following:
Oct 26 17:30:11 bill int1: Config 'co' at server startup Oct 26 17:30:11 bill int1: Config 'homefn' at server startup Oct 26 17:30:11 bill int1: Config 'simple' at server startup Oct 26 17:30:11 bill int1: Config 'test' at server startup Oct 26 17:30:13 bill int1: START server (2345) (INET and UNIX)
Example: Sending facility 'local3' messages to appropriate log file
As you might know, messages sent using syslog reach the syslog daemon
sooner or later. There, they are examined and "routed" to their final
destination. For BSD-compatible syslog daemons, the configuration
file is probably /etc/syslog.conf
, and the
configuration snippet needed to route Interchange messages to
/var/log/interchange.log
is as follows:
# Log local3 stuff to Interchange log local3.* /var/log/interchange.log
Example: Custom logging script for logging to a database
#!/usr/bin/perl my $script_name = "logdatabase"; use DBI; use Getopt::Std; getopts('d:p:T:k:') or die "$script_name options: $@\n"; use vars qw/$opt_d $opt_p $opt_T $opt_k/; my $dsn = $opt_d || $ENV{DBI_DSN}; my $template = $opt_T || "insert into log values ('~~KEY~~', '~~LEVEL~~', '~~MSG~~')"; my $dbh = DBI->connect($dsn) or die "$script_name cannot connect to DBI: $DBI::errstr\n"; my %data; $data{KEY} = $opt_k || ''; local ($/); $data{MSG} = <>; $data{LEVEL} = $opt_p || 'interchange.info'; $template =~ s/\~\~(\w+)\~\~/$dbh->quote($data{$1})/; my $sth = $dbh->prepare($template) or die "$script_name error executing query: $template\n"; $sth->execute() or die "$script_name error executing query: $template\n"; exit;
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
TableRestrict — restrict database searches to rows satisfying given criteria
The directive is used to emulate database "views" in database-based searches.
For each database search, additional "filtering" will be performed
and only rows satisfying given condition will be returned. Commonly,
you will want to use something like owner=username
, to
restrict searches to just rows that the corresponding users "own".
Example: Restricting database searches to username
The following would prevent database searches from returning any records,
except those where the column owner
contains the current value of [data session username]
.
TableRestrict products owner=username
As you can see from the ad-hoc example above, owner
is a
database column name, and username
is the key
from the session database. (The user's [data session username]
must match the value of the owner field
if a record is to be returned in a search operation).
Example: Restricting edit to owned fields
TableRestrict
is also useful in embedded Perl code:
[calc] # Restrict edit to owned fields $Config->{TableRestrict}{products} = 'owner=username'; return; [/calc]
(Note that the above example works because value of the TableRestrict
config directive is overridden only for the duration of the current page —
for next page or access, TableRestrict
will again have the original
value).
Example: Searching using SQL
When using SQL-based database searches, the owner=username
directive in effect turns the base search query of say,
SELECT * FROM products
into
SELECT * FROM products WHERE owner = '[data session username]'
TableRestrict
does not affect the text searches.
The directive may be useful in "mall" situations, where user is allowed to only see products from the current store ID.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
TagDir — specify directories containing code declaration blocks
Specify directories containing tag, filter, widget, actionmap and other code declarations.
For more information on possible code declarations, see
ITL and filter glossary entries and the CodeDef
configuration directive.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3934 (context shows lines 3934-3950)
sub parse_root_dir_array { my($var, $value) = @_; return [] unless $value; no strict 'refs'; my $c = ${"Global::$var"} || []; my @dirs = grep /\S/, Text::ParseWords::shellwords($value); foreach my $dir (@dirs) { $dir = "$Global::VendRoot/$dir" unless file_name_is_absolute($dir); $dir =~ s./+$..; push @$c, $dir; } return $c; }
TagGroup — group Interchange code declarations in groups, for later convenient inclusion or exclusion from the setup
The directive groups symbols (usually depending on their type) under group names. This allows for very convenient inclusion or exclusion of whole tag groups from the Interchange server.
Example: Defining TagGroup
TagGroup :file "counter file include log value_extended" Require taggroup :file
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2592 (context shows lines 2592-2623)
sub parse_tag_group { my ($var, $setting) = @_; my $c; if(defined $C) { $c = $C->{$var} || {}; } else { no strict 'refs'; $c = ${"Global::$var"} || {}; } $setting =~ tr/-/_/; $setting =~ s/[,\s]+/ /g; $setting =~ s/^\s+//; $setting =~ s/\s+$//; my @pairs = Text::ParseWords::shellwords($setting); while(@pairs) { my ($group, $sets) = splice @pairs, 0, 2; my @sets = grep $_, split /\s+/, $sets; my @groups = grep /:/, @sets; @sets = grep $_ !~ /:/, @sets; for(@groups) { next unless $c->{$_}; push @sets, @{$c->{$_}}; } $c->{$group} = \@sets; } return $c; }
TagInclude — include (a group of) tags in Interchange
Include a set of tags for compilation and use under the Interchange server.
TagDir
s are scanned for files, then they're assigned to groups
according to TagGroup
directives, and finally they're included
using TagInclude
.
The syntax supports the use of !
to exclude items,
and keyword ALL
. Tag group names should be prefixed
with :
. See the section called “EXAMPLES”.
Example: Defining TagInclude
The following would include all tags, except those in group
crufty
and tag get-url
specifically.
TagInclude ALL !:crufty !get_url
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2626 (context shows lines 2626-2684)
sub parse_tag_include { my ($var, $setting) = @_; my $c; my $g; my $mapper = $incmap{$var} || 'TagGroup'; if(defined $C) { $c = $C->{$var} || {}; $g = $C->{$mapper} || {}; } else { no strict 'refs'; $c = ${"Global::$var"} || {}; $g = ${"Global::$mapper"} || {}; } $setting =~ s/"/ /g; $setting =~ s/^\s+//; $setting =~ s/\s+$//; $setting =~ s/[,\s]+/ /g; if($setting eq 'ALL') { return { ALL => 1 }; } delete $c->{ALL}; get_system_groups() unless $SystemGroupsDone; my @incs = Text::ParseWords::shellwords($setting); for(@incs) { my @things; my $not = 0; if(/:/) { $not = 1 if s/^!//; if(! $g->{$_}) { config_warn( "unknown %s %s included from %s", $mapper, $_, $var, ); } else { @things = @{$g->{$_}} } } else { @things = ($_); } for(@things) { my $not = s/^!// ? ! $not : $not; $c->{$_} = not $not; } } return $c; }
TaxInclusive — display prices with tax amount included
Display product prices with tax amount included (instead of calculating and displaying tax amount separately). This is common in European countries.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
TaxShipping
TcpHost — specify which hosts can connect to Interchange server running in Inet mode
The TcpHost
directive defines a list of hostnames whose
connections to the Interchange Inet socket will be accepted.
This effectively allows or denies access to all catalogs running on the
corresponding Interchange server.
It's important to note that the directive does not support wildcards or anything, it only accepts plain list of space-separated IPs or hostnames.
TcpMap — specify which ports should Interchange server running in Inet mode listen on
The TcpMap
directive defines a list of host addresses and ports that
the Interchange server should listen on (when running in Inet mode using
tlink
link program, of course).
In the past, Interchange had its own built-in Web server which also allowed for binding of specific catalogs to specific ports. Since this built-in server is long gone now, its behavior was replaced by a combination of aliases on the real Web server and Interchange catalog definitions. See the section called “EXAMPLES” for clarification.
By default, Interchange listens on all IP addresses, on port 7786
.
The port number comes from the ASCII values of letters M
and
V
, which stood for "MiniVend
"
(see Interchange
About and History page for more background information).
host_and_port_specification
defines hostnames and
ports to bind to. Self-explanatory examples include 7786
,
*:7786
, 127.0.0.1:7786
or
myhost.mydomain.local:7786
.
catalog_specification
is the name of the catalog to
offer on selected hostname and port. Since there is no more built-in
Web server in Interchange, the only sensible definition is "-
".
Example: Defining TcpMap
The following makes Interchange listen on three ports.
TcpMap 7786 - 7787 - 7788 -
Example: Mass-defining TcpMap
To define a large number of ports, the "here document" capability of Interchange configuration engine can be used:
TcpMap <<EOD *:7786 - 127.0.0.1:7787 - myhost.mydomain.local:7788 - *:7789 - EOD
Example: Offering specific catalogs on specific ports
Even though the internal Web server in Interchange is gone,
tlink
(Inet link program) still relies only on
the SCRIPT_PATH
environment variable to determine which
catalog was requested. This means that the
functional equivalent of catalogs bound to ports can still be achieved (without
TcpMap
),
by the use of Web server location aliases and Interchange script path aliases.
Actually, you'd probably want to do this just to reduce the length of
HTML links.
Here's an example of needed Apache Web server configuration:
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ ScriptAlias /CATALOG_NAME /usr/lib/cgi-bin/ic/CATALOG_NAME <Directory "/usr/lib/cgi-bin"> AllowOverride None Options ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory>
And here's the appropriate catalog definition in interchange.cfg
:
Catalog CATALOG_NAME /PATH/TO/CATALOG/CATALOG_NAME /cgi-bin/ic/CATALOG_NAME /CATALOG_NAME
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
TemplateDir — specify common template/fallback "pages" directories
Specify directories containing default pages that are to be looked up if pages
are not found in the usual PageDir
. This effectively allows
keeping pages common for all catalogs in common directories,
or — in case
of a catalog directive — extending page
search outside the catalog's PageDir
.
Example: Setting TemplateDir to multiple directories
TemplateDir /usr/local/interchange/default_pages /common/pages
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3934 (context shows lines 3934-3950)
sub parse_root_dir_array { my($var, $value) = @_; return [] unless $value; no strict 'refs'; my $c = ${"Global::$var"} || []; my @dirs = grep /\S/, Text::ParseWords::shellwords($value); foreach my $dir (@dirs) { $dir = "$Global::VendRoot/$dir" unless file_name_is_absolute($dir); $dir =~ s./+$..; push @$c, $dir; } return $c; }
Source: lib/Vend/Config.pm
Line 3952 (context shows lines 3952-3973)
sub parse_dir_array { my($var, $value) = @_; return [] unless $value; $C->{$var} = [] unless $C->{$var}; my $c = $C->{$var} || []; my @dirs = grep /\S/, Text::ParseWords::shellwords($value); foreach my $dir (@dirs) { unless (allowed_file($dir)) { config_error('Path %s not allowed in %s directive', $dir, $var); } $dir = "$C->{VendRoot}/$dir" unless file_name_is_absolute($dir); $dir =~ s./+$..; push @$c, $dir; } return $c; }
TolerateGet — specify whether information from both GET and POST method should be parsed when form is submitted using POST method
Enabling the option makes Interchange parse both GET data and POST data when a POST form is submitted. Unfortunately this has to be a global setting because at URL parse time, the Interchange daemon doesn't yet know which catalog it is dealing with (due to catalog aliases, etc.).
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
TrackDateFormat — specify time format used in TrackFile logs
The TrackDateFormat
directive specifies the time format to be
used in TrackFile
logs.
The default format is %Y%m%d
. For a list of
accepted POSIX format specifiers, see the time glossary entry.
TrackFile — specify user tracking log filename
Specify the usertrack log file location.
User tracking can be used in back office administration to summarize traffic by affiliates or provide other statistics.
The Interchange daemon must have the permission to create and write to the specified file, of course.
TrackPageParam — insert specified variables' values in the user track file
Specify Interchange pages and CGI variables whose values should be inserted into user tracking file along with the visited page information.
Variable names and values are only printed if they are selected for output using this directive, and if they have really been directly passed onto the target page as CGI variables.
Example: Setting TrackPageParam
TrackFile logs/trackfile TrackPageParam index var1,var2 index2 var3,var4
The example will monitor values of the var1
and var2
CGI variables on page
index.html
, and
values of the var3
and var4
CGI variables on page
index2.html
.
To see it in practice, visit the index page of your catalog, append
&var1=TEST&var2=500
to its URL, and press enter
to visit the page with those CGI variables defined. You'll see
page accesses recorded in the user tracking file, along with the names
and values of the two variables. The log in the trackfile might look like this:
20050812 fft2VXwJ 127.0.0.1 1123868228 VIEWPAGE=index var1=TEST var2=500
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
TrustProxy — designate certain IP addresses or hostnames as trusted HTTP proxies
The directive
allows Interchange administrator to designate certain IP addresses or hostnames
as trusted HTTP proxies, whose claims (via the
HTTP_X_FORWARDED_FOR
environment variable set by the web server) about the original requesting
host will be assumed truthful and accurate.
For example, if you are using a front-end proxy for Interchange, all requests will
appear to come from the proxy address (say, 127.0.0.1
if
on the same machine). In turn, all clients will appear as having the same
source IP address (much like if you enabled WideOpen
). Under such
circumstances, user session hijacking becomes trivial enough that it can even
happen by accident (if, say, someone copies an URL that includes his/her
session cookie and gives it to others to visit — they all will end up
having the same user info and shopping cart!).
Having said the above, TrustProxy
takes a comma-separated list of
IP addresses and/or hostnames (globbing possible - see examples) that are
trusted proxies and whose value of HTTP_X_FORWARDED_FOR
should be used as request source instead of the actual IP directly.
"Globs" are *
and ?
. The
*
stands for any number of characters (including none), while
?
stands for 1 character exactly.
The directive could, in general, be also used with external, untrusted HTTP
proxies (which you can only hope aren't lying) by using a *
glob (see examples).
Note that the environment variables are not modified in any way; only
Interchange's idea of the remote host is altered, as you see with
[data session host]
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3859 (context shows lines 3859-3863)
sub parse_list_wildcard_full { my $value = get_wildcard_list(@_,1); return '' unless length($value); return qr/^($value)$/i; }
UTF8
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
Unix_Mode — specify whether Interchange server should open an UNIX socket
Specify whether the Interchange server should listen on an UNIX-domain socket.
This configuration directive can be overridden using
interchange -u
switch on the command line.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 424 (context shows lines 414-419)
['Unix_Mode', 'yesno', ( defined $Global::Inet_Mode || defined $Global::Unix_Mode ) ? ($Global::Unix_Mode || 0) : 'Yes'],
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
UnpackJSON
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
UpsZoneFile — specify file containing region-specific UPS zone information
Specify the file containing UPS zone information. It can be in the format distributed by UPS or can be in a tab-delimited format, with the three-letter zip prefix of the customer used to determine the zone.
The directive works according to the mv_shipmode
variable.
User database named the same as the value of mv_shipmode
must
be present, or the lookup will return zero.
Zone information and updated pricing from UPS must be obtained in order for this to work properly. The zone information is specific to a region!
UrlSepChar — specify default URL separator character
Specify URL separator character for Interchange-generated HTML links.
Only one character is allowed, and the only recommended ones are
the default &
, ;
or
:
.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3750 (context shows lines 3750-3772)
sub parse_url_sep_char { my($var,$val) = @_; $val =~ s/\s+//g; if($val =~ /[\w%]/) { config_error( errmsg("%s character value '%s' must not be word character or %%.", $var, $val) ); } elsif(length($val) > 1) { config_error( "%s character value '%s' longer than one character.", $var, $val, ); } elsif($val !~ /[&;:]/) { config_warn("%s character value '%s' not a recommended value.", $var, $val); } return $val; }
UseModifier — specify default attributes that can be attached to items
Specify item attributes (or modifiers) that can be be attached to items.
Some of the names are reserved for use by Interchange, and you must not use them
in modifier names. Namely, they include
item
,
group
,
quantity
,
free
,
free_message
,
code
and, of course,
all mv_
variables.
You can see a quick list of those "reserved" names by entering the Interchange
source tree and issuing grep -r 'item->{[^$]' * | less
.
Example: Simple and standalone UseModifier example
We first need to define UseModifier
in the catalog.cfg
file (and restart
Interchange afterwards):
UseModifier size,color
Then we need to add the appropriate columns — size and color — to the products database. Here's an example:
sku description price size color 50595 Standard T-Shirt 15 S=Small, M=Medium, L=Large*, XL=Extra Large red=Red, blue=Blue, white=White 50623 Winter Jacket 140 S=Small, M=Medium, L=Large, XL=Extra Large*, XXL=Extra Extra Large blue=Blue, white=White, black=Black 50198 Long-sleeved Cotton Shirt 45 M=Medium*, L=Large red=Red, blue=Blue, white=White, maroon=Maroon
(The entry signified with "*
" will be understood as the
default).
And now all we need to display item size options is call
[accessories
on an
Interchange page. Let's create a sample
attributes.html page:SKU
size]
<html> <body> <table cellpadding="5"> <tr> <th>Test #</th> <th>Description</th> <th>Price</th> <th>Modifiers</th> </tr> [loop search="ra=yes/fi=products"] <tr> <td>[loop-code]</td> <td> [page [loop-code]] [loop-field description] </a> </td> <td align="right">[loop-field price]</td> <td> [loop-accessories size] [loop-accessories color] </td> </tr> [/loop] </table> </body> </html>
I hope this completes a very simple but working example, and breaks the entry-barrier to the world of Interchange modifiers.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3780 (context shows lines 3780-3800)
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; }
UserControl — enable enhanced user database functions
The directive enables enhanced user database functions.
The default UserDB functions are programmed in the
Vend::UserDB
module. When this directive is
enabled, functions from Vend::UserControl
are used
instead.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
UserDB — adjust default behavior of Interchange user database functions
The directive sets parameters to adjust the behavior of Interchange's built-in user database functions.
Parameter | Explanation | Default |
---|---|---|
acl | Field name for the simple page access control | acl |
addr_field | Field name for the address book | address_book |
assign_username | Automatically assign username if not provided? | 0 |
bill_field | Field name for billing accounts | accounts |
captcha | ||
cart_field | Field name for carts storage | carts |
clear_cookie | List of cookies to clear on explicit logout, separated by space, a comma or null-character | None |
clear_session | Clear user session completely upon logout? | 0 |
counter | Counter filename for assign_username function
| etc/username.counter |
crypt | Encrypt passwords? | 1 |
database | Name of the user database | userdb |
db_acl | Field name for database access control | db_acl |
expire_field | Field name for account expiration data | expiration |
file_acl | Field name for file access control | file_acl |
force_lower | Force possibly upper-case database fields to lower case session variable names? | 0 |
ignore_case | Ignore case in usernames and passwords? | 0 |
indirect_login | Field name used as login field if different from the primary table key | None |
logfile | Filename to which successful and unsuccessful authentication messages should be sent | error.log |
md5 | Use MD5 for encryption algorithm instead of the standard (and aging) Unix crypt? | 0 |
no_get | Do not load values from the database into the user's values space at login time? | 0 |
no_login | Successfully perform login even if already logged in? | 0 |
outboard_key_col | Field name providing key for outboard tables | None |
outboard | List of fields that live in another table | None |
pass_field | Field name for password | password |
passminlen | Minimum password length | 2 |
postlogin_action | Macro to run after the user is logged in | None |
pref_field | Field name for preferences | preferences |
scratch | List of UserDB fields to load into scratch space, instead of the default values space | None |
secure_cookies | Forces the MV_PASSWORD cookie to be set secure | 1, if using https |
sql_counter | SQL counter spec (sequence or AUTO_INCREMENT ) for assign_username function
| |
super_field | Field name that, when set to 1 , indicates account's superuser status
| super |
time_field | Field name for storing last login time | time |
unix_time | In log files, use seconds since Unix epoch instead of human-readable time? | 0 |
userminlen | Minimum username length | 2 |
username_email | ||
username_mask | Regular expression that usernames must not match in order to be allowed | None |
validchars | Character classes that usernames must match in order to be allowed | -A-Za-z0-9_@. |
Example: Minimum lengths
Set minimum lengths in characters for username and password.
UserDB default userminlen 8 UserDB default passminlen 6
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3071 (context shows lines 3071-3135)
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 Vend::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; }
UserDatabase — specify name of table to use as user database
Specify name of the user database.
The default user database name is "userdb
" and rarely
needs to be changed.
UserTag — define an Interchange tag
Catalog-based usertag will run under safe restrictions,
and will only be accessible only from the corresponding catalog.
Global UserTag
s are not restricted
by Safe
and are available to all catalogs running on
the server.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5129 (context shows lines 5129-5285)
sub parse_tag { my ($var, $value) = @_; my ($new); #::logDebug("parse_tag var=$var val=$value") unless $Global::Foreground; return if $Vend::ExternalProgram; unless (defined $value && $value) { return {}; } return parse_mapped_code($var, $value) if $var ne 'UserTag'; #::logDebug("ready to read tag, C='$C' SystemCodeDone=$SystemCodeDone") unless $Global::Foreground; get_system_code() unless defined $SystemCodeDone; my $c = defined $C ? $C->{UserTag} : $Global::UserTag; my($tag,$p,$val) = split /\s+/, $value, 3; unless ( $tagCanon{lc $p} ) { config_warn("Bad user tag parameter '%s' for '%s', skipping.", $p, $tag); return $c; } # Canonicalize $p = $tagCanon{lc $p}; $tag =~ tr/-/_/; $tag =~ s/\W//g and config_warn("Bad characters removed from '%s'.", $tag); if ($tagSkip{$p}) { return $c; } if($p eq 'Underride') { if($Global::UserTag->{Routine}->{$tag} or $C && $C->{UserTag}->{Routine}->{$tag}) { $c->{Done}{$tag} = 1; } } return $c if $c->{Done}{$tag}; if($CodeDest and $CodeDest eq 'CoreTag') { return $c unless $Global::TagInclude->{$tag} || $Global::TagInclude->{ALL}; } #::logDebug("ready to read tag=$tag p=$p") unless $Global::Foreground; if($p eq 'Override') { for (keys %$c) { delete $c->{$_}{$tag}; } } elsif($p eq 'Routine' or $p eq 'PosRoutine') { if (defined $c->{Source}->{$tag}->{$p}){ config_error( errmsg( "Duplicate usertag %s found", $tag, ) ); } if (defined $C && defined $Global::UserTag->{Routine}->{$tag}){ config_warn( errmsg( "Local usertag %s overrides global definition", $tag, ) ) unless $C->{Limit}{override_tag} =~ /\b$tag\b/; } my $sub; $c->{Source}->{$tag}->{$p} = $val; unless(!defined $C or $Global::AllowGlobal->{$C->{CatalogName}}) { my $safe = new Vend::Safe; my $code = $val; $code =~ s'$Vend::Session->'$foo'g; $code =~ s'$Vend::Cfg->'$bar'g; $safe->trap(@{$Global::SafeTrap}); $safe->untrap(@{$Global::SafeUntrap}); $sub = $safe->reval($code); if($@) { config_warn( "UserTag '%s' subroutine failed safe check: %s", $tag, $@, ); return $c; } } local($^W) = 1; my $fail = ''; { local $SIG{'__WARN__'} = sub {$fail .= "$_[0]\n";}; package Vend::Interpolate; $sub = eval $val; } if($@) { config_warn( "UserTag '%s' subroutine failed compilation:\n\n\t%s", $tag, "$@ (warnings=$fail)", ); return $c; } elsif($fail) { config_warn( "Warning while compiling UserTag '%s':\n\n\t%s", $tag, $fail, ); return $c; } config_warn( "UserTag '%s' code is not a subroutine reference", $tag, ) unless ref($sub) eq 'CODE'; $c->{$p}{$tag} = $sub; $c->{Order}{$tag} = [] unless defined $c->{Order}{$tag}; } elsif (! $C and $p eq 'MapRoutine') { #::logDebug("In MapRoutine ") unless $Global::Foreground; $val =~ s/^\s+//; $val =~ s/\s+$//; no strict 'refs'; $c->{Routine}{$tag} = \&{"$val"}; $c->{Order}{$tag} = [] unless defined $c->{Order}{$tag}; } elsif(defined $tagAry{$p}) { my(@v) = Text::ParseWords::shellwords($val); $c->{$p}{$tag} = [] unless defined $c->{$p}{$tag}; push @{$c->{$p}{$tag}}, @v; } elsif(defined $tagHash{$p}) { my(%v) = Text::ParseWords::shellwords($val); $c->{$p}{$tag} = {} unless defined $c->{$p}{$tag}; for (keys %v) { $c->{$p}{$tag}{$_} = $v{$_}; } } elsif(defined $tagBool{$p}) { $c->{$p}{$tag} = 1 unless defined $val and $val =~ /^[0nf]/i; } else { config_warn("UserTag %s scalar parameter %s redefined.", $tag, $p) if defined $c->{$p}{$tag}; $c->{$p}{$tag} = $val; } return $c; }
UserTrack — enable sending of X-Track HTTP header
Prior to Interchange 5.5.2, there was no ability to control
X-Track
header, and it was unconditionally enabled
if TrackFile
was defined.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
ValuesDefault — define default user values
The directive sets default values in users' sessions. Values are otherwise kept in UserDB and they override the defaults, but when the user is not logged in (and hasn't set any of his preferences for the current session), those defaults will be used.
Example: Defining default values
Put the following in catalog.cfg
:
ValuesDefault fname New lname User ValuesDefault country HR
Create a test page:
Welcome!<br/> Your first name is: [value fname]<br/> Your last name is: [value lname]<br/> Your country code is: [value country]
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 3188 (context shows lines 3188-3205)
sub parse_hash { my($item,$settings) = @_; if (! $settings) { return $HashDefaultBlank{$item} ? '' : {}; } my $c; if(defined $C) { $c = $C->{$item} || {}; } else { no strict 'refs'; $c = ${"Global::$item"} || {}; } return hash_string($settings,$c); }
VarName — remap Interchange variables to arbitrary names in generated URLs
The directive sets the names of variables that will be remapped to and from the URL when Interchange outputs it in user pages or reads from form submission requests.
Interchange already ships with some remapping definitions (to shorten URLs, not
obfuscate code or anything); see etc/varnames
for a
list.
When remapping mv_
variable names, make sure you avoid
two-letter abbreviations — most are reserved for the
search parameters. Names consisting of
1, 3 or more characters would be fine, though.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 2874 (context shows lines 2874-2911)
sub parse_varname { my($item,$settings) = @_; return if $Vend::ExternalProgram; my($iv,$vn,$k,$v,@set); #logDebug("parse_varname: $settings"); if(defined $C) { return '' if ! $settings; $C->{IV} = { %{$Global::IV} } if ! $C->{IV}; $C->{VN} = { %{$Global::VN} } if ! $C->{VN}; $iv = $C->{IV}; $vn = $C->{VN}; } else { if (! $Global::VarName) { unless (-s "$Global::ConfDir/varnames" && -r _) { $settings = $Varnames . "\n$settings"; writefile("$Global::ConfDir/varnames", $Varnames); } else { $settings = readfile("$Global::ConfDir/varnames"); } } undef $Varnames; $Global::IV = {} if ! $Global::IV; $Global::VN = {} if ! $Global::VN; $iv = $Global::IV; $vn = $Global::VN; } @set = grep /\S/, split /\s+/, $settings; while( $k = shift @set, $v = shift @set ) { $vn->{$k} = $v; $iv->{$v} = $k; } return 1; }
Variable — define an Interchange variable
The directive defines a variable that will be available either
globally (if defined in interchange.cfg
) or within a catalog (if defined in catalog.cfg
).
Variable names are case sensitive and can only contain word characters (that is, a-z, A-Z, 0-9 and _).
Once the variable is defined, it can be accessed using the following syntax:
__
- to only look for a catalog variable
NAME
__
@@
- to only look for a global variable
NAME
@@
@_
- to first look for a catalog variable, falling back to global
unless found
NAME
_@
Using the var
tag (Note: the var
tag is parsed together with
all other tags, unlike the previous methods which are parsed separately,
before ITL tag processing takes place)
Variable names do not need to begin with a capital letter (unlike the documentation prior to Interchange 5.4 release stated), even though specifying them in all-uppercase is a widely accepted practice.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5295 (context shows lines 5295-5317)
sub parse_variable { my ($var, $value) = @_; my ($c, $name, $param); # Allow certain catalogs global subs unless (defined $value and $value) { $c = { 'save' => {} }; return $c; } if(defined $C) { $c = $C->{$var}; } else { no strict 'refs'; $c = ${"Global::$var"}; } ($name, $param) = split /\s+/, $value, 2; chomp $param; $c->{$name} = $param; return $c; }
VariableDatabase — specify database containing variables
The directive specifies name of a database containing a field Variable which will be used to return Interchange variable values.
In other words, instead of keeping a long list of
Variable NAME value
definitions in interchange.cfg
or catalog.cfg
, you can
simply create a database with the name and value pairs.
Example: Enabling VariableDatabase
Save the following as products/variables.txt
:
code Variable HELLO Hi ANON Guest
Put the following lines in catalog.cfg
:
Database variables variables.txt TAB VariableDatabase variables
Create a test page:
[tmp user][either][data session username][or]__ANON__[/either][/tmp] __HELLO__, [scratch user]!
If no Database
entry corresponding to VariableDatabase
definition is found, a default of TAB-separated .txt
file is assumed. In other words:
VariableDatabase variables
is the same as:
Database variables variables.txt TAB VariableDatabase variables
But if you want to use a non-default database, you must
explicitly define it using the Database
directive and do so before the
VariableDatabase
line.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4769 (context shows lines 4769-4815)
sub parse_dbconfig { my ($var, $value) = @_; my ($file, $type); return '' if ! $value; local($Vend::Cfg) = $C; my ($db, $table); eval { ($db, $table) = get_configdb($var, $value); }; return '' if ! $db; my ($k, @f); # key and fields my @l; # refs to locale repository my @n; # names of locales my @h; # names of locales @n = $db->columns(); shift @n; my $extra; for(@n) { my $real = $CDname{lc $_}; if (! ref $Vend::Cfg->{$real} or $Vend::Cfg->{$real} !~ /HASH/) { # ignore non-existent directive, but put in hash my $ref = {}; push @l, $ref; push @h, [$real, $ref]; next; } push @l, $Vend::Cfg->{$real}; } my $i; while( ($k, undef, @f ) = $db->each_record) { #::logDebug("Got key=$k f=@f"); for ($i = 0; $i < @f; $i++) { next unless length($f[$i]); $l[$i]->{$k} = $f[$i]; } } for(@h) { $Vend::Cfg->{Hash}{$_->[0]} = $_->[1]; } $db->close_table(); return $table; }
VendURL — specify base URL of the Interchange catalog link program
VendURL
is one of mandatory settings in every catalog.cfg
.
The directive specifies a base catalog URL, that is, it's entry point (usually a cgi-bin link program).
Example: Setting VendURL
Put the following lines in catalog.cfg
:
VendURL http://myhost.mydomain.local/cgi-bin/ic/tutorial
VendURL
value can also be a relative path, with or without the
protocol and hostname specification.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 4002 (context shows lines 4002-4006)
sub parse_url { my($var, $value) = @_; $value =~ s,/+$,,; $value; }
WideOpen — disable IP-based qualification of user sessions (the directive degrades catalog security!)
The WideOpen
directive disables IP-based qualification of user
sessions, and everyone's hostname part of the Interchange cookie is
set to nobody
.
This increases compatibility, but reduces catalog security.
When this directive is enabled, no IP-based checking is done, so anyone guessing and supplying a valid session ID can hijack other client's session.
The option was introduced to achieve more compatibility with old browsers, at
cost of some security. Do not enable it unless your clients experience
problems caused by IP addresses that change from access to access.
Also do not use it unless you are using encryption
(PGP/CreditCardAuto
) or a real-time payment gateway, or the risk may
be too high.
Example: Enabling WideOpen directive
Put any of the following lines in catalog.cfg
:
WideOpen 1 WideOpen Yes
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }
Windows — (obsolete) indicate that Interchange is running under Microsoft Windows
The option should be enabled to indicate (an unfortunate) situation where Interchange is running on Microsoft Windows family of products.
However, Unix is best. The Windows version, while perhaps more than just a toy,
is not suitable for high-volume catalog serving. This is mostly due to Windows
NT not fitting the UNIX fork()
model which works so well
with Interchange.
On Microsoft Windows, you will want to stop and re-start your Interchange server at
least once per day. You can use a system agent to automate it — you will
want to stop the server to expire the session database anyway. You need to do
this because Interchange requires the Unix-specific fork()
call
to spawn multi-tasked
servers, and without multi-tasked servers there is a strong possibility of
a memory leak — especially if you use embedded Perl or conditional tags.
Interchange support for Microsoft Windows support has been abandoned. This configuration directive has no purpose; if you think you need it, think twice.
WritePermission — affect file mode (write permissions) on Interchange-generated files
By default, only the user account that Interchange runs under, can read and write files created by Interchange. The specified option allows adjustment of file modes (write permissions, specifically).
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5448 (context shows lines 5448-5457)
sub parse_permission { my($var, $value) = @_; $_ = $value; tr/A-Z/a-z/; if ($_ ne 'user' and $_ ne 'group' and $_ ne 'world') { config_error("Permission must be one of 'user', 'group', or 'world' for the $var directive\n"); } $_; }
XHTML — enable XHTML-conformant HTML output
If the directive is enabled, Interchange produces more XHTML-compliant HTML
output. This just includes the insertion of "/
"
in standalone tag endings, since argument name lowercasing and argument
option quoting (the other two "things" that make XHTML XHTML)
have been already adopted practices for all HTML output.
Interchange is gradually adopting XHTML-compliant HTML code. Therefore,
some things might still not be XHTML-ready even after users enable
XHTML
.
Making HTML output XHTML-compliant is extremely easy (basically, you only
need to lowercase argument names, quote argument options, and include
$Vend::Xtrailer
before the ending
">
" for standalone tags. That said, XHTML-compliance
patches are gladly accepted to speed up the effort.
Interchange 5.9.0:
Source: lib/Vend/Config.pm
Line 5434 (context shows lines 5434-5446)
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"); } }