For a complete introduction to Interchange pragmas, please see the pragma glossary entry.
Table of Contents
cache_control
Interchange 5.9.0 (2/2 contexts shown):
Source: lib/Vend/Server.pm
Line 639 (context shows lines 629-643 in get_cache_headers():636)
$_ = shift; s:^\s+::; s:\s+$::; s:\s*\n\s*:\r\n:g; return "$_\r\n"; } sub get_cache_headers { my @headers; my $cc = $::Pragma->{cache_control}; push @headers, "Cache-Control: $cc" if $cc; push @headers, "Pragma: no-cache" if delete $::Scratch->{mv_no_cache};
Source: lib/Vend/Server.pm
Line 803 (context shows lines 793-807 in respond():655)
# We ensure that POSTs are never suppressed (i.e., cacheable), and # we also allow this option to be configured per catalog, as not # every catalog may be be setup to properly handle these # assumptions and affects. $Vend::suppress_cookies = $CGI::request_method !~ /POST/i && $Vend::Cfg->{SuppressCachedCookies} && ( (defined $::Pragma->{cache_control} && ($::Pragma->{cache_control} !~ /no-cache/i)) || ($Vend::StatusLine =~ /^Cache-Control:\s+(?!no-cache)\s*$/im) ) ;
dml — control behavior of Vend::Data::update_data()
This pragma controls the behavior of
Vend::Data::update_data()
function
in regard to manipulating database records.
No value implies the traditional and backward-compatible Interchange behavior of "update or insert" (upsert).
Value 'preserve
'
restricts inserts to insert-only, but allows
the fall-through behavior from update to insert.
As the name preserve implies, it means records can
be inserted, but no existing data can be clobbered.
Value 'strict
' forces update or insert
to only perform the requested action.
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Data.pm
Line 2278 (context shows lines 2268-2282 in update_data():1804)
} push(@email_rows, [$f, $value]) if $CGI::values{mv_data_email}; #::logDebug("update_data:db=$d key=$key field=$f value=$value"); $brec->{$f} = $value if $brec; } my $dml = { dml => 'upsert' }; $dml->{dml} = $function if $::Pragma->{dml} eq 'strict' || $function eq 'insert' && $::Pragma->{dml} eq 'preserve'; for(keys %$qd) { #::logDebug("update_data: Getting ready to set_slice");
download — disable any output interpolation not to corrupt verbatim content download
The main function of this pragma is to prevent any
interpolation of the output (see the interpolate glossary entry).
It helps to preserve the downloads intact if they
happen to contain constructs similar to
__
or VAR
__[tag]
.
In practice, this pragma is only used internally. If
you wanted to make Interchange a content-delivery engine only, you could
set it in catalog.cfg
, and only undefine it for a few
pages where you want standard page processing.
You might take a look at the deliver
tag which uses this
pragma.
Example: Disable download pragma on a page
Put the following anywhere on your specific page:
[pragma download 0]
Interchange 5.9.0 (5/5 contexts shown):
Source: code/SystemTag/deliver.coretag
Line 95 (context shows lines 85-99)
if($opt->{get_encrypted}) { $opt->{get_encrypted} = 1 unless $opt->{get_encrypted} =~ /^\d+$/; my $idx = $opt->{get_encrypted}; while ($idx--) { $$out =~ s/.*?(---+BEGIN PGP MESSAGE--+)/$1/s; } $$out =~ s/(---+END PGP MESSAGE---+).*/$1\n/s; } $::Pragma->{download} = 1; ::response($out); $Vend::Sent = 1; return 1; }
Source: lib/Vend/Interpolate.pm
Line 534 (context shows lines 524-538 in substitute_image():530)
elsif($joiner =~ m{\\}) { $joiner = $safe_safe->reval("qq{$joiner}"); } return length($joiner) ? $joiner : $default; } sub substitute_image { my ($text) = @_; ## Allow no substitution of downloads return if $::Pragma->{download}; ## If post_page routine processor returns true, return. Otherwise, ## continue image rewrite if($::Pragma->{post_page}) {
Source: lib/Vend/Parse.pm
Line 772 (context shows lines 762-776 in start():592)
Status: $attr->{status} Location: $attr->{href} EOF #::logDebug("bouncing...status line=\n$Vend::StatusLine"); $$buf = ''; $Initialized->{_buf} = ''; my $body = qq{Redirecting to <a href="%s">%s</a>.}; $body = errmsg($body, $attr->{href}, $attr->{href}); #::logDebug("bouncing...body=$body"); $::Pragma->{download} = 1; ::response($body); $Vend::Sent = 1; $self->{ABORT} = 1; $self->{SEND} = 1;
Source: lib/Vend/Dispatch.pm
Line 74 (context shows lines 64-78 in response():70)
my $H; sub http { return $H; } sub response { my $possible = shift; return if $Vend::Sent; if (defined $possible and ! $::Pragma->{download}) { push @Vend::Output, (ref $possible ? $possible : \$possible); } if($::Pragma->{download}) {
Source: lib/Vend/Dispatch.pm
Line 78 (context shows lines 68-82 in response():70)
} sub response { my $possible = shift; return if $Vend::Sent; if (defined $possible and ! $::Pragma->{download}) { push @Vend::Output, (ref $possible ? $possible : \$possible); } if($::Pragma->{download}) { $H->respond(ref $possible ? $possible : \$possible); } elsif($Vend::MultiOutput) { for my $space (keys %Vend::OutPtr) {
dynamic_variables — dynamically update configuration directives from files and databases
This pragma enables configuration directives (Variable
s,
most notably) to be dynamically updated from system files and databases.
It only makes sense to use this in combination with the
DirConfig
or VariableDatabase
directives,
so check their reference pages for more information.
Example: Enable dynamic_variables pragma catalog-wide
Put the following in your catalog.cfg
:
Pragma dynamic_variables
Interchange 5.9.0 (2/2 contexts shown):
Source: code/UserTag/var.tag
Line 25 (context shows lines 15-29)
my ($key, $global, $filter) = @_; my $value; if ($global and $global != 2) { $value = $Global::Variable->{$key}; } elsif ($Vend::Session->{logged_in} and defined $Vend::Cfg->{Member}{$key}) { $value = $Vend::Cfg->{Member}{$key}; } else { $value = ( $::Pragma->{dynamic_variables} ? Vend::Interpolate::dynamic_var($key) : $::Variable->{$key} ); $value ||= $Global::Variable->{$key} if $global;
Source: lib/Vend/Interpolate.pm
Line 611 (context shows lines 601-615 in vars_and_comments():593)
$::Pragma->{$1} = (length($2) ? $2 : 1), ''/ige; undef $Vend::PageInit unless $::Pragma->{init_page}; if(defined $Vend::PageInit and ! $Vend::PageInit++) { Vend::Dispatch::run_macro($::Pragma->{init_page}, $html); } # Substitute in Variable values $$html =~ s/$Gvar/$Global::Variable->{$1}/g; if($::Pragma->{dynamic_variables}) { $$html =~ s/$Evar/dynamic_var($1) || $Global::Variable->{$1}/ge and $$html =~ s/$Evar/dynamic_var($1) || $Global::Variable->{$1}/ge; $$html =~ s/$Cvar/dynamic_var($1)/ge;
dynamic_variables_file_only — dynamically update configuration directives from files only
If this pragma is set, it prevents opening of Interchange databases in search for dynamic content of the directives, so that only files are checked.
It only makes sense to use this in combination with the
<pragma>dynamic_variables</pragma> pragma, and
DirConfig
and VariableDatabase
directives,
so check their reference pages for more information.
Example: Enable dynamic_variables_file_only pragma catalog-wide
Put the following in your catalog.cfg
:
Pragma dynamic_variables Pragma dynamic_variables_file_only
dynamic_variables_file_only is available in Interchange versions:
4.6.0-5.9.0 (git-head)
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Interpolate.pm
Line 578 (context shows lines 568-582 in dynamic_var():570)
} sub dynamic_var { my $varname = shift; return readfile($Vend::Cfg->{DirConfig}{Variable}{$varname}) if $Vend::Cfg->{DirConfig} and defined $Vend::Cfg->{DirConfig}{Variable}{$varname}; VARDB: { last VARDB if $::Pragma->{dynamic_variables_file_only}; last VARDB unless $Vend::Cfg->{VariableDatabase}; if($Vend::VarDatabase) { last VARDB unless $Vend::VarDatabase->record_exists($varname); return $Vend::VarDatabase->field($varname, 'Variable');
init_page — custom subroutine to run before page Variable processing
This pragma defines a Sub
or GlobalSub
to run
before page Variable
processing.
A reference to the contents of the
page is passed to the subroutine.
Example: Auto-wrapping pages in templates
We check the page to see if it contains any @_VARIABLE_@
strings.
If it does not, we consider it not to have a template and add the
definitions ourselves.
The following is needed in catalog.cfg
:
Pragma init_page=wrap_page Sub <<EOS sub wrap_page { my $pref = shift; return if $$pref =~ m{\@_[A-Z]\w+_\@}; $$pref =~ m{<!--+ title:\s*(.*?)\s+-->} and $Scratch->{page_title} = $1; $$pref = <<EOF; \@_MYTEMPLATE_TOP_\@ <!--BEGIN CONTENT --> $$pref <!-- END CONTENT --> \@_MYTEMPLATE_BOTTOM_\@ EOF return; } EOS
Example: Auto-wrapping pages in templates, deciding about a template depending on page path
In this real-life example, we want to automatically attach header and footer to every served page. We also have four different templates, and want to include them depending on the path of the page being served.
Pragma init_page=wrap_page Sub <<EOS sub wrap_page { my $pref = shift; my $tmpl; if ( $Session->{last_url} =~ m#^/www(/|$)# ) { $tmpl = "www" } elsif ( $Session->{last_url} =~ m#^/plus(/|$)# ) { $tmpl = "plus" } elsif ( $Session->{last_url} =~ m#^/hp(/|$)# ) { $tmpl = "hp" } elsif ( $Session->{last_url} =~ m#^/adm(/|$)# ) { $tmpl = "adm" } $Scratch->{subsite} = $tmpl || $Scratch->{subsite} || "plus"; $$pref = "[include templates/$Scratch->{subsite}-top]" . $$pref . "[include templates/$Scratch->{subsite}-bottom]"; return; } EOS
Note that we explicitly check for supported template types
(www
, plus
, hp
or adm
) to minimize the chance of abuse.
Invalid or unmatched templates default to the previously used template, or
plus
as a bottom line and
the files templates/plus-top
and
templates/plus-bottom
are included then.
You might wonder in what cases would the code fail to match the template?
Well, obviously, users could simply try to access non-existent pages.
The other common issue are ActionMaps such as
/scan
or /process
.
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Interpolate.pm
Line 603 (context shows lines 593-607 in vars_and_comments():593)
sub vars_and_comments { my $html = shift; ## We never want to interpolate vars if in restricted mode return if $Vend::restricted; local($^W) = 0; # Set whole-page pragmas from [pragma] tags 1 while $$html =~ s/\[pragma\s+(\w+)(?:\s+(\w+))?\]/ $::Pragma->{$1} = (length($2) ? $2 : 1), ''/ige; undef $Vend::PageInit unless $::Pragma->{init_page}; if(defined $Vend::PageInit and ! $Vend::PageInit++) { Vend::Dispatch::run_macro($::Pragma->{init_page}, $html); }
interpolate_itl_references — allow ITL interpolation of reference-based ITL attributes
When the pragma is enabled, ITL interpolation of reference-based ITL attributes is enabled.
In other words, suppose that you execute the following code:
Example: Enable interpolate_itl_references
The pragma allows the following type of code:
[pragma interpolate_itl_references] [tmp testing]foobar'ed[/tmp] [record table=inventory key=newkey col.quantity=300 col.stock_message="[scratch testing]" ]
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Parser.pm
Line 210 (context shows lines 200-214)
} next if $old; if(! $attr) { $attr->{OLD} = $val if defined $attr; next; } if(defined $element) { #::logDebug("Found element: $element val=$val"); $val = Vend::Interpolate::interpolate_html($val) if $::Pragma->{interpolate_itl_references} and $val =~ /\[\w[-\w]*\s+.*]/s; if(! ref $attr{$attr}) { if ($element =~ /[A-Za-z]/) { $attr{$attr} = { $element => $val };
max_matches
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/DbSearch.pm
Line 241 (context shows lines 231-245 in search():116)
$qual .= join $joiner, @{$s->{eq_specs_sql}}; } $s->save_specs(); # set max_matches based on the lower of the pragma & the search parameter # (so end-users can further restrict the size of the result set, but not increase it) my $max_matches; { no warnings 'uninitialized'; $max_matches = $::Pragma->{max_matches}; undef $max_matches if $max_matches < 1; my $search_mm = $s->{mv_max_matches}; $max_matches = $search_mm if $search_mm > 0 and (!$max_matches or $search_mm < $max_matches);
no_default_reparse — do not reparse Interchange output by default
This pragma disables default reparse of Interchange output from container tags.
Reparsing can, of course, still be requested using the
Reparse
setting
in individual ITL tag definition, or by providing the
universal reparse=1
attribute to any container tag.
Example: Enable no_default_reparse pragma page-wide
Put the following anywhere on your page:
[pragma no_default_reparse]
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Parse.pm
Line 700 (context shows lines 690-704 in start():592)
#::logDebug("using default $k = $v"); $attr->{$k} = $v; } } $attr->{enable_html} = 1 if $Vend::Cfg->{Promiscuous}; $attr->{reparse} = 1 unless ( defined $NoReparse{$tag} || defined $attr->{reparse} || $::Pragma->{no_default_reparse} ); my ($routine,@args);
no_html_comment_embed — do not treat specially formed HTML comments as ITL code
Many HTML editing applications do not support ITL directly, and
some
(thinking it doesn't belong to the page) ruin your work. This is
understandable to an extent, because some ITL tags (such as list
)
appear in places that raise errors with HTML syntax checking algorithms.
So in order to help that, Interchange allows you to wrap ITL code into HTML comments, which the editing applications leave alone in most cases.
When such HTML comment is found, it is stripped away, ITL tags are interpolated and the output is displayed as if HTML comment was never there.
To make use of this arcane feature, simply leave no space between the HTML comment and ITL tags:
The time is now <!--[time]-->.
Setting the <pragma>no_html_comment_embed</pragma> pragma instructs Interchange not to parse and interpolate any HTML comments. With this pragma enabled, the above example would not display the current time.
Example: Enable no_html_comment_embed pragma page-wide
Put the following anywhere on your page:
[pragma no_html_comment_embed]
Although this feature existed in Interchange for a very long time, the pragma to control its behavior was added in September 2004, after someone stumbled on it by accident.
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Interpolate.pm
Line 632 (context shows lines 622-636 in vars_and_comments():593)
} if($::Pragma->{pre_page}) { Vend::Dispatch::run_macro($::Pragma->{pre_page}, $html); } # Strip out [comment] [/comment] blocks 1 while $$html =~ s%$QR{comment}%%go; # Translate Interchange tags embedded in HTML comments like <!--[tag ...]--> ! $::Pragma->{no_html_comment_embed} and $$html =~ s/<!--+\[/[/g and $$html =~ s/\]--+>/]/g;
no_image_rewrite — prevent image locations from being altered
This pragma prevents image locations in Interchange pages from being altered.
Interchange normally rewrites image locations to point to ImageDir
(or ImageDirSecure
). This applies to image locations mentioned in <img src="">, <input src="">, <body background="">, <table background=""> and table subelements (<th>, <tr> and <td>).
Example: Image path rewriting example
If the <pragma>no_image_rewrite</pragma> pragma is
disabled and
ImageDir
is set to "/standard/images", an image URL
like:
<img src="fancy.gif">
would be changed to:
<img src="/standard/images/fancy.gif">
With the directive enabled, the image URLs would be left intact.
Interchange 5.9.0 (4/4 contexts shown):
Source: code/SystemTag/unpack.coretag
Line 40 (context shows lines 30-44)
} } } } else { for(@Vend::Output) { Vend::Interpolate::substitute_image($_); } } undef $Vend::MultiOutput; $::Pragma->{no_image_rewrite} = 1; Vend::Page::templatize($template); return; } EOR
Source: lib/Vend/Interpolate.pm
Line 543 (context shows lines 533-547 in substitute_image():530)
## Allow no substitution of downloads return if $::Pragma->{download}; ## If post_page routine processor returns true, return. Otherwise, ## continue image rewrite if($::Pragma->{post_page}) { Vend::Dispatch::run_macro($::Pragma->{post_page}, $text) and return; } unless ( $::Pragma->{no_image_rewrite} ) { my $dir = $CGI::secure ? ($Vend::Cfg->{ImageDirSecure} || $Vend::Cfg->{ImageDir}) : $Vend::Cfg->{ImageDir};
Source: lib/Vend/Parse.pm
Line 340 (context shows lines 330-344 in destination():307)
return unless $attr; #::logDebug("destination extended output settings"); my $fary = $Vend::OutFilter{$name}; if ($name) { $Vend::MultiOutput = 1; if(! $Vend::OutFilter{''}) { my $ary = []; push @$ary, \&Vend::Interpolate::substitute_image unless $::Pragma->{no_image_rewrite}; $Vend::OutFilter{''} = $ary; } if(! $fary) {
Source: lib/Vend/Parse.pm
Line 354 (context shows lines 344-358 in destination():307)
if(! $fary) { $fary = $Vend::OutFilter{$name} = []; if($attr->{output_filter}) { my $filt = $attr->{output_filter}; push @$fary, sub { my $ref = shift; $$ref = Vend::Interpolate::filter_value($filt, $$ref); return; }; } if (! $attr->{no_image_parse} and ! $::Pragma->{no_image_rewrite}) { push @$fary, \&Vend::Interpolate::substitute_image; } if ($attr->{output_extended}) { $Vend::OutExtended{$name} = $attr;
no_locale_parse — do not parse [L] or [LC] tags
Applying this pragma on the page level isn't really helpful, as pseudo tags contained in the page are parsed before the pragma directive.
Interchange 5.9.0 (2/2 contexts shown):
Source: code/UserTag/loc.tag
Line 23 (context shows lines 13-27)
# it works with contained tags # UserTag loc Order locale UserTag l Alias loc UserTag loc hasEndTag 1 UserTag loc Interpolate 1 UserTag loc Version $Revision: 1.7 $ UserTag loc Routine <<EOF sub { my ($locale, $message) = @_; if($::Pragma->{no_locale_parse}) { ## Need to do this but might have side-effects in PreFork mode undef $Vend::Parse::myRefs{Alias}{l}; my $begin = '[L'; $begin .= " $locale" if $locale;
Source: lib/Vend/Util.pm
Line 1113 (context shows lines 1103-1117 in parse_locale():1110)
} $text =~ m{\[$Lang\](.*)\[/$Lang\]}s and return $1; $text =~ s{\[(\w+)\].*\[/\1\].*}{}s; return $text; } sub parse_locale { my ($input) = @_; return if $::Pragma->{no_locale_parse}; # avoid copying big strings my $r = ref($input) ? $input : \$input;
no_negative_tax — disallow tax calculations to apply negative value
When the pragma is enabled and the tax calculation yields a negative number, the tax amount applied will be reset to zero.
Interchange 5.9.0 (2/2 contexts shown):
Source: lib/Vend/Interpolate.pm
Line 5728 (context shows lines 5718-5732 in salestax():5685)
} else { $tax_hash = $Vend::Cfg->{SalesTaxTable}; #::logDebug("looking for tax function: " . uneval($tax_hash)); } # if we have a cost from previous routines, return it if(defined $cost) { $Vend::Items = $save if $save; switch_discount_space($oldspace) if defined $oldspace; if($cost < 0 and $::Pragma->{no_negative_tax}) { $cost = 0; } return Vend::Util::round_to_frac_digits($cost); }
Source: lib/Vend/Interpolate.pm
Line 5785 (context shows lines 5775-5789 in salestax():5685)
{ mv_price => $amount, code => $code, quantity => $amount, }, $tax); } #::logDebug("salestax: final tax='$r' for code='$code'"); last; } $Vend::Items = $save if defined $save; if($r < 0 and ! $::Pragma->{no_negative_tax}) { $r = 0; } return Vend::Util::round_to_frac_digits($r);
perl_warnings_in_page — display Perl "warnings" for Interchange pages
If it is desirable to turn on Perl warnings for pages, you can use
[pragma perl_warnings_in_page]
and see warnings for that page
(or all pages by default if you put in catalog.cfg
).
Example: Enable perl_warnings_in_page catalog-wide
Put the following in catalog.cfg
:
Pragma perl_warnings_in_page
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Interpolate.pm
Line 663 (context shows lines 653-667 in interpolate_html():640)
and $html =~ s/^/$::Variable->{MV_AUTOLOAD}/; defined $::Variable->{MV_AUTOEND} and $html =~ s/$/$::Variable->{MV_AUTOEND}/; $toplevel = 1; } #::logDebug("opt=" . uneval($opt)); vars_and_comments(\$html) unless $opt and $opt->{onfly}; $^W = 1 if $::Pragma->{perl_warnings_in_page}; # Returns, could be recursive my $parse = new Vend::Parse $wantref; $parse->parse($html);
post_page — custom subroutine to run before image paths substitution on a page
This pragma defines a Sub
or GlobalSub
to run
before image paths substitution on a page. A
reference to the page contents
is passed to the subroutine.
Example: Treat URLs relative to current directory
It is possible to have URL links treated
as being relative to the current directory.
The following is needed in catalog.cfg
:
Pragma post_page=relative_urls ### Take hrefs like <A HREF="about.html"> and make relative to current ### directory Sub <<EOR sub relative_urls { my $page = shift; my @dirs = split "/", $Tag->var('MV_PAGE', 1); pop @dirs; my $basedir = join "/", @dirs; $basedir ||= ''; $basedir .= '/' if $basedir; my $sub = sub { my ($entire, $pre, $url) = @_; return $entire if $url =~ /^\w+:/; my($page, $form) = split /\?/, $url, 2; my $u = $Tag->area({ href => "$basedir$page", form => $form, }); return qq{$pre"$u"}; }; $$page =~ s{( ( <a \s+ (?:[^>]+?\s+)? href \s*=\s* ) (["']) ([^\s"'>]+) \3 )} { $sub->($1,$2,$4) }gsiex; return; } EOR
The old documentation system improperly describes the phase at which the <pragma>post_page</pragma> pragma takes effect (it states it happens after Variable
processing and before tags are interpolated).
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Interpolate.pm
Line 538 (context shows lines 528-542 in substitute_image():530)
} sub substitute_image { my ($text) = @_; ## Allow no substitution of downloads return if $::Pragma->{download}; ## If post_page routine processor returns true, return. Otherwise, ## continue image rewrite if($::Pragma->{post_page}) { Vend::Dispatch::run_macro($::Pragma->{post_page}, $text) and return; }
pre_page — custom subroutine to run after Variable substitution, before interpolation
This pragma defines a Sub
or GlobalSub
to run
after Variable
substitution and
before tags are interpolated on a page. A
reference to the page contents
is passed to the subroutine.
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Interpolate.pm
Line 624 (context shows lines 614-628 in vars_and_comments():593)
$$html =~ s/$Evar/dynamic_var($1) || $Global::Variable->{$1}/ge; $$html =~ s/$Cvar/dynamic_var($1)/ge; } else { $$html =~ s/$Evar/$::Variable->{$1} || $Global::Variable->{$1}/ge and $$html =~ s/$Evar/$::Variable->{$1} || $Global::Variable->{$1}/ge; $$html =~ s/$Cvar/$::Variable->{$1}/g; } if($::Pragma->{pre_page}) { Vend::Dispatch::run_macro($::Pragma->{pre_page}, $html); } # Strip out [comment] [/comment] blocks
safe_data — allow interpolation of database values in search for Interchange tags
By default, Interchange does not allow data returned from the databases to be interpolated (all the [s are converted to an HTML entity [ and displayed literally). Setting this pragma eliminates the restriction and passes [s through for interpolation.
If you want to have tags in your database and display them in Interchange pages (to say, display page
links for internal hyperlinks in your product descriptions), you need to enable this pragma.
Some things to consider, though:
It might be better to use the safe_data
attribute available to certain tags, or perhaps the pragma
for a whole page or tag pragma safe_data
/tag
for a small block of ITL code on a page, instead of setting a catalog-wide <pragma>safe_data</pragma> pragma.
In any case, it is strongly recommended that you surround the area in a restrict
tag to only allow specific set of tags to appear "in-band" (which should be relatively safe), such as page
or area
. Expect security compromises if you allow calc
, perl
or any other extremely powerful tags.
Be certain that you absolutely know where the data from your databases will be used. Consider the following:
Will it always be possible to interpolate?
What about e-mailed plain-text receipts? Will literal "page
" tags show up in product descriptions on the receipt?
Would the desired output of <a href="..."> be any better than a simple plain text?
What if you access your database from applications other than Interchange? You'd then have to decide what to do with such tags; perhaps you could simply strip them, but will the missing output cause trouble?
To sum up, <pragma>safe_data</pragma> is disabled by default for a reason, and you should be very careful if you decide to enable it.
Example: Enabling safe_data block-wide
We'll restrict the available tags to area
and page
, and
enclose the critical section in [tag pragma ...]
:
[tag pragma safe_data]1[/tag] ...critical section... [restrict area page] ...critical section... [/restrict] ...critical section... [tag pragma safe_data]0[/tag]
Example: Enabling safe_data page-wide
Add the following anywhere on an Interchange page:
[pragma safe_data]
Watch out for parse order with tag pragma
or restrict
when used with lists that retrieve data from the database (such as PREFIX-*
, loop
, or the flypage). Loops parse before regular tags like tag
, and are thus not affected by them (so you must include the whole loop code in the "critical section").
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Interpolate.pm
Line 1746 (context shows lines 1736-1750 in ed():1745)
if ($opt->{no_return}) { $Vend::Session->{mv_perl_result} = $result; $result = join "", @Vend::Document::Out; @Vend::Document::Out = (); } #::logDebug("tag_perl succeeded result=$result\nEND"); return $result; } sub ed { return $_[0] if ! $_[0] or $Safe_data or $::Pragma->{safe_data}; $_[0] =~ s/\[/[/g; return $_[0]; }
set_httponly
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Server.pm
Line 621 (context shows lines 611-625 in create_cookie():566)
elsif($expire =~ /\s\S+\s/) { $expstring = $expire; } $expstring = strftime "%a, %d-%b-%Y %H:%M:%S GMT ", gmtime($expire) unless $expstring; $expstring = "expires=$expstring" if $expstring !~ /^\s*expires=/i; $expstring =~ s/^\s*/ /; $out .= $expstring; } $out .= '; secure' if $secure; $out .= '; HttpOnly' if $::Pragma->{set_httponly}; $out .= "\r\n"; } return $out; }
strip_white — strip whitespace from the top of Interchange-served HTML pages
This pragma strips whitespace from the top of HTML pages output by Interchange. Such whitespace usually comes from Interchange tags which get processed and leave empty space behind them. The purpose of this pragma is to make View source option in your web browser a more tolerable experience.
Example: Strip whitespace from the top of Interchange-served pages
Simply add the following to catalog.cfg
Pragma strip_white
Interchange 5.9.0 (2/2 contexts shown):
Source: lib/Vend/Page.pm
Line 275 (context shows lines 265-279 in output_cat():265)
sub output_cat { my ($tag) = @_; my $ary; return '' unless $ary = $Vend::OutPtr{lc $tag}; my $out = ''; for(@$ary) { next unless $Vend::Output[$_]; $out .= ${$Vend::Output[$_]}; undef $Vend::Output[$_]; } $out =~ s/^\s+// if $::Pragma->{strip_white}; return $out; } sub output_ary {
Source: lib/Vend/Server.pm
Line 679 (context shows lines 669-683 in respond():655)
? "$1" : "200 OK"; } if($CGI::redirect_status and ! $Vend::StatusLine) { $status = "200 OK"; $Vend::StatusLine = "Status: 200 OK\nContent-Type: text/html"; } $$body =~ s/^\s+// if ! $Vend::ResponseMade and $::Pragma->{strip_white}; $Vend::StatusLine =~ s/\s*$/\r\n/ if $Vend::StatusLine; # NOTE: if we're supporting arbitrary encodings here in the
url_no_session_id
Interchange 5.9.0 (1/1 contexts shown):
Source: lib/Vend/Util.pm
Line 1366 (context shows lines 1356-1370 in vendUrl():1316)
push @parms, Vend::Interpolate::escape_form($opt->{form}); } my($id, $ct); $id = $Vend::SessionID unless $opt->{no_session_id} or ($Vend::Cookie and $::Scratch->{mv_no_session_id}); $ct = ++$Vend::Session->{pageCount} unless $opt->{no_count}; if($opt->{no_session} or $::Pragma->{url_no_session_id}) { undef $id; undef $ct; }