1947 lines
39 KiB
C++
1947 lines
39 KiB
C++
#include <sqlext.h>
|
|
#include <netdb.h>
|
|
#include <utime.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/tcp.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <stdarg.h>
|
|
#include "smtp.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "cgi.h"
|
|
#include <regex.h>
|
|
|
|
#include "safestring.h"
|
|
#include "cfg.h"
|
|
#include "clog.h"
|
|
|
|
#include "util.h"
|
|
#include "timer.h"
|
|
|
|
extern char SENDMAIL[];
|
|
|
|
int GetParam(char * params, char _name[], char value[], int valuelen, char ** end /*= NULL*/)
|
|
// *end is the first character after the end of the value
|
|
{
|
|
// logfmt( FLOG_MAX, "::GetParam( params='%s', name='%s', sz=%d )", params, _name, valuelen );
|
|
|
|
char *c, *cbeg, *cend, *vc;
|
|
unsigned int ch, len;
|
|
char name[50];
|
|
value[0] = 0;
|
|
|
|
snprintf( name, sizeof(name), "%s=", _name );
|
|
|
|
// logfmt( FLOG_MAX, "name=%s, params=%s", name, params );
|
|
|
|
|
|
if ( strncasecmp( name, params, strlen(name) ) == 0 )
|
|
{
|
|
cbeg = params + strlen( name );
|
|
cend = params + strcspn( params, "&;" );
|
|
// logfmt( FLOG_MAX, "cbeg=%s, len=%d", cbeg, cend-cbeg );
|
|
}
|
|
else
|
|
{
|
|
snprintf( name, sizeof(name), "&%s=", _name );
|
|
c = strcasestr( params, name );
|
|
if (!c )
|
|
{
|
|
snprintf( name, sizeof(name), " %s=", _name );
|
|
c = strcasestr( params, name );
|
|
}
|
|
if (!c )
|
|
{
|
|
snprintf( name, sizeof(name), "\n%s=", _name );
|
|
c = strcasestr( params, name );
|
|
}
|
|
if (!c)
|
|
return 0;
|
|
|
|
cbeg = c + strlen( name );
|
|
c++;
|
|
cend = c + strcspn( c, "&;" );
|
|
//logfmt( FLOG_MAX, "" );
|
|
}
|
|
|
|
// Ready to deal with '%' and '+' -- urldecode
|
|
|
|
c = cbeg; vc = value;
|
|
|
|
char save = *cend;
|
|
*cend = 0;
|
|
urldecode( cbeg, value, valuelen );
|
|
*cend = save;
|
|
|
|
|
|
// Strip trailing spaces
|
|
//logfmt( FLOG_MAX, "" );
|
|
|
|
while ( strlen(value)>0 && value[ strlen(value)-1 ] == ' ' )
|
|
value[ strlen(value)-1 ] = 0;
|
|
|
|
if (end)
|
|
*end = cend;
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
bool initcgilib(int log = 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
char * strlower( const char * str, char * res )
|
|
{
|
|
int len = strlen(str);
|
|
|
|
for ( int i=0; i<=len; i++ )
|
|
{
|
|
res[i] = tolower( str[i] );
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
/* Class definitions */
|
|
|
|
|
|
C_CGI_Form::C_CGI_Form( char * _dir, char * _template_file, char * _global_template/*=NULL*/, int _argc/*=0*/, char **_argv/* = NULL*/ )
|
|
|
|
{
|
|
|
|
//logfmt( FLOG_MAX, "C_CGI_Form constructor" );
|
|
|
|
sequence = SEQ_NONE;
|
|
|
|
dir = strdup( _dir );
|
|
|
|
if (_global_template)
|
|
global_template = strdup(_global_template);
|
|
else
|
|
global_template = NULL;
|
|
|
|
if ( getenv("SCRIPT_NAME") )
|
|
{
|
|
argc = _argc; argv = _argv;
|
|
char pars[16096]; pars[sizeof(pars)-1] = 0;
|
|
|
|
if ( !fgets( pars, sizeof(pars), stdin ) )
|
|
{
|
|
method = METHOD_GET;
|
|
|
|
char * qs = getenv("QUERY_STRING");
|
|
if ( qs && (strlen(qs)>0) )
|
|
params = strdup( qs );
|
|
else
|
|
{
|
|
params = strdup( "" );
|
|
// LOG( "No parameters", LOG_FATAL );
|
|
}
|
|
}
|
|
else // method POST
|
|
{
|
|
method = METHOD_POST;
|
|
|
|
//log.logfmt( FLOG_MAX, "strlen(pars)=%d, pars=%s", strlen(pars), pars );
|
|
params = strdup(pars);
|
|
if (!params)
|
|
{
|
|
logfmt( FLOG_MAX, "strdup failed" );
|
|
params = strdup("");
|
|
}
|
|
}
|
|
|
|
// log.logfmt( FLOG_MAX, pars );
|
|
|
|
// Uncomment below is you want to see what is being passed from the browser
|
|
|
|
// if ( params[0] ) //LOG( params, LOG_COMMAND );
|
|
// log.logfmt( FLOG_MAX, "%s", params );
|
|
}
|
|
else
|
|
{
|
|
method = METHOD_NONE;
|
|
params = strdup( "" );
|
|
}
|
|
|
|
template_file = strdup(_template_file);
|
|
nlists = 0;
|
|
|
|
|
|
#ifdef WITH_LANGUAGE
|
|
|
|
language[0] = 0;
|
|
|
|
char tmp_lang[10];
|
|
|
|
GetParam( "lang", tmp_lang, sizeof(tmp_lang) );
|
|
|
|
if ( reg_match( tmp_lang, "[[:alpha:]_-]+" ) )
|
|
{
|
|
logfmt( FLOG_MAX, "Language given as a parameter: %s", tmp_lang );
|
|
|
|
char expires[50] = "", domain[50] = "chiefsoft.com";
|
|
|
|
// determine the domain name
|
|
|
|
char * server_name = getenv( "SERVER_NAME" );
|
|
if ( server_name )
|
|
{
|
|
strsafecpy( domain, server_name, sizeof(domain) );
|
|
tolower( domain );
|
|
if ( strncasecmp( domain, "www.", 4 )==0 )
|
|
memmove( domain, &domain[4], strlen(domain)-4+1 );
|
|
}
|
|
else
|
|
logfmt( logWARNING, "Environment variable SERVER_NAME not found" );
|
|
|
|
|
|
int cookie_duration = 365*24*60; // default is now 24 hours x 365 = 1 year
|
|
time_t now = time( NULL ); now += cookie_duration*60; // cookie_duration is in minutes
|
|
strftime( expires, sizeof(expires), "; expires=%a, %d-%b-%Y %X GMT", gmtime( &now ) );
|
|
|
|
logfmt( FLOG_MAX, "DEBUG" );
|
|
|
|
send_header( "Set-Cookie: lang=%s; path=/; domain=%s%s", tmp_lang, domain, expires );
|
|
logfmt( FLOG_MAX, "DEBUG" );
|
|
logfmt( FLOG_MAX, "Set-Cookie: lang=%s; path=/; domain=%s%s", tmp_lang, domain, expires );
|
|
logfmt( FLOG_MAX, "DEBUG" );
|
|
|
|
strsafecpy( language, tmp_lang, sizeof( language ) );
|
|
logfmt( FLOG_MAX, "DEBUG" );
|
|
}
|
|
else
|
|
{
|
|
char * cookie = getenv( "HTTP_COOKIE" );
|
|
if ( cookie )
|
|
{
|
|
::GetParam( cookie, "lang", tmp_lang, sizeof( tmp_lang ) );
|
|
|
|
if ( reg_match( tmp_lang, "[[:alpha:]_-]+" ) )
|
|
{
|
|
logfmt( FLOG_MAX, "Language found in a cookie: %s", tmp_lang );
|
|
strsafecpy( language, tmp_lang, sizeof( language ) );
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif
|
|
};
|
|
|
|
|
|
|
|
C_CGI_Form::~C_CGI_Form()
|
|
{
|
|
for ( int i=0; i<nlists; i++ )
|
|
if ( lists[i] ) delete lists[i]; // maybe zero out lists[i].form?
|
|
|
|
free( dir );
|
|
free( template_file );
|
|
free( params );
|
|
if ( global_template ) free( global_template );
|
|
|
|
}
|
|
|
|
|
|
void CatFile( char * fname, FILE * fout )
|
|
{
|
|
FILE * f = fopen( fname, "r" );
|
|
|
|
if (!f)
|
|
{
|
|
logfmt( logWARNING, "Couldn't open included file '%s'", fname );
|
|
|
|
return;
|
|
}
|
|
|
|
char buf[1024];
|
|
int read;
|
|
|
|
do {
|
|
read = fread( buf, 1, sizeof(buf), f );
|
|
fwrite( buf, 1, read, fout );
|
|
|
|
} while ( read==sizeof(buf) );
|
|
|
|
fclose( f );
|
|
}
|
|
|
|
char * C_CGI_Form::FormFile( char * fname )
|
|
{
|
|
logfmt( FLOG_MAX, "CGI Parsing: %s", fname );
|
|
|
|
char * result = NULL;
|
|
struct stat stats;
|
|
if ( stat(fname, &stats)==-1 )
|
|
{
|
|
logfmt( FLOG_MAX, "stat() error: %s, '%s'", strerror(errno), fname );
|
|
// delete filename;
|
|
// return 0;
|
|
return strdup("Template read error");
|
|
|
|
}
|
|
|
|
FILE * f = fopen( fname, "r" );
|
|
|
|
// delete filename;
|
|
|
|
if (!f)
|
|
{
|
|
logfmt( logERROR, "Could not read template '%s'", fname );
|
|
|
|
return strdup("Template read error");
|
|
}
|
|
|
|
char * buf = (char *)malloc(stats.st_size+1);
|
|
if (!buf)
|
|
{
|
|
fclose( f );
|
|
logfmt( logERROR, "Could not allocate %d bytes form template '%s'", stats.st_size+1, fname );
|
|
return 0;
|
|
}
|
|
|
|
fread( buf, 1, stats.st_size, f );
|
|
fclose( f );
|
|
|
|
buf[stats.st_size] = 0;
|
|
|
|
|
|
// Find out if this template has a parent and insert it into parent as necessary
|
|
|
|
char ret[100], *start = buf;
|
|
|
|
if ( reg_match( buf, "^([[:alnum:][:punct:]-]+\\[[[:alnum:]_]+\\]).*", ret, sizeof(ret) ) )
|
|
{
|
|
logfmt( FLOG_MAX, "TODO: Parent template: %s", ret );
|
|
|
|
start += strlen(ret);
|
|
|
|
char pfname[100], varname[50], pfname_full[200];
|
|
|
|
reg_match( ret, "^([[:alnum:][:punct:]-]+)\\[[[:alnum:]_]+\\]$", pfname, sizeof(pfname) );
|
|
reg_match( ret, "^[[:alnum:][:punct:]-]+\\[([[:alnum:]_]+)\\]$", varname, sizeof(varname) );
|
|
|
|
logfmt( FLOG_MAX, "file=%s, name=%s", pfname, varname );
|
|
|
|
LetStr( varname, start );
|
|
|
|
free(buf);
|
|
|
|
snprintf( pfname_full, sizeof(pfname_full), TMPL_PREFIX"/tmpl/%s", pfname );
|
|
|
|
logfmt( FLOG_MAX, "Loading Template '%s'", pfname_full );
|
|
|
|
buf = FormFile( pfname_full );
|
|
|
|
return buf;
|
|
}
|
|
|
|
logfmt( FLOG_MAX, "Template '%s' loaded: %d bytes", fname, stats.st_size );
|
|
|
|
|
|
// Last step: parse and substutute
|
|
|
|
result = RFormBuffer( start );
|
|
free( buf );
|
|
|
|
logfmt( FLOG_MAX, "Returning from FormFile()" );
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
int regall( const char * regex, const char * string, size_t nmatch, regmatch_t pmatch[] )
|
|
{
|
|
regex_t compiled;
|
|
int r;
|
|
|
|
r = regcomp( &compiled, regex, REG_EXTENDED );
|
|
if ( r ) return r;
|
|
|
|
r = regexec( &compiled, string, nmatch, pmatch, 0 );
|
|
|
|
regfree( &compiled );
|
|
|
|
return r;
|
|
}
|
|
|
|
|
|
void C_CGI_Form::GetNextVariable( TList * &cur, char * &c1, char * &c, char * listname, int listi )
|
|
{
|
|
c = strstr( c1, "{{" );
|
|
|
|
if (!c)
|
|
{
|
|
cur = Add( cur, c1, strlen(c1) ); // end
|
|
return;
|
|
}
|
|
// LOG( "BP", LOG_MAX );
|
|
|
|
cur = Add( cur, c1, c-c1 );
|
|
c += 2;
|
|
|
|
// LOG( "BP", LOG_MAX );
|
|
// Check for recursive variables, i.e., {{text{{var2}}}}
|
|
// Find the corresponding right bracket '}}'
|
|
|
|
char *c2;
|
|
int level = 1, maxlevel = 1;
|
|
|
|
char * b1 = c, *b2;
|
|
for ( c2=b1; c2<c+strlen(c); c2++ )
|
|
{
|
|
// logfmt(FLOG_MAX, "*c2=%c", *c2 );
|
|
if ( *c2=='{' && *(c2+1)=='{' )
|
|
{
|
|
level++; c2++;
|
|
if ( level>maxlevel )
|
|
maxlevel = level;
|
|
}
|
|
else
|
|
if ( *c2=='}' && *(c2+1)=='}' )
|
|
{
|
|
level--; c2++;
|
|
// logfmt(FLOG_MAX, "level=%d", level );
|
|
}
|
|
if (!level) break;
|
|
}
|
|
// LOG( "BP", LOG_MAX );
|
|
|
|
if ( c2==c1+strlen(c1) ) // no closing }}
|
|
{
|
|
cur = Add( cur, c, strlen(c) ); // end
|
|
c = 0;
|
|
return;
|
|
}
|
|
// LOG( "BP", LOG_MAX );
|
|
|
|
c2--; *c2 = 0; c2+=2;
|
|
|
|
// logfmt( FLOG_MAX, "Looking at '%s'", c );
|
|
|
|
if ( maxlevel>1 ) // recursive call needed
|
|
{
|
|
// char *newbuf = new char[ c2-b1 ];
|
|
// memcpy( newbuf, b1, c2-b1-1 );
|
|
// newbuf[ c2-b1-1 ] = 0;
|
|
|
|
// LOG( "Recursive call", LOG_MAX );
|
|
c = RFormBuffer( c, listname, listi );
|
|
|
|
// delete newbuf;
|
|
}
|
|
|
|
c1 = c2;
|
|
}
|
|
|
|
char * C_CGI_Form::RFormBuffer( char * buf, char * listname /*= NULL*/, int listi /*= 0*/ )
|
|
{
|
|
// parse and substutute
|
|
|
|
char * c = buf, *c1=buf;
|
|
|
|
TList *top = new TList, *cur = top;
|
|
|
|
// LOG( "BP", LOG_MAX );
|
|
|
|
do {
|
|
c = strstr( c1, "{{" );
|
|
// logfmt( FLOG_MAX, c );
|
|
|
|
if (!c)
|
|
{
|
|
cur = Add( cur, c1, strlen(c1) ); // end
|
|
break;
|
|
}
|
|
// LOG( "BP", LOG_MAX );
|
|
|
|
cur = Add( cur, c1, c-c1 );
|
|
c += 2;
|
|
|
|
// LOG( "BP", LOG_MAX );
|
|
// Check for recursive variables, i.e., {{text{{var2}}}}
|
|
// Find the corresponding right bracket '}}'
|
|
|
|
char *c2;
|
|
int level = 1, maxlevel = 1;
|
|
|
|
char * b1 = c, *b2;
|
|
for ( c2=b1; c2<c+strlen(c); c2++ )
|
|
{
|
|
// logfmt(FLOG_MAX, "*c2=%c", *c2 );
|
|
if ( *c2=='{' && *(c2+1)=='{' )
|
|
{
|
|
level++; c2++;
|
|
if ( level>maxlevel )
|
|
maxlevel = level;
|
|
}
|
|
else
|
|
if ( *c2=='}' && *(c2+1)=='}' )
|
|
{
|
|
level--; c2++;
|
|
// logfmt(FLOG_MAX, "level=%d", level );
|
|
}
|
|
if (!level) break;
|
|
}
|
|
// LOG( "BP", LOG_MAX );
|
|
|
|
if ( c2==c1+strlen(c1) ) // no closing }}
|
|
{
|
|
cur = Add( cur, c, strlen(c) ); // end
|
|
break;
|
|
}
|
|
// logfmt( FLOG_MAX, "BP, *c2=%s, c=%s", c2, c );
|
|
|
|
c2--; *c2 = 0; c2+=2;
|
|
|
|
// logfmt( FLOG_MAX, "Looking at '%s'", c );
|
|
|
|
if ( maxlevel>1 ) // recursive call needed
|
|
{
|
|
// char *newbuf = new char[ c2-b1 ];
|
|
// memcpy( newbuf, b1, c2-b1-1 );
|
|
// newbuf[ c2-b1-1 ] = 0;
|
|
|
|
// LOG( "Recursive call", LOG_MAX );
|
|
c = RFormBuffer( c, listname, listi );
|
|
|
|
// delete newbuf;
|
|
}
|
|
|
|
// resolve result which should have no recursive variables
|
|
|
|
// LOG( "BP", LOG_MAX );
|
|
|
|
c1 = c2;
|
|
|
|
// char var[20000];
|
|
|
|
if (c[0]) // non-empty variable
|
|
{
|
|
// Let's see if a special command is given
|
|
if ( c[0] == '#' )
|
|
{
|
|
regmatch_t match[2*10];
|
|
regex_t compiled;
|
|
|
|
if ( !regall( "^#include file=\"([[:alnum:][:punct:] ]+)\"$", c, 2, match ) )
|
|
{
|
|
char fname[50];
|
|
int len = match[1].rm_eo-match[1].rm_so;
|
|
if ( len>=sizeof(fname) )
|
|
len = sizeof(fname)-1; // to be safe
|
|
|
|
strncpy( fname, &c[ match[1].rm_so ], len );
|
|
fname[ len ] = 0;
|
|
|
|
logfmt( FLOG_MAX, "Including file '%s'", fname );
|
|
|
|
char filename[100];
|
|
snprintf( filename, sizeof(filename), TMPL_PREFIX"/%s", fname );
|
|
|
|
char * tt = FormFile( filename );
|
|
cur = Add( cur, tt, strlen(tt) );
|
|
delete tt;
|
|
}
|
|
else
|
|
if ( !regall( "^#field_([[:alpha:]]+)[[:space:]]*\\([[:space:]]*([[:alnum:]_]+)[[:space:]]*,[[:space:]]*\"(.*)\"[[:space:]]*,[[:space:]]*([[:digit:]]+)[[:space:]]*,[[:space:]]*([[:digit:]]+)[[:space:]]*\\)[[:space:];]*$", c, 6, match ) )
|
|
{
|
|
char name[50], description[200], size[10], maxlen[10], type[20];
|
|
|
|
strnsafecpy( type, c+match[1].rm_so, match[1].rm_eo-match[1].rm_so, sizeof(type) );
|
|
strnsafecpy( name, c+match[2].rm_so, match[2].rm_eo-match[2].rm_so, sizeof(name) );
|
|
strnsafecpy( description, c+match[3].rm_so, match[3].rm_eo-match[3].rm_so, sizeof(description) );
|
|
|
|
strnsafecpy( size, c+match[4].rm_so, match[4].rm_eo-match[4].rm_so, sizeof(size) );
|
|
strnsafecpy( maxlen, c+match[5].rm_so, match[5].rm_eo-match[5].rm_so, sizeof(maxlen) );
|
|
|
|
LetStr( "__func_type", type );
|
|
LetStr( "__func_name", name );
|
|
LetStr( "__func_description", description );
|
|
LetStr( "__func_size", size );
|
|
LetStr( "__func_maxlen", maxlen );
|
|
|
|
logfmt( FLOG_MAX, "field_%s( %s, %s, %s, %s )", type, name, description, size, maxlen );
|
|
|
|
char filename[100];
|
|
snprintf( filename, sizeof(filename), TMPL_PREFIX"/%s", "field_text.func" );
|
|
|
|
char * tt = FormFile( filename );
|
|
cur = Add( cur, tt, strlen(tt) );
|
|
delete tt;
|
|
}
|
|
|
|
|
|
|
|
if ( regcomp( &compiled, "^#global file=\"([[:alnum:][:punct:] ]+)\"$", REG_EXTENDED ) != 0 )
|
|
{
|
|
logfmt( logWARNING, "regcomp returned non-0, ignoring command" );
|
|
}
|
|
else
|
|
{
|
|
size_t r = regexec( &compiled, c, 2, match, 0 );
|
|
if (r)
|
|
;
|
|
// { logfmt( logWARNING, "Command detected, but no match" ); }
|
|
else
|
|
{
|
|
char fname[50];
|
|
int len = match[1].rm_eo-match[1].rm_so;
|
|
if ( len>=sizeof(fname) )
|
|
len = sizeof(fname)-1; // to be safe
|
|
|
|
strncpy( fname, &c[ match[1].rm_so ], len );
|
|
fname[ len ] = 0;
|
|
|
|
GlobalTemplate( fname );
|
|
ParseGlobalTemplate();
|
|
}
|
|
|
|
}
|
|
|
|
regfree( &compiled );
|
|
}
|
|
else
|
|
// if (false)
|
|
if ( c[0]=='\\' ) // talking lists now
|
|
{
|
|
//logfmt( FLOG_MAX, "talking lists now" );
|
|
char listname[50];
|
|
// strsafecpy( listname, c+1, sizeof(listname) );
|
|
|
|
int len = strcspn( c+1, " }" );
|
|
strnsafecpy( listname, c+1, len, sizeof(listname) );
|
|
|
|
// Locate the list in the form object
|
|
|
|
int j;
|
|
for (j=0; j<nlists; j++)
|
|
if ( strcasecmp( lists[j]->listname, listname )==0 ) break;
|
|
|
|
if (j==nlists)
|
|
{
|
|
// logfmt( logWARNING, "List '%s' not found in form object", listname );
|
|
// continue;
|
|
}
|
|
else
|
|
logfmt( FLOG_MAX, "Processing list %s[%d]", listname, lists[j]->n );
|
|
|
|
|
|
// logfmt( FLOG_MAX, "c -> '%s'", c );
|
|
|
|
|
|
bool only_if_present = *(c+1+len) != 0;
|
|
|
|
// logfmt( FLOG_MAX, "only_if_present = '%d'", only_if_present );
|
|
|
|
c += strlen(c)+2; // set c to after {{\list 1}} // ???? = c2
|
|
// crash ^^^
|
|
// c1++;
|
|
|
|
char temp[100], temp1[100];
|
|
|
|
snprintf( temp, sizeof(temp), "{{/%s}}", listname );
|
|
char * listend = strcasestr( c, temp ); // c1
|
|
if (!listend)
|
|
{
|
|
logfmt( logWARNING, "End of list '%s' not found", temp );
|
|
continue;
|
|
// fprintf(fout, c1); // end
|
|
// break;
|
|
}
|
|
|
|
*listend = 0;
|
|
|
|
c1 = listend + strlen(temp); // point to after the list closing command
|
|
|
|
// is there an 'else' section ?? {{//list}}
|
|
snprintf( temp, sizeof(temp), "{{//%s}}", listname );
|
|
char * celse = strcasestr( c1, temp );
|
|
|
|
|
|
// 06-16-2002
|
|
|
|
snprintf( temp1, sizeof(temp1), "{{\\%s", listname );
|
|
char * cnextinst = strcasestr( c1, temp1 );
|
|
|
|
if ( cnextinst && (cnextinst<celse) ) // 'else' section belongs to the next occurence of the list
|
|
celse = NULL;
|
|
|
|
// end 06-16-2002
|
|
|
|
|
|
if ( only_if_present && j<nlists && !lists[j]->n )
|
|
{
|
|
if (!celse) continue;
|
|
*celse = 0;
|
|
|
|
char * tt = RFormBuffer( c1 );
|
|
cur = Add( cur, tt, strlen(tt) );
|
|
delete tt;
|
|
|
|
c1 = celse + strlen(temp);
|
|
|
|
continue;
|
|
}
|
|
|
|
if (celse) c1 = celse + strlen(temp);
|
|
|
|
|
|
// if there is no such list drop it
|
|
|
|
if ( j==nlists )
|
|
{
|
|
logfmt( FLOG_MAX, "List '%s' not found in form object. Skipping...", listname );
|
|
continue;
|
|
}
|
|
|
|
|
|
// now parse
|
|
|
|
char * c2;
|
|
|
|
// Skip all child lists before {{...}}
|
|
|
|
c2 = strstr( c, "{{\\" );
|
|
char * c3 = strstr( c, "{{...}}" );
|
|
if ( c2 && c3 && c2<c3 )
|
|
{
|
|
c2 += 3;
|
|
char skiplist[30];
|
|
int n = strcspn( c2, " }" );
|
|
if (n<sizeof(skiplist))
|
|
{
|
|
strncpy( skiplist, c2, n );
|
|
skiplist[n] = 0;
|
|
|
|
logfmt( FLOG_MAX, "Childlist '%s'. Skip.", skiplist );
|
|
|
|
char temp[40];
|
|
snprintf( temp, sizeof(temp), "{{/%s}}", skiplist );
|
|
|
|
// logfmt( FLOG_MAX, "Looking for '%s'", temp );
|
|
|
|
c2 = strcasestr( c2, temp );
|
|
if (c2)
|
|
c2 += n+5;
|
|
|
|
// logfmt( FLOG_MAX, "Continuing at '%s'", c2 );
|
|
|
|
}
|
|
}
|
|
else
|
|
c2 = c;
|
|
|
|
if (!c2)
|
|
c2 = c;
|
|
|
|
|
|
c2 = strstr( c2, "{{...}}" );
|
|
if (!c2) // no elements, list used as a block
|
|
{
|
|
logfmt( FLOG_MAX, "List '%s' does not contain any {{...}} -> used as a block", listname );
|
|
char * tt = RFormBuffer( c );
|
|
cur = Add( cur, tt, strlen(tt) );
|
|
delete tt;
|
|
continue;
|
|
}
|
|
|
|
|
|
*c2 = 0;
|
|
char * tt = RFormBuffer( c );
|
|
cur = Add( cur, tt, strlen(tt) );
|
|
delete tt;
|
|
c = c2+7;
|
|
|
|
c2 = strstr( c, "{{/...}}" );
|
|
if (!c2) // no element close directive
|
|
{
|
|
logfmt( logWARNING, "Element close directive for '%s' not found", listname );
|
|
|
|
char * tt = RFormBuffer( c );
|
|
cur = Add( cur, tt, strlen(tt) );
|
|
delete tt;
|
|
|
|
continue; // this is correct
|
|
}
|
|
*c2 = 0;
|
|
|
|
|
|
//logfmt( FLOG_MAX, "Processing list '%s' 5", listname );
|
|
|
|
//logfmt( FLOG_MAX, "Calling FormBuffer() for '%s'", c );
|
|
|
|
for ( int i=0; i< lists[j]->n; i++ )
|
|
{
|
|
char * ctemp = strdup( c );
|
|
|
|
if (ctemp)
|
|
{
|
|
char * tt = RFormBuffer( ctemp, listname, i );
|
|
cur = Add( cur, tt, strlen(tt) );
|
|
delete tt;
|
|
free( ctemp );
|
|
}
|
|
}
|
|
|
|
tt = RFormBuffer( c2+8 );
|
|
cur = Add( cur, tt, strlen(tt) );
|
|
delete tt;
|
|
|
|
continue;
|
|
}
|
|
|
|
else
|
|
{
|
|
char * c5;
|
|
|
|
if (!listname)
|
|
{
|
|
// logfmt( FLOG_MAX, "Getting variable '%s'", c);
|
|
|
|
// GetVariable( c, var, sizeof(var) );
|
|
// cur = Add( cur, var, strlen(var) );
|
|
|
|
c5 = GetVariable( c );
|
|
if (c5)
|
|
{ // 11-03-2002 Parse variable contents recursively
|
|
char * temp = strdup( c5 ); // to prevent damage to the buffer
|
|
char * c = RFormBuffer( temp );
|
|
free( temp ); // 11-03-2002 This stuff rocks da house
|
|
|
|
cur = Add( cur, c, strlen(c) );
|
|
delete c;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char buf[100];
|
|
snprintf( buf, sizeof(buf), "__list_%s_%d_%s",
|
|
listname, listi, c );
|
|
|
|
// logfmt( FLOG_MAX, "Fetching variable '%s'", buf );
|
|
c5 = GetVariable( buf );
|
|
if (!c5)
|
|
c5 = GetVariable( c );
|
|
if (c5)
|
|
cur = Add( cur, c5, strlen(c5) );
|
|
|
|
}
|
|
|
|
if ( *c1=='/' && *(c1+1)=='\\' && *(c1+2)=='{' )
|
|
{
|
|
c1 += 2;
|
|
GetNextVariable( cur, c1, c, listname, listi );
|
|
if (!c5)
|
|
{
|
|
if ( c5 = GetVariable( c ) )
|
|
cur = Add( cur, c5, strlen(c5) );
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// c1 += 2;
|
|
|
|
} while ( 1 );
|
|
|
|
// LOG( "BP3", LOG_MAX );
|
|
|
|
// PrintList( top );
|
|
|
|
ULONG len=0; cur = top;
|
|
|
|
while (cur->text)
|
|
{
|
|
len += strlen(cur->text);
|
|
cur = cur->next;
|
|
}
|
|
|
|
// logfmt( FLOG_MAX, "Allocating %lu bytes", len+1 );
|
|
|
|
char * ret = new char[len+1];
|
|
|
|
if (!ret) logfmt( logWARNING, "Not enough memory allocating %lu bytes", len );
|
|
|
|
cur = top; ULONG pos=0;
|
|
TList * prev;
|
|
|
|
while ( cur && cur->text)
|
|
{
|
|
// logfmt( FLOG_MAX, "Copying %d chars at %d..", strlen( cur->text ), pos );
|
|
memcpy( &ret[pos], cur->text, strlen( cur->text ) );
|
|
pos += strlen( cur->text );
|
|
|
|
delete cur->text;
|
|
prev = cur;
|
|
cur = cur->next;
|
|
delete prev;
|
|
}
|
|
// LOG( "BP5", LOG_MAX );
|
|
|
|
ret[pos] = 0;
|
|
|
|
|
|
|
|
// Fold();
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
char * C_CGI_Form::FormBuffer( char * buf )
|
|
{
|
|
char * ret;
|
|
char * c = strdup( buf );
|
|
|
|
ret = RFormBuffer( c );
|
|
free( c );
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
void C_CGI_Form::ParseGlobalTemplate( char * fname /*= NULL*/ )
|
|
{
|
|
char * global_template = fname?fname:this->global_template;
|
|
|
|
|
|
logfmt( FLOG_MAX, "ParseGlobalTemplate( \"%s\" )", global_template );
|
|
struct stat stats;
|
|
if ( stat(global_template, &stats)==-1 )
|
|
{
|
|
logfmt( FLOG_MAX, "stat() error: %s, '%s'", strerror(errno), global_template );
|
|
return;
|
|
}
|
|
|
|
char * buf = (char *)malloc(stats.st_size+1);
|
|
|
|
if (!buf)
|
|
{
|
|
logfmt( logERROR, "Could not allocate %d bytes for global template %s", stats.st_size+1, global_template );
|
|
return;
|
|
}
|
|
|
|
FILE * f = fopen( global_template, "r" );
|
|
if (!f)
|
|
{
|
|
logfmt( logERROR, "Could not read global template '%s'", global_template );
|
|
return;
|
|
}
|
|
|
|
fread( buf, 1, stats.st_size, f );
|
|
buf[stats.st_size] = 0;
|
|
fclose( f );
|
|
|
|
int i;
|
|
char s1[30], s2[30], *c1, *c2;
|
|
|
|
for (i=1; 1; i++ )
|
|
{
|
|
snprintf( s1, sizeof(s1), "<!--section%d-->", i );
|
|
snprintf( s2, sizeof(s2), "<!--/section%d-->", i );
|
|
c1 = strstr(buf, s1);
|
|
c2 = strstr(buf, s2);
|
|
if (!c1 || !c2) break;
|
|
c1 += strlen(s1);
|
|
|
|
snprintf( s2, sizeof(s2), "section%d", i );
|
|
|
|
char * buf = new char[c2-c1+1];
|
|
memcpy( buf, c1, c2-c1 );
|
|
buf[c2-c1] = 0;
|
|
char * temp = RFormBuffer( buf );
|
|
delete buf;
|
|
LetStr( s2, temp );
|
|
free( temp );
|
|
|
|
// LetStr( s2, c1, c2-c1 );
|
|
|
|
// logfmt( FLOG_MAX, "%s=%s", s2, GetVariable(s2) );
|
|
|
|
}
|
|
|
|
logfmt( FLOG_MAX, "%d sections found", i-1 );
|
|
|
|
free( buf );
|
|
}
|
|
|
|
|
|
bool C_CGI_Form::ParseNewTemplate( char * fname /*= NULL*/ )
|
|
// returns false if this seems to be wrong format template
|
|
{
|
|
char * global_template = fname?fname:this->global_template;
|
|
|
|
logfmt( FLOG_MAX, "ParseNewTemplate( \"%s\" )", global_template );
|
|
struct stat stats;
|
|
if ( stat(global_template, &stats)==-1 )
|
|
{
|
|
// delete filename;
|
|
|
|
logfmt( FLOG_MAX, "stat() error: %s, '%s'", strerror(errno), global_template );
|
|
return true;
|
|
}
|
|
|
|
char * buf = (char *)malloc(stats.st_size+1);
|
|
|
|
if (!buf)
|
|
{
|
|
// delete filename;
|
|
logfmt( logERROR, "Could not allocate %d bytes for global template %s", stats.st_size+1, global_template );
|
|
return true;
|
|
}
|
|
|
|
FILE * f = fopen( global_template, "r" );
|
|
|
|
// delete filename;
|
|
|
|
if (!f)
|
|
{
|
|
logfmt( logERROR, "Could not read global template '%s'", global_template );
|
|
return true;
|
|
}
|
|
|
|
fread( buf, 1, stats.st_size, f );
|
|
buf[stats.st_size] = 0;
|
|
fclose( f );
|
|
|
|
|
|
logfmt( FLOG_MAX, "New template loaded '%s', size=%d bytes", global_template, stats.st_size );
|
|
|
|
int i;
|
|
char name[50], *c1, *c2;
|
|
|
|
c1 = buf;
|
|
if ( c1[0]!='[' )
|
|
{
|
|
c1 = strstr( c1, "\n[" );
|
|
if (c1) c1++;
|
|
}
|
|
|
|
bool result = true;
|
|
|
|
if ( !c1 )
|
|
result = false;
|
|
|
|
while (c1)
|
|
{
|
|
c1++;
|
|
c2 = strchr( c1, ']' );
|
|
strnsafecpy( name, c1, c2-c1, sizeof(name) );
|
|
c2++;
|
|
c1 = c2+strspn( c2, " \t\r\n" ); // ignore initial spaces
|
|
|
|
if ( *c1=='[' ) // blank variable
|
|
{
|
|
LetStr( name, "" );
|
|
continue;
|
|
}
|
|
|
|
c2 = strstr( c1, "\n[" );
|
|
if (c2)
|
|
{
|
|
*c2 = 0;
|
|
c2++;
|
|
}
|
|
|
|
char * c = (c2?c2:(buf+stats.st_size)) -1;
|
|
|
|
while ( c>=c1 && strchr( " \t\r\n", *c ) )
|
|
{
|
|
*c = 0; c--;
|
|
}
|
|
|
|
LetStr( name, c1 = RFormBuffer(c1) );
|
|
free( c1 );
|
|
|
|
// logfmt( FLOG_MAX, "FOUND: %s, len = '%d'", name, strlen(GetVariable(name)) );
|
|
|
|
c1 = c2;
|
|
}
|
|
|
|
|
|
free( buf );
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
bool C_CGI_Form::Form( FILE * fout )
|
|
{
|
|
fprintf( fout, "Content-Type: text/html; charset=UTF-8\n\n");
|
|
|
|
if (global_template) ParseGlobalTemplate();
|
|
|
|
CTimer timer;
|
|
|
|
char * c = FormFile( template_file );
|
|
|
|
logfmt( logINFO, "FormFile() took %.3f sec", timer.elapsed()/1e6 );
|
|
logfmt( logINFO, "strlen(c)=%d", strlen(c) );
|
|
|
|
int r;
|
|
if ( r = ferror( fout ) ) logfmt( logWARNING, "ferror() returned %d: %s", r, strerror(r) );
|
|
fprintf( fout, "%s", c );
|
|
logfmt( FLOG_MAX, "DEBUG" );
|
|
if ( r = ferror( fout ) ) logfmt( logWARNING, "ferror() returned %d: %s", r, strerror(r) );
|
|
fflush( fout );
|
|
logfmt( FLOG_MAX, "DEBUG" );
|
|
delete c;
|
|
|
|
logfmt( logINFO, "fprintf()/fflush() took %.3f sec", timer.elapsed()/1e6 );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool C_CGI_Form::Form( FILE * fout, char * template_file )
|
|
{
|
|
char * c = FormFile( template_file );
|
|
fprintf( fout, c ); fflush( fout );
|
|
delete c;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
int C_CGI_Form::GetParam( char name[], char *value, int valuelen, char ** end /*= NULL*/, char * start /*= NULL*/ )
|
|
{
|
|
// logfmt( FLOG_MAX, "C_CGI_Form::GetParam( name='%s', sz=%d )", name, valuelen );
|
|
// printf("C_CGI_Form() on params=%s \n", params);
|
|
|
|
int result;
|
|
char * qs;
|
|
|
|
if (start)
|
|
result = ::GetParam( start, name, value, valuelen, end );
|
|
else
|
|
{
|
|
qs = getenv("QUERY_STRING");
|
|
|
|
//logfmt( FLOG_MAX, "qs='%s'", qs );
|
|
|
|
if ( !qs || !(result = ::GetParam( qs, name, value, valuelen, end ) ) )
|
|
result = ::GetParam( params, name, value, valuelen, end );
|
|
}
|
|
|
|
// if ( !value[0] )
|
|
|
|
|
|
// logfmt( FLOG_MAX, "GetParam returns '%s'='%s', qs='%s'", name, value, qs );
|
|
|
|
return result;
|
|
}
|
|
|
|
int C_CGI_Form::GetParamMul( char name[], TList ** list )
|
|
{
|
|
char value[100];
|
|
int r, i=0;
|
|
|
|
char * qs = params;
|
|
|
|
logfmt( FLOG_MAX, "params=%s", qs );
|
|
// getenv("QUERY_STRING"); if (!qs) qs = params;
|
|
|
|
char *start = qs, * end;
|
|
|
|
TList *top=NULL, *cur=NULL, *tmp;
|
|
|
|
do {
|
|
r = GetParam( name, value, sizeof(value), &end, start );
|
|
logfmt( FLOG_MAX, "%s[%d]=%s", name, i, value );
|
|
start = end;
|
|
if (r)
|
|
{
|
|
tmp = new TList;
|
|
tmp->text = strdup( value );
|
|
tmp->next = NULL;
|
|
|
|
if (cur)
|
|
{
|
|
cur->next = tmp;
|
|
cur = cur->next;
|
|
}
|
|
else
|
|
top = cur = tmp;
|
|
|
|
i++;
|
|
}
|
|
} while (r);
|
|
|
|
if (list) *list = top;
|
|
return i;
|
|
}
|
|
|
|
|
|
int C_CGI_Form::GetCommand( char * commands[], int n )
|
|
{
|
|
char cmd[30];
|
|
|
|
cmd[0] = 0;
|
|
|
|
/* LOG( argv[1], LOG_MAX );
|
|
if (argc>1)
|
|
{
|
|
::GetParam( argv[1], "action", cmd, sizeof(cmd) );
|
|
if (cmd[0])
|
|
logfmt( FLOG_MAX, "Command given as a parameter: %s", cmd);
|
|
}*/
|
|
|
|
/*
|
|
char * qs = getenv("QUERY_STRING");
|
|
if (qs)
|
|
{
|
|
::GetParam( qs, "action", cmd, sizeof(cmd) );
|
|
if (cmd[0])
|
|
logfmt( FLOG_MAX, "Command given as a parameter: %s", cmd);
|
|
}
|
|
|
|
if ( !cmd[0] )*/
|
|
|
|
GetParam( "action", cmd, sizeof(cmd) );
|
|
|
|
if ( !cmd[0] )
|
|
{
|
|
char * c;
|
|
|
|
c = strcasestr( params, ".x=" );
|
|
if (!c)
|
|
return -1;
|
|
|
|
char * c1 = strchr( c, '&' );
|
|
if (!c1) return -1;
|
|
|
|
|
|
c1++;
|
|
c = strchr( c1, '.' );
|
|
if (!c) return -1;
|
|
|
|
|
|
if (c-c1 < sizeof(cmd) )
|
|
strncpy( cmd, c1, c-c1 );
|
|
else
|
|
return -1;
|
|
|
|
cmd[c-c1] = 0;
|
|
}
|
|
|
|
//logfmt( FLOG_MAX, "command=%s", cmd); // LOG
|
|
|
|
int i;
|
|
|
|
for ( i=0; i<n; i++ )
|
|
{
|
|
if ( strcasecmp(cmd, commands[i])==0 )
|
|
break;
|
|
}
|
|
|
|
if (i==n)
|
|
return -1;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
int C_CGI_Form::GetScreen( char * screens[], int n, const char * scrs /*= NULL*/ )
|
|
{
|
|
char cmd[30];
|
|
|
|
if ( !scrs )
|
|
{
|
|
|
|
char * qs = getenv("QUERY_STRING");
|
|
if (qs)
|
|
{
|
|
::GetParam( qs, "screen", cmd, sizeof(cmd) );
|
|
if (cmd[0])
|
|
logfmt( FLOG_MAX, "Screen given as a parameter: %s", cmd);
|
|
}
|
|
|
|
if (!cmd[0])
|
|
GetParam( "screen", cmd, sizeof(cmd) );
|
|
|
|
if ( !cmd[0] )
|
|
return -1;
|
|
|
|
}
|
|
else
|
|
strsafecpy( cmd, scrs, sizeof(scrs) );
|
|
|
|
int i;
|
|
|
|
for ( i=0; i<n; i++ )
|
|
{
|
|
if ( strcasecmp(cmd, screens[i])==0 )
|
|
break;
|
|
}
|
|
|
|
if (i==n)
|
|
return -1;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
void C_CGI_Form::Flag( char * var, char * explanation /*= NULL*/ )
|
|
{
|
|
char buf[500], s[500];
|
|
|
|
snprintf( buf, sizeof(buf), "c%s", var );
|
|
LetStr( buf, GetVariable("syntax") );
|
|
|
|
snprintf( buf, sizeof(buf), "err_%s", var );
|
|
|
|
if ( CGI_FLAG_CLEAR==explanation )
|
|
LetStr( buf, "" );
|
|
else
|
|
LetStrf( buf, "<a href='#' onClick=\"alert('%1$s');return false;\" TABINDEX=-1><img src='/image/gif/point.gif' align=middle border=0 width=10 height=15 alt='%1$s'></a>", explanation?explanation:"Invalid input" );
|
|
|
|
logfmt( FLOG_MAX, "Flagged %s", buf );
|
|
}
|
|
|
|
|
|
void C_CGI_Form::Flag( CGI_Variable * var )
|
|
{
|
|
if ( var && var->pattern )
|
|
Flag( var->name, var->pattern->explanation );
|
|
}
|
|
|
|
|
|
void C_CGI_Form::MatchVariable( CGI_Variable * var, bool optional /*= false*/, bool flag_if_mismatch /*= true*/ )
|
|
{
|
|
char s[500];
|
|
char buf[500];
|
|
regex_t compiled;
|
|
char smatch[500], fc;
|
|
unsigned int i;
|
|
int n = 0;
|
|
ULONG * t = (ULONG*)var->target;
|
|
double amount;
|
|
|
|
// typedef *ULONG PULONG;
|
|
// (ULONG *) t[100];
|
|
// t = var->target;
|
|
|
|
if ( var->type != CGI_CHECKBOXLIST && var->type != CGI_CHECKBOXLIST_ARRAY)
|
|
{
|
|
GetParam( var->name, s, sizeof( s ) );
|
|
|
|
var->match = true; // Let's not raise hell
|
|
|
|
strsafecpy( smatch, s, sizeof(smatch) ); // in case it doesn't get filled in
|
|
|
|
if ( optional && smatch[0]==0 /*&& var->type==CGI_STRING*/ )
|
|
var->match = true;
|
|
else
|
|
{
|
|
if ( var->pattern ) // Matching requested?
|
|
{
|
|
regmatch_t match[2];
|
|
|
|
if ( regcomp( &compiled, var->pattern->mask, REG_EXTENDED ) != 0 )
|
|
{
|
|
logfmt( logWARNING, "regcomp returned non-0, assuming a match" );
|
|
}
|
|
else
|
|
{
|
|
size_t r = regexec( &compiled, s, 2, match, 0 );
|
|
|
|
if ( r==0 ) // match
|
|
{
|
|
int len = match[1].rm_eo-match[1].rm_so;
|
|
if ( len>=sizeof(smatch) )
|
|
len = sizeof(smatch)-1; // to be safe
|
|
|
|
strncpy( smatch, &s[ match[1].rm_so ], len );
|
|
smatch[ len ] = 0;
|
|
|
|
}
|
|
else
|
|
var->match = false;
|
|
|
|
regfree( &compiled );
|
|
}
|
|
}
|
|
|
|
// Too short or too long?
|
|
|
|
if ( ( var->minlen>=0 && strlen( smatch )<var->minlen ) ||
|
|
( var->maxlen>=0 && strlen( smatch )>var->maxlen )
|
|
)
|
|
var->match = false;
|
|
}
|
|
|
|
LetStr( var->name, smatch );
|
|
|
|
}
|
|
else
|
|
var->match = true;
|
|
|
|
if ( ( var->type==CGI_RADIO || var->type==CGI_RADIO_INT || var->type==CGI_RADIO_INT2 ) && smatch[0]==0 )
|
|
var->match = false;
|
|
|
|
|
|
// If match => store it
|
|
|
|
|
|
bool *_bool = (bool*)var->target;
|
|
|
|
|
|
if ( var->match )
|
|
{
|
|
switch ( var->type )
|
|
{
|
|
case CGI_STRING:
|
|
|
|
strsafecpy( (char *)var->target, smatch, var->size );
|
|
break;
|
|
|
|
case CGI_RADIO:
|
|
|
|
for ( i=0; i<var->nradio; i++ )
|
|
if ( strcasecmp( var->radio[i], smatch ) == 0 )
|
|
break;
|
|
|
|
if ( i == var->nradio )
|
|
var->match = 0;
|
|
else
|
|
{
|
|
*(unsigned char*)var->target = i;
|
|
|
|
snprintf( buf, sizeof(buf), "%schecked", smatch );
|
|
LetStr( buf, "checked" );
|
|
}
|
|
|
|
break;
|
|
|
|
case CGI_RADIO_INT:
|
|
|
|
snprintf( buf, sizeof(buf), "%c%s", var->name[0], smatch );
|
|
LetStr( buf, "checked" );
|
|
|
|
|
|
char * endptr;
|
|
*(short*)var->target = (short)strtol( smatch, &endptr, 10 );
|
|
var->match = smatch[0]!=0 && *endptr==0;
|
|
|
|
break;
|
|
|
|
case CGI_RADIO_INT2:
|
|
|
|
snprintf( buf, sizeof(buf), "%.2s%s", var->name, smatch );
|
|
LetStr( buf, "checked" );
|
|
|
|
|
|
*(short*)var->target = (short)strtol( smatch, &endptr, 10 );
|
|
var->match = smatch[0]!=0 && *endptr==0;
|
|
|
|
break;
|
|
|
|
case CGI_SELECT:
|
|
|
|
logfmt( FLOG_MAX, "CGI_SELECT" );
|
|
memset( var->target, 0, var->size );
|
|
*(unsigned short*)var->target = atol( smatch );
|
|
|
|
if ( var->radio )
|
|
fc = (char)*(*(var->radio+0)+0);
|
|
else
|
|
fc = var->name[0];
|
|
|
|
snprintf( buf, sizeof(buf), "%c%s", fc, smatch );
|
|
LetStr( buf, "selected" );
|
|
|
|
break;
|
|
|
|
case CGI_SELECT_LOOKUP:
|
|
|
|
memset( var->target, 0, var->size );
|
|
|
|
strsafecpy( (char *)var->target, smatch, var->size );
|
|
|
|
|
|
if ( var->radio )
|
|
fc = (char)*(*(var->radio+0)+0);
|
|
else
|
|
fc = var->name[0];
|
|
|
|
snprintf( buf, sizeof(buf), "%c%s", fc, smatch );
|
|
LetStr( buf, "selected" );
|
|
|
|
break;
|
|
|
|
|
|
case CGI_CHECKBOX:
|
|
|
|
// target is a boolean
|
|
|
|
*_bool = 0==strcasecmp( smatch, "on" );
|
|
|
|
if ( *_bool )
|
|
{
|
|
snprintf( buf, sizeof(buf), "%schecked", var->name );
|
|
LetStr( buf, "checked" );
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
case CGI_CHECKBOXLIST:
|
|
|
|
// target is a ULONG 32-bit?
|
|
|
|
*(ULONG*)var->target = 0;
|
|
for (i=0; i<var->maxlen && i<sizeof(ULONG)*8; i++)
|
|
{
|
|
snprintf( s, sizeof(s), "%s%d", (char*)var->radio[0], i+1 );
|
|
GetParam( s, buf, sizeof(buf) );
|
|
|
|
logfmt( FLOG_MAX, "CHECKBOX_LIST '%s' %s=%s", var->name, s, buf );
|
|
|
|
if (buf[0])
|
|
{
|
|
// logfmt( FLOG_MAX, "CGI_CHECKBOXLIST: %d=%s, target=%lu", i+1, buf,
|
|
// *(ULONG*)var->target );
|
|
*(ULONG*)var->target |= (1<<i);
|
|
logfmt( FLOG_MAX, "CGI_CHECKBOXLIST: %d=%s, target=%lu", i+1, buf,
|
|
*(ULONG*)var->target );
|
|
LetStr( s, "checked" );
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case CGI_CHECKBOXLIST_ARRAY:
|
|
|
|
// target is a ULONG 32-bit?
|
|
|
|
// *(ULONG*)var->target = 0;
|
|
for (i=0; i<var->maxlen; i++) //&& i<sizeof(ULONG)*8
|
|
{
|
|
snprintf( s, sizeof(s), "%s%d", (char *)var->radio[0], i );
|
|
GetParam( s, buf, sizeof(buf) );
|
|
if (buf[0])
|
|
{
|
|
t[n] = atol( buf ); n++;
|
|
// logfmt( FLOG_MAX, "CGI_CHECKBOXLIST: %d=%s, target=%lu", i+1, buf,
|
|
// *(ULONG*)var->target );
|
|
// *(ULONG*)var->target |= (1<<i);
|
|
// logfmt( FLOG_MAX, "CGI_CHECKBOXLIST: %d=%s, target=%lu", i+1, buf,
|
|
// *(ULONG*)var->target );
|
|
LetStr( s, "checked" );
|
|
}
|
|
}
|
|
t[n] = 0;
|
|
|
|
if ( n<var->minlen ) // minimum required number of checked boxes
|
|
var->match = false;
|
|
|
|
break;
|
|
|
|
case CGI_SELECT_MUL:
|
|
|
|
TList *list, *cur;
|
|
GetParamMul( var->name, &list );
|
|
//PrintList( list );
|
|
|
|
cur = list;
|
|
|
|
for (i=0; cur; i++)
|
|
{
|
|
if ( var->radio )
|
|
if ( *(char*)var->radio==cur->text[0] )
|
|
{
|
|
t[n] = atol( &cur->text[1] ); n++;
|
|
}
|
|
else
|
|
{
|
|
cur = cur->next;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
t[n] = atol( cur->text ); n++;
|
|
}
|
|
|
|
LetStr( cur->text, "selected" );
|
|
|
|
|
|
|
|
|
|
cur = cur->next;
|
|
}
|
|
t[n] = 0;
|
|
|
|
if ( n<var->minlen ) // minimum required number of checked boxes
|
|
var->match = false;
|
|
|
|
cur = list;
|
|
|
|
DestroyList( list );
|
|
|
|
break;
|
|
|
|
case CGI_LONG:
|
|
|
|
// target is a 32-bit long
|
|
|
|
*(long*)var->target = strtol( smatch, &endptr, 10 );
|
|
var->match = smatch[0]!=0 && *endptr==0;
|
|
|
|
break;
|
|
|
|
case CGI_FLOAT:
|
|
|
|
*(float*)var->target = strtod( smatch, &endptr );
|
|
var->match = smatch[0]!=0 && *endptr==0;
|
|
|
|
break;
|
|
|
|
|
|
case CGI_AMOUNT:
|
|
|
|
amount = strtod( smatch, &endptr );
|
|
var->match = smatch[0]!=0 && *endptr==0;;
|
|
*(unsigned long*)var->target = (ULONG)(amount*100.0+0.5);
|
|
|
|
break;
|
|
|
|
|
|
default: ; // do not let this happen, ok?
|
|
|
|
} // switch
|
|
|
|
|
|
}
|
|
|
|
// else
|
|
|
|
if ( !var->match )
|
|
{
|
|
|
|
|
|
|
|
|
|
if ( var->pattern /*&& !optional*/ && flag_if_mismatch )
|
|
{
|
|
Flag( var );
|
|
}
|
|
|
|
// PrintVars();
|
|
|
|
}
|
|
|
|
if ( optional && !var->match )
|
|
{
|
|
logfmt( FLOG_MAX, "Resetting '%s'", var->name );
|
|
memset( var->target, 0xFF, var->size );
|
|
|
|
if ( var->type== CGI_SELECT )
|
|
logfmt( FLOG_MAX, "%s, smatch=%s", var->name, smatch );
|
|
|
|
// Clear the flag if blank
|
|
if ( !smatch[0] )
|
|
Flag( var->name, CGI_FLAG_CLEAR );
|
|
}
|
|
|
|
if ( optional && var->type!=CGI_STRING )
|
|
var->match = true;
|
|
|
|
// logfmt( FLOG_MAX, "MatchVariable(): %s=%s, match=%s", var->name, smatch, var->match?"true":"false" );
|
|
}
|
|
|
|
void C_CGI_Form::SetVariable( CGI_Variable * var )
|
|
{
|
|
char buf[100], s[100];
|
|
int i;
|
|
|
|
switch ( var->type )
|
|
{
|
|
case CGI_STRING:
|
|
|
|
LetStr( var->name, (char*)var->target );
|
|
break;
|
|
|
|
case CGI_RADIO:
|
|
|
|
snprintf( buf, sizeof(buf), "%schecked", var->radio[ *(unsigned char *)var->target ] );
|
|
LetStr( buf, "checked" );
|
|
|
|
break;
|
|
|
|
case CGI_RADIO_INT:
|
|
|
|
snprintf( buf, sizeof(buf), "%c%d", var->name[0], *(short *)var->target );
|
|
LetStr( buf, "checked" );
|
|
|
|
break;
|
|
|
|
case CGI_RADIO_INT2:
|
|
|
|
snprintf( buf, sizeof(buf), "%.2s%d", var->name, *(short*)var->target );
|
|
LetStr( buf, "checked" );
|
|
|
|
break;
|
|
|
|
|
|
case CGI_SELECT:
|
|
|
|
snprintf( buf, sizeof(buf), "%c%d", var->name[0], *(unsigned short*)var->target );
|
|
LetStr( buf, "selected" );
|
|
|
|
break;
|
|
|
|
case CGI_SELECT_LOOKUP:
|
|
|
|
snprintf( buf, sizeof(buf), "%c%s",
|
|
var->radio ? (char)*(*(var->radio+0)+0) : var->name[0],
|
|
|
|
(char *)var->target );
|
|
LetStr( buf, "selected" );
|
|
|
|
break;
|
|
|
|
case CGI_CHECKBOX:
|
|
|
|
// target is a boolean
|
|
if (var->target)
|
|
{
|
|
snprintf( buf, sizeof(buf), "%schecked", var->name );
|
|
LetStr( buf, "checked" );
|
|
}
|
|
|
|
break;
|
|
|
|
case CGI_CHECKBOXLIST:
|
|
|
|
// target is a ULONG 32-bit?
|
|
|
|
for (i=0; i<var->maxlen && i<sizeof(ULONG)*8; i++)
|
|
{
|
|
if (*(ULONG*)var->target & 1<<i)
|
|
{
|
|
snprintf( s, sizeof(s), "%s%d", (char *)var->radio[0], i+1 );
|
|
LetStr( s, "checked" );
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case CGI_LONG:
|
|
|
|
// target is a 32-bit long
|
|
snprintf( s, sizeof(s), "%lu", *(ULONG*)var->target );
|
|
LetStr( var->name, s );
|
|
|
|
break;
|
|
|
|
case CGI_FLOAT:
|
|
|
|
LetStrf( var->name, "%.2f", *(float*)var->target );
|
|
break;
|
|
|
|
case CGI_AMOUNT:
|
|
|
|
// target is a 32-bit long
|
|
snprintf( s, sizeof(s), "%.2f", (*(ULONG*)var->target)/100.0 );
|
|
LetStr( var->name, s );
|
|
|
|
break;
|
|
|
|
|
|
default: ; // do not let this happen, ok?
|
|
|
|
}// switch
|
|
}
|
|
|
|
|
|
void C_CGI_Form::Email( char * fname, char * from/*=NULL*/ )
|
|
{
|
|
char name[100], headers[100];
|
|
snprintf( name, sizeof(name), EMAIL_PREFIX"/%s", fname );
|
|
|
|
char * c = FormFile( name );
|
|
|
|
logfmt( FLOG_MAX, "Template parsed: %s", name );
|
|
|
|
// logfmt( FLOG_MAX, "body=%s", c );
|
|
|
|
// Strip 8-bit content
|
|
|
|
int len = strlen( c );
|
|
for ( int i=0; i<len; i++ )
|
|
c[i] &= 0x7F;
|
|
|
|
// snprintf( headers, sizeof(headers), "X-EmailID: %s\n", fname );
|
|
|
|
|
|
// --
|
|
bool test = false;
|
|
|
|
SMTP2(CfgReadChar("mailsend.server"),
|
|
(from != NULL && strlen(from)>5) ? from : CfgReadChar( "mailsend.from" ), // From: "support@chiefsoft.com"
|
|
GetVariable("email"),
|
|
c,
|
|
CfgReadChar( "mailsend.domain" ),
|
|
CfgReadChar( "mailsend.user" ),
|
|
CfgReadChar( "mailsend.pass" ),
|
|
CfgReadChar( "mailsend.name" ));
|
|
|
|
free(c);
|
|
}
|
|
|
|
CGIList::CGIList( C_CGI_Form * _form, char * name )
|
|
|
|
// Instantiates a CGI_List object
|
|
// _form points to the parent form object
|
|
// name - name of the list as used in template
|
|
|
|
{
|
|
// logfmt( FLOG_MAX, "CGIList::CGIList()" );
|
|
form = _form; n = 0; listname = strdup(name);
|
|
if (!listname)
|
|
logfmt( FLOG_MAX, "Out of memory" );
|
|
|
|
listn = form->nlists;
|
|
form->lists[ listn ] = this;
|
|
form->nlists++;
|
|
// logfmt( FLOG_MAX, "/CGIList::CGIList(), form->lists[%d]='%s'", form->nlists-1, listname );
|
|
};
|
|
|
|
|
|
void CGIList::LetStrf( char * var, const char * format, ... )
|
|
{
|
|
char buf[100];
|
|
snprintf( buf, sizeof(buf), "__list_%s_%d_%s", listname, n, var );
|
|
|
|
va_list ap;
|
|
va_start( ap, format );
|
|
|
|
form->vLetStrf( buf, format, ap );
|
|
|
|
va_end( ap );
|
|
|
|
}
|
|
|
|
|
|
void CGIList::LetStr( char * var, char * value )
|
|
{
|
|
char buf[100];
|
|
|
|
snprintf( buf, sizeof(buf), "__list_%s_%d_%s", listname, n, var );
|
|
form->LetStr( buf, value );
|
|
}
|
|
|
|
void CGIList::LetStr( char * var, const char * format, ... )
|
|
{
|
|
char buf[100];
|
|
snprintf( buf, sizeof(buf), "__list_%s_%d_%s", listname, n, var );
|
|
|
|
char tmp[1000];
|
|
|
|
va_list ap;
|
|
va_start( ap, format );
|
|
vsnprintf( tmp, sizeof(tmp), format, ap );
|
|
va_end( ap );
|
|
|
|
form->LetStr( buf, tmp );
|
|
}
|
|
|
|
void CGIList::LetInt16( char * var, const int value )
|
|
{
|
|
char buf[100];
|
|
|
|
snprintf( buf, sizeof(buf), "__list_%s_%d_%s", listname, n, var );
|
|
form->LetInt16( buf, value );
|
|
// logfmt( FLOG_MAX, "Setting %s=%d", buf, value );
|
|
}
|
|
|
|
|
|
char * CGIList::GetVariable( char * var, char * result, int size )
|
|
{
|
|
char buf[100];
|
|
|
|
snprintf( buf, sizeof(buf), "__list_%s_%d_%s", listname, n, var );
|
|
return form->GetVariable( buf, result, size );
|
|
}
|
|
|
|
|
|
void CInputError::Log()
|
|
{
|
|
L_Variables * v;
|
|
v = this->var_top;
|
|
|
|
if ( !v ) return;
|
|
|
|
while ( v )
|
|
{
|
|
logfmt( FLOG_MAX, "%d: %s = %s", v->opts, v->name, v->value );
|
|
v = v->next;
|
|
}
|
|
|
|
}
|
|
|
|
void CInputError::Add( bool text, const char * var, const char * explanation, ... )
|
|
{
|
|
char *tmp;
|
|
int size;
|
|
|
|
va_list ap;
|
|
va_start( ap, explanation );
|
|
size = vsnprintf( NULL, 0, explanation, ap ) + 1;
|
|
tmp = (char*)malloc( size );
|
|
vsnprintf( tmp, size, explanation, ap );
|
|
va_end( ap );
|
|
|
|
|
|
L_Variables * v;
|
|
v = FindVariable( var, true );
|
|
|
|
if (v->value)
|
|
free( v->value );
|
|
|
|
v->value = strdup( tmp );
|
|
|
|
v->opts = text;
|
|
|
|
free( tmp );
|
|
}
|
|
|
|
|
|
char *CInputError::Get( const char * var, bool *text )
|
|
{
|
|
L_Variables * v;
|
|
|
|
v = FindVariable( var );
|
|
|
|
if ( !v )
|
|
return NULL;
|
|
else
|
|
{
|
|
*text = v->opts;
|
|
return v->value;
|
|
}
|
|
}
|
|
|
|
void C_CGI_Form::ClearVariable( CGI_Variable var )
|
|
{
|
|
char tmp[200];
|
|
LetStr( var.name, "" );
|
|
snprintf( tmp, sizeof(tmp), "err_%s", var.name );
|
|
LetStr( tmp, "" );
|
|
}
|