|
Csoft-CGI is a small and unobstrusive framework for
writing multi-lingual web applications in C. Traditional CGI and
FastCGI modes are
supported.
This document demonstrates some of the basic functions implemented
by the library.
All source code should include <libcgi/cgi.h>, even if it does not
use libcgi calls directly, in FastCGI mode it provides necessary stdio
wrappers.
Csoft-cgi provides the following includes:
#include <libcgi/cgi.h> /* Required */
#include <libcgi/mime.h> /* MIME-related functions */
#include <libcgi/html.h> /* HTML output related functions */
#include <libcgi/table.h> /* General-purpose tables */
|
|
Before using any libcgi function, you must invoke the cgi_init()
function, providing a pointer to a preinitialized struct cgi. This
structure contains some information about the application, a list of
available languages, optiopn flags and a pointer to an optional function
to call when the application exits.
Instead of using exit(), you should use cgi_destroy(). The
first argument is the return code.
The second argument is an optional error message.
#include <libcgi/cgi.h>
struct cgi hello_cgi = {
"Hello, world application", /* Application title */
"", /* Copyright */
{ "en", "fr", "no", NULL }, /* Available languages */
CGI_HTML_ERRORS, /* Option flags */
foo_destroy /* Exit function */
};
int
main(int argc, char *argv)
{
cgi_init(&hello_cgi);
cgi_destroy(EX_OK, NULL);
return (0);
}
The list of languages defines the languages which the application
speaks. When processing queries, the application checks the client's
list of accepted languages and switches to the first language appearing
on this list. Multilanguage support is provided by both an internal
gettext implementation (which substitutes marked strings such as
_("foo") in the code), and the html subsystem which uses an
XSL transform to treat <ml lang="xx"> tags in the html source
and templates.
Possible option flags include CGI_HTML_ERRORS (generate HTML
error in addition to logging), and CGI_PERSISTENT (require
FastCGI mode; application must run persistently).
|
|
A typical csoft-cgi application will loop processing requests every time
the cgi_accept() function return a struct cgi_query pointer.
The cgi_begin() function outputs the HTTP headers, such as
Content-Type. Between those two calls, the application can set cookies
or return specific HTTP headers.
#include <libcgi/cgi.h>
struct cgi hello_cgi = {
"Hello, world application", /* Application title */
"", /* Copyright */
{ "en", "fr", "no", NULL }, /* Available languages */
CGI_HTML_ERRORS, /* Option flags */
foo_destroy /* Exit function */
};
int
main(int argc, char *argv)
{
struct cgi_query *q;
cgi_init(&hello_cgi);
while ((q = cgi_accept()) != NULL) {
cgi_begin(q, "text/html");
cgi_log(LOG_INFO, "Processing request");
cgi_printf(q, "Hello, world!");
}
cgi_destroy(EX_OK, NULL);
return (0);
}
The cgi_printf() function, as you might have guessed, outputs
text to the client. The cgi_log() function inserts an entry in
the application's logfile (ie. "hello.fcgi.log").
|
|
The cgi_get_arg() and cgi_lget_arg() functions are used to
retrieve GET and POST arguments. Each argument has two strings, a key and
a value. The key length is always limited to CGI_ARG_KEY_MAX
characters. The length of values is not limited (at least not at the
application level) unless you retrieve it using cgi_lget_arg().
Note that characters in values of all GET arguments are substituted
per RFC1738, so you do not need to worry about URL escaping.
#include <libcgi/cgi.h>
struct cgi hello_cgi = {
"Hello, world application", /* Application title */
"", /* Copyright */
{ "en", "fr", "no", NULL }, /* Available languages */
CGI_HTML_ERRORS, /* Option flags */
foo_destroy /* Exit function */
};
int
main(int argc, char *argv)
{
struct cgi_query *q;
cgi_init(&hello_cgi);
while ((q = cgi_accept()) != NULL) {
const char *foo, *bar;
cgi_begin(q, "text/html");
foo = cgi_get_arg(q, "foo");
bar = cgi_lget_arg(q, "foo", 20);
cgi_printf(q, "Foo = %s", foo);
cgi_printf(q, "Bar = %s", bar);
}
cgi_destroy(EX_OK, NULL);
return (0);
}
To test the arguments, invoke hello.fcgi?foo=fooval&bar=barval.
In this example, if the length of the "bar" argument exceeds 20 characters,
its value will be truncated.
|
|
Csoft-cgi's build system uses a set of M4 templates and an XSLT processor
(xsltproc) to process a set of HTML source files (which must have the
*.htm extension) into pre-processed HTML documents in different
languages and character sets. For example, if the application is available
in both French and English, you would run make to process
foo.htm into foo.html.en, foo.html.en.utf8,
foo.html.fr, foo.html.fr.utf8 and foo.html.fr.iso8859-1.
At each request, csoft-cgi will switch to the proper language based on
HTTP/1.1 language negotiation. It is possible to override language
negotiation by providing a lang argument.
The html_output() function is used to output the contents of a
preprocessed HTML document to the client. Various substitutions are made.
For instance, if you use var_set("foo", "bar") in the program,
instances of "$foo" in the document (either the *.htm or any of the
*.m4 templates will be substituted for "bar".
#include <libcgi/cgi.h>
struct cgi hello_cgi = {
"Hello, world application", /* Application title */
"", /* Copyright */
{ "en", "fr", "no", NULL }, /* Available languages */
CGI_HTML_ERRORS, /* Option flags */
foo_destroy /* Exit function */
};
int
main(int argc, char *argv)
{
struct cgi_query *q;
cgi_init(&hello_cgi);
while ((q = cgi_accept()) != NULL) {
const char *foo, *bar;
cgi_begin(q, "text/html");
var_set("foo", "bar");
html_output(q, "mypage");
}
cgi_destroy(EX_OK, NULL);
return (0);
}
Now you must add "mypage.htm" to the ${HTML} list in your
application's Makefile, and create the file. Two special macros
are required, CONTENT() and TITLE(). You can use m4
builtins, such as define() and include().
The default quotes are "[" and "]". If
you need
to use those literal characters in the document, you might need to
use the m4 changequote() function. The XSL processor will
escape some characters for you. Literal quotes that are not part of an
HTML tag, for instance, are automatically substituted to """.
TITLE([
<ml lang="en">My page</ml>
<ml lang="fr">Ma page</ml>
])
CONTENT([
<ml lang="en">The value of foo is "$foo".</ml>
<ml lang="fr">La valeur de foo est «$foo».</ml>
])
|
The cgi_set_cookie() and cgi_get_cookie() function allows
you to set and retrieve HTTP cookies.
#include <libcgi/cgi.h>
struct cgi hello_cgi = {
"Hello, world application", /* Application title */
"", /* Copyright */
{ "en", "fr", "no", NULL }, /* Available languages */
CGI_HTML_ERRORS, /* Option flags */
foo_destroy /* Exit function */
};
int
main(int argc, char *argv)
{
struct cgi_query *q;
cgi_init(&hello_cgi);
while ((q = cgi_accept()) != NULL) {
const char *foo, *bar;
struct cookie *ticket;
ticket = cgi_set_cookie("ticket", "12345678");
ticket->expire = "12/31/2009 00:00:00";
ticket->secure = 1;
cgi_begin(q, "text/html");
cgi_printf(q, "Ticket = %s", cgi_get_cookie(q, "ticket"));
}
cgi_destroy(EX_OK, NULL);
return (0);
}
|
(More to come...)
|