Function Details
time_t cgi_add_bdays(time_t i_date, int bdays);
Add (subtract) business days to a date.
Knows weekends.
Knows holidays.
char *cgi_canonical_date(char *in_date);
Convert any date string into an oracle 4 digit year date string.
For example, '23-OCT-2000'.
Returns a pointer to a malloc'ed buffer, which should be free'd by caller.
Returns NULL if error.
char *cgi_add_commas(char *str);
Add commas to a string.
For example, "123456789" becomes "123,456,789".
If there is a decimal point, it starts there.
For example, "1234567.12" becomes "1,234,567.12".
Otherwise, it starts at the end of the string.
Return a copy in static space, that is overwritten on each call.
The string may not expand to longer than 100 characters (not enforced).
char *cgi_canonical_newlines(char *str)
Newlines are replaced with Unix style newlines.
DOS style newlines, ^M^J, Macintosh style newlines, ^M
and Unix style newlines, ^J, are recognized.
They are all replaced with Unix style newlines.
The string is modified in place.
For example, embedded newlines collected using
textarea
form widgets are stored as carriage returns (^M).
Developer 2000 uses line feed characters (^J) to
represent newlines. So, web forms should convert
text data before it is stored in the database.
void cgi_cclose(int stream);
Close a client stream opened with ccon.
int cgi_ccon(char *service, char *host);
Connect to a remote server.
AF_INET stream sockets are always used.
service - the name or number of the port that the server serves.
host - the name or internet number of the host where the server runs.
The file descriptor of the socket is returned.
If there is an error, -1 is returned, errno may be of value.
time_t cgi_cnvdate(char *date_str);
Convert any date string into an Unix time_t.
Returns -1 for error, as
the mktime(3C) manual page indicates.
char *cgi_create_cookie(char *user, char *passwd);
Create a cookie. Return the generated cookie name=value string.
A file called "master" has the last number used.
Each cookie has a file, named by the cookie name.
Return NULL for error (unlikely).
void cgi_crypt(char *str);
Simple reversible substitution cypher. A child can break it.
The goal is so that when the administrator looks at a cookie
file, they do not have the password staring in their face.
You only need one routine for encrypt or decrypt.
The string is encrypted or decrypted in place.
char *cgi_canonical_date_time(char *in_date);
Convert any date/time string into an oracle 4 digit year date/time string.
For example, '23-OCT-2000 15:23:37'.
Returns a pointer to a malloc'ed buffer, which should be free'd by caller.
Returns NULL if error.
char *cgi_date_fmt_ccyymmdd(char *when);
Format a date string into "ccyymmddhhmmss".
For example, a returned string might by "19990816142115".
Returns a pointer to a static buffer, which is overwritten by each call.
Useful in filenames which sort chronologically in listings.
char *cgi_date_fmt_mmddccyy(char *when);
Format a date string into "mm/dd/ccyy".
Returns a pointer to a static buffer, which is overwritten
by each call.
const char *cgi_get_odbname(void);
Return the Oracle database name.
Returns NULL if
cgi_ologin has not been called.
void cgi_emit_login(const char *url, const char *error);
Emit the login screen form. If URL is NULL, omit it from the hidden
variable URL.
If errro is not NULL, it is printed in bold red before the login screen.
Typically, it is a error from a previous login.
void cgi_err(char *format, ...);
Emit an error for a cgi program.
Operates like printf(3).
Uses bold red text.
In many ways, routines from the liberr
library are superior, and should be considered.
char *cgi_fmt_date(time_t when);
Format a time_t into "DD-MON-YYYY".
Returns a pointer to a static buffer, which is overwritten
by each call.
char *cgi_fmt_date_time(time_t when);
Format a time_t into "DD-MON-YYYY HH24:MI:SS".
Returns a pointer to a static buffer, which is overwritten
by each call.
char *cgi_fmt_ansi_date(time_t when);
Format a time_t into "YYYY-MM-DD".
Returns a pointer to a static buffer, which is overwritten
by each call.
char *cgi_fmt_ansi_date_time(time_t when);
Format a time_t into "YYYY-MM-DD HH:MM:SS".
Returns a pointer to a static buffer, which is overwritten
by each call.
void cgi_form(const char *url);
Emit <form> start.
Use
cgi_mk_url
to generate references to the same application.
There is no call to end a form.
Generally it is sufficient to use:
puts("</form>");
struct sll *cgi_form_add(const char *key, const char *dat);
Add a key/datum pair to the internal cgi_fi form info list.
Adds to the beginning, so that searches find the new one.
Creates copies of key and datum.
Returns NULL if error - out of RAM.
All data may be removed from the internal list with
cgi_rm_fi.
char *cgi_form_datum(const char *key);
Get datum for key. The key/datum
pairs are entered either from form data - parsed by
cgi_form_info,
or explicitly added with
cgi_form_add.
All data may be removed from the internal list with
cgi_rm_fi.
struct sll *cgi_form_info(void);
Parse POST style form data, and return an array with the decoded data.
Return the form list as an sll if there is any data.
Returns NULL for no data or any error.
char *cgi_fmt_account(char *account);
Format an account number.
Basically, add a dash.
Given an account number "12345678",
turn it into "123-45678".
Returns a pointer to a static buffer which is overwritten
on subsequent calls.
Return NULL if passed account is not long enough or NULL.
See cgi_validate_account
and cgi_strip_dashes.
void cgi_free_path_info(char **path_info);
Free a path_info, as returned by cgi_path_info.
char *cgi_fts(char *str);
Format a table cell string.
char *cgi_get_date(void);
Get the system date in "DD-MON-YYYY" format from the
web server (local time(2) call).
char *cgi_get_date_time(void);
Get the system date in "DD-MON-YYYY HH24 MI SS" format from the
web server (local time(2) call).
char *cgi_get_ansi_date(void);
Get the system date in "YYYY-MM-DD" format from the
web server (local time(2) call).
char *cgi_get_ansi_date_time(void);
Get the system date in "YYYY-MM-DD HH:MM:SS" format from the
web server (local time(2) call).
char *cgi_getcookie(const char *key);
Get the value of a cookie.
Returns NULL if key not found.
The first found cookie is returned, in the case that there
are more than one. The list is reversed, so this amounts
to the last cookie value. This is important for last_update.
Two values in every cookie are user and password.
Passwords are encrypted. Use cgi_crypt
to decrypt a password before comparing it to user input.
void cgi_invalidate_cookies(void);
Invalidate all cookies sent by the browser.
In effect, this is a logout from the current app.
void cgi_header(const char *title);
Emit html header.
void cgi_icheckbox(const char *name);
Emit a "checkbox" input.
name - the 'name' of the "checkbox" input field.
The name is fed to cgi_form_datum.
void cgi_ihidden(const char *name);
Emit hidden "input" field. Name is fed to
cgi_form_datum.
void cgi_ipassword(const char *name);
Emit a password input.
name - the name of the password input field.
Name is not fed to
cgi_form_datum.
void cgi_iradio(const char *name, char *value, int checked);
Emit a "radio" input.
name - the 'name' of the "checkbox" input field.
This name is common to the group of radio buttons.
The name is fed to cgi_form_datum,
and overrides the checked flag if non-NULL.
value is the value for this button - eg: "yes", "no" or "maybe".
checked is this the default button.
The caller should use the values TRUE and FALSE, defined by the header.
A TRUE value indicates that this radio button is the current value
for the radio group. A FALSE value indicates that this radio button
isn't the current value for the radio group.
Only one radio button in the group may be checked.
There does not have to be any radio button in a group checked.
The browser standard says that in this case, the browser will use
the value of the first radio button as the value for the group.
That would generally be the one the upper left of the group.
struct sll *cgi_mks_iselect(char *entries[]);
Using a NULL terminated array of entries, create a list usable with
cgi_iselect.
Returns NULL if out of RAM (unlikely).
Entries are malloc'ed, and the list can be deleted with
sll_rmlist.
Each entry in the list becomes both key and datum.
Therefore the string that the user sees is the string that the
receiving program reads.
For example:
char *internet[] = {
"Alta Vista",
"CNNfn",
"Excite",
"Women.com",
NULL
};
...
cgi_iselect("Internet", cgi_mks_iselect(internet)));
...
This produces:
struct sll *cgi_mk_iselect(struct cgi_select_entries *entries[]);
Create a select list from an entry list.
Returns an sll list for use with cgi_iselect.
Returns NULL if out of RAM.
Entries are malloc'ed, and the list can be deleted with
sll_rmlist.
For example:
struct cgi_select_entries *Heroes[] = {
{ "Bruce", "Batman" },
{ "Peter", "Spider-Man" },
{ "Clark", "Superman" },
{ "Bruce", "The Hulk" },
{ NULL, NULL }
}
...
cgi_iselect("Internet", cgi_mk_iselect(Heroes)));
...
This uses the structure from cgi.h which looks like this:
struct cgi_select_entries {
char *key; /* Key - program visible. */
char *datum; /* Datum - user visible. */
};
This produces:
void cgi_iselect(const char *name, struct sll *opts);
Emit <select>...</select>. Name is fed to
cgi_form_datum.
If the selected option is in the list, it is used as the default value.
The datum part of each node of the linked list is the value that is
displayed, while the key is used as the value sent to the receiving
CGI program. The key value is never displayed.
One may use
cgi_mk_iselect or
cgi_mks_iselect
to construct the list.
A short example follows. The cgi_form_add
call shows how to have a
selected value for the pull down list. Without such a form variable,
a blank entry is added to the top of the list, and is selected.
#include <stdio.h>
#include <string.h>
#include "sll.h"
#include "cgi.h"
int main(void);
int
main()
{
struct sll *opts = NULL;
sll_add_item(&opts, strdup("Wilma"), strdup("Fred"));
sll_add_item(&opts, strdup("Betty"), strdup("Barney"));
sll_add_item(&opts, strdup("Pebbles"), strdup("Bam Bam"));
cgi_header("Rocks");
cgi_form("envform.cgi");
cgi_form_add("Flintstones", "Wilma");
cgi_iselect("Flintstones", opts);
puts("<br><input type=\"submit\">");
puts("</form>");
cgi_trailer();
return 0;
}
When this is run, a form is emitted which looks like this:
void cgi_iselects(const char *name, struct sll *opts);
Emit <select>...</select>. Name is fed to
cgi_form_datum.
If there is a Name form variable, then the value of that
variable is used as a default value for the select list. (This
presumes that the value matches an entry in the list).
The list format is the same as is returned by
cgi_msql,
cgi_osql and
cgi_psql.
The first column of each row is used as the non-displayed value
that is sent to the server, and the second column is used as the
displayed value that is not sent.
This version differs from the older
cgi_iselect
only in the format of the linked list. It should be noted that
cgi_iselect
historically predates
cgi_msql,
cgi_osql and
cgi_psql,
as well as
the libsll.a
2 dimensional list support routines.
Neither version is deprecated, though it is exepected that
cgi_iselects
will often be more convenient when used with
RDBMS databases.
A short example follows. The cgi_form_add
call shows how to have a
selected value for the pull down list. Without such a form variable,
a blank entry is added to the top of the list, and is selected.
#include <stdio.h>
#include <string.h>
#include "sll.h"
#include "cgi.h"
int main(void);
int
main()
{
struct sll *opts = NULL;
cgi_header("State");
cgi_plogin(NULL, NULL, NULL);
opts = cgi_psql("select state_code, state from states;");
cgi_form("envform.cgi");
cgi_form_add("state", "MI");
cgi_iselects("state", opts);
puts("<br><input type=\"submit\">");
puts("</form>");
cgi_trailer();
return 0;
}
This produces a form such as:
void cgi_itextarea(const char *name, const int rows, const int cols);
Emit textarea input field. Name is fed to
cgi_form_datum.
Use rows for the height of the box in lines.
Use cols for the width of the box in characters.
In a break with tradition,
both start and end for <textarea> are emitted.
void cgi_itextarea_spell(const char *name, const int rows, const int cols);
Emit textarea input field. Name is fed to
cgi_form_datum.
Use rows for the height of the box in lines.
Use cols for the width of the box in characters.
In a break with tradition,
both start and end for <textarea> are emitted.
After the textarea, emit any misspelled words.
See cgi_spell_check.
Requires local spell dictionary - app specific.
The file spell.dict must exist in same directory as cgi program.
void cgi_itext(const char *name);
Emit text input field. Name is fed to
cgi_form_datum.
void cgi_itextr(const char *name);
Emit text input field. Name is fed to
cgi_form_datum.
Right justify the text in the text box - for numerics.
void cgi_itext_size(const char *name, int size);
Emit text input field. Name is fed to
cgi_form_datum.
The size is the width of the text field.
void cgi_itextr_size(const char *name, int size);
Emit text input field. Name is fed to
cgi_form_datum.
The size is the width of the text field.
Right justify the text in the text box - for numerics.
The library may be compiled without Oracle support, in which
case, only gdbm login is supported.
char *cgi_mk_base_url(const char *ref, ...);
Generate a URL relative to the app's base directory.
ref can be NULL or "",
"@", which means the same thing as NULL,
or start with a '/'.
If the ref starts with a '/', then the path to the
cgi program is not omitted, and an absolute URL relative to
the document root is created.
The C compiler will probably emit warnings if you pass this
function NULL or the null string, "", so "@" is preferred.
If the CGI program is running on a server on port 80, the
port number is omitted in the URL.
If the CGI program is running on a secure site (https), or on
port 443, then URLs are generated with "https". The same
binary can emit correct URLs for secure and insecure servers.
Returns pointer to static data.
ref can be a printf(3) like format string, with
arguments to follow.
char *cgi_mk_help_url(void);
Generate a URL to point to the local help.
If the CGI program is running on a server on port 80, the
port number is omitted in the URL.
If the CGI program is running on a secure site (https), or on
port 443, then URLS are generated with "https". The same
binary can emit correct URLS for secure and insecure servers.
Returns pointer to static data.
char *cgi_mklower(char *str);
cgi_mklower - Convert a string to lower case in place.
char *cgi_mkupper(char *str);
Convert a string to UPPER CASE in place.
char *cgi_replace(char *str, int old, int new);
Replace all instances of old characters
with new character in given string.
struct sll *cgi_spell(char *str);
Return a list of unrecognized words.
Words are in the key fields of the list.
Words end with a null ('\0').
See cgi_spell_check.
Requires local spell dictionary - app specific.
The file spell.dict must exist in same directory as cgi program.
void cgi_spell_check(char *str);
Emit to stdout the unrecognized words.
See cgi_spell.
Requires local spell dictionary - app specific.
The file spell.dict must exist in same directory as cgi program.
char *cgi_mk_url(const char *ref, ...);
Generate a URL to point back here.
ref can be NULL, or the null string, "",
but should not start with a '/', eg: "edit/1".
Returns pointer to static data.
ref can be a printf(3) like format string, with
arguments to follow.
ref can be NULL or "",
but should not start with a '/', eg: "images/f.gif".
ref can also be "@", which means the same thing as NULL.
The C compiler will probably emit warnings if you pass this
function NULL or the null string, "", so "@" is preferred.
If the CGI program is running on a server on port 80, the
port number is omitted in the URL.
If the CGI program is running on a secure site (https), or on
port 443, then URLS are generated with "https". The same
binary can emit correct URLs for secure and insecure servers.
void cgi_prompt(char *prompt);
Emit a prompt, creating a table cell.
This uses the white on blue color scheme, with a right justified prompt.
void cgi_oclose(void);
Close an Oracle database connection.
Databases are opened with cgi_ologin.
int cgi_ologin(const char *dbname, const char *user, const char *passwd);
Open an Oracle database.
Return TRUE if connected.
Return FALSE if not connected.
struct sll *cgi_osql(char *sql);
Execute a dynamic Oracle SQL statement.
This may be a select, update, insert, or
delete.
Assumes you are already connected, via
cgi_ologin.
The SQL statement may be UPPER or lower case.
Terminate SQL statements with a semicolon.
Terminate PL/SQL blocks (which can contain embedded semicolons)
with a slash (/).
Return NULL on error.
Errors are reported by using calls in liberr.
For select statements,
data is returned in a list of lists, using libsll.
This amounts to a dynamic two dimensional array.
Each returned row is a list.
The outer list contains only lists.
The lists are pointed to using the key field of the outer list.
The first row is a list of headers, or column titles.
The rest of the rows are data from the query.
For update, delete, or insert statements,
the returned list has one entry, whose key field
is a number encoded as a string. This number reflects the number
of rows that were processed by the statement.
For example, if a delete statement removes ten rows from
a table, the number would be ten.
The Oracle SQL syntax for changing a column name in a select
is to follow the column name with the alias. The alias may be
in double quotes. For example:
select chipsoz \"Chips (OZ)\" from chips;
This is handy when using
cgi_table.
If the database transaction is successful, a commit is issued.
void cgi_osql_print(struct sll *list);
Print osql output to stdout, formatted for a terminal.
This is likely for debugging.
Usage is to call cgi_msql,
cgi_osql
or cgi_psql
with a select statement,
then call this function with the list.
int cgi_mlogin(char *pghost, char *dbName);
Log into the Mini SQL database.
Host and database name may be NULL, and may default
to the uittinet.accountsupportmysql.com (using Unix domain sockets), and web user database.
Returns 0 for success, -1 for error.
struct sll *cgi_msql(char *sql);
Perform the sql string.
Allows a terminating semicolon, even though MSQL generally does not.
Only one statement per call is allowed.
Return NULL for error.
This routine is intended to be compatible with
cgi_osql and
cgi_psql, in the sense that
the same SQL commands are supported, and yield the same
list results. However, Mini SQL does not support PL/SQL.
Further, version two does not support aggregates, such as
sum, count, min, max. Use single quotes for strings.
To get the effect of min and max, you can use order by as
follows:
select NAME from place order by NAME desc limit 1;
void cgi_mclose(void);
Close the connection to the database and cleanup.
void cgi_inserts_msql(struct sll *sp);
From the output of cgi_osql or cgi_psql, print msql insert statements,
suitable for the msql command line client. This has been used
to move data from an Access database to an MSQL database using
a CSV file. It was painful, and the tool requires that the resulting
file be edited a little before being run. Still, the bulk of the work was
OK.
int cgi_plogin(char *pghost, char *pgport, char *dbName);
Log into the PostgreSQL database.
Host, port and database name may be NULL, and may default
to the uittinet.accountsupportmysql.com, correct local PostgreSQL port, and web user database.
Returns 0 for success, -1 for error.
struct sll *cgi_psql(char *sql);
Perform the sql string.
Return NULL for error.
This routine is intended to be compatible with
cgi_osql, in the sense that
the same SQL commands are supported, and yield the same
list results. However, PostgreSQL does not support PL/SQL.
The PostgreSQL SQL syntax for changing a column name in a select
is to follow the column name with the keyword "as" followed by the alias.
The alias may be in double quotes. For example:
select chipsoz as \"Chips (OZ)\" from chips;
This is handy when using
cgi_table.
void cgi_pclose(void);
Close the connection to the database and cleanup.
struct sll *cgi_page_children(struct cgi_page tbl[], char *page);
Return all the children of a page. The page names are in the
key fields of the list. The page aliases are in the
datum fields of the list.
See cgi_page_nav for details.
void cgi_page_content(struct cgi_page tbl[], char *page);
Call the function for the current page. The functions are registered
int the cgi_page array.
See cgi_page_nav for details.
int cgi_page_header(struct cgi_page tbl[], char *page);
Emit the header for the page.
See cgi_page_nav for details.
Returns TRUE if the page can't be found.
This might indicate an internal error.
void cgi_page_index(struct cgi_page tbl[]);
Emit an index for the app.
The index, like an index in a book, is alphabetized.
However, the description is also emitted.
If the description is NULL in the navigation table, that
page is omitted. This is useful if, for example, it is desired to
have automatic navigation to a page used for submission, but
where it makes no sense having the user navigate there without
a form.
See cgi_page_nav for details.
struct cgi_page *cgi_page_lookup(struct cgi_page tbl[], char *page);
Find the cgi_page entry for a page.
See cgi_page_nav for details.
void cgi_page_nav(struct cgi_page tbl[], char *page);
Emit the navigation bar for the current page.
tbl is an array of struct cgi_page.
It contains application structure info.
page is the name of the current page. This
name is used to identify the page to the application.
Names are used in href's to the application as the first
path information element.
The cgi_page structure:
struct cgi_page {
char *parent; /* Internal name of parent page "main" */
char *page; /* Internal name of the page "check_bal" */
char *page_alias; /* May have spaces in it "Check Balance" */
char *help; /* Help name for page "check_bal.shtml" */
void (*func)(void); /* page handler routine. */
char *title; /* Title for page. */
char *desc; /* Description. NULL for don't display. */
};
Note that in the example below, the Checking Account Balance and
Visa Account Balance do not appear in the top level menu, as
generated by cgi_page_index.
It is generally desireable to omit pages that take form data from
a previous page. These pages will not have such data when the
navigation is a simple href.
struct cgi_page tbl[] = {
{ "top", "top", "Top", "top_help.shtml",
top, "Top", "Top Page" },
{ "top", "check", "Check", "check_help.shtml",
check, "Check", "Checking Account" },
{ "check", "checkbal", "Checking Acocunt Balance", "checkbal_help.shtml",
checkbal, "Checking Blance", NULL },
{ "top", "visa", "Visa", "visa_help.shtml",
visa, "Visa", "Visa Account" },
{ "visa", "visabal", "Visa Account Balance", "visabal_help.shtml",
visabal, "Visa Balance", NULL },
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }
};