CGI

The HTTP (Web) protocol does not use the same mechanism to send data from server to client, and from client to server. Client to server communication must usually happen over CGI (Common Gateway Interface), by having users submit HTML forms.

Form data submitted usually consists of key=value pairs. One other option are just values following one another (value1+value2+value3...); those are called "ISINDEX" queries, and are not generally used with Interchange.

Form submission can happen in two ways.

The "GET" method is very basic, as it just embeds form values in the URL being sent to the server. One example of a GET query is http://myhost.mydomain.local/cgi-bin/ic/test?mv_arg=1&mv_pc=14. I think it's simple enough to notice variables mv_arg and mv_pc being submitted. The GET method is very convenient because all data is embedded in the URL, making it very easy to copy and share links with other people.

It is recommended to create these links in Interchange with [area].,e.g.:


<a href="[area href="" form="param1=foo
  param2=bar"]">FOO & BAR</a>
</a>

The other method is called POST. This way, the information is sent in a way not visible to the user. POST forms have this disadvantage of not being suitable for copy-pasting HTML links directly, but they do offer greater flexibility, especially if a lot of form data is being sent.

When forms are submitted using the POST method, they can also embed data in the URL, effectively passing both POST and GET data at once. Interchange ignores GET data on POST forms, but can be instructed to parse both using the TolerateGet directive.

In the end, it turns out you can just use GET in most situations. It's simpler, more convenient, and gets the job done just as well.

CGI variables in Interchange are accessible using the [cgi] tag, and only on a page directly following the form submission. This is logical, of course. A page request reaches the Interchange daemon, and it either has or doesn't have the accompanying form data; there's no "history" mechanism included. (However, Interchange does allow you to save values for future reference, usually in the value or scratch space). Interchange is, by default, eager to collect user information, at least for the duration of the session (so the users don't have to retype it again). During processing, CGI variables are therefore propagated to the values space, for subsequent requests. The FormIgnore directive specifies which CGI variables should not be propagated.

Users have complete control over CGI data they will send. Therefore, this input should never be trusted. It's raw data, and it is a security risk to save it in a database or display in a page before sanitization. The most common security risk is displaying HTML code which allows remote scripting exploits like cookie-stealing.

Never do something like the following:

[cgi VARNAME]

or

[calc]
  my $out = $CGI->{VARNAME};
  return $out;
[/calc]

Fortunately, Interchange offers a number of ways to take care of the data, usually by filtering it. For more discussion and help on filtering, see the filter glossary entry. A safe no-brainer approach is to just use the encode_entities filter on the input.

So, to obtain a "safe" value while keeping the original intact, use:

[cgi name=VARNAME filter=entities]

or:

[filter entities][cgi VARNAME][/filter]

or:

[calc]
  my $out = $Tag->cgi({ name => 'VARNAME', filter => 'entities' });
  return $out;
[/calc]

or:

[calc]
  my $out = $Tag->filter($CGI->VARNAME, 'entities');
  return $out;
[/calc]

One interesting feature in Interchange is that you can set CGI values yourself. This has two common uses. You can set a value and pretend as if it was sent by the user (so the rest of your code doesn't need to split in two execution paths, depending on whether the variable was set or not). Another thing you can do, is set special CGI variables (the mv_* ones that affect how Interchange processes the page) and let Interchange do its magic. Heck, not only you can set them once, but you can change their value during processing, achieving different behavior in different parts of the page.

You can set values by providing set=VALUE hide=1 attributes to the [cgi] tag, or by simple assignment in Perl ($CGI->{VARNAME} = 'VALUE').

Here's a complete list of ways to access CGI variables:

In ITL:

Access syntaxNotes
[cgi VARNAME]Doesn't prevent users from injecting ITL code; don't use it!
[cgi name=VARNAME filter=entities]A safe and correct way to go

In embedded Perl:

Access syntaxNotes
$CGI->{VARNAME}Retrieves raw CGI value; don't use before filtering
$Tag->cgi({ name => 'VARNAME', filter => 'entities' });A safe and correct way to go
$Tag->filter($CGI->{VARNAME}, 'entities');A safe and correct way to go

DocBook! Interchange!