#include #include #include #include #include #include #include #include #include #include #include #include "smtp.h" #include #include "cgi.h" #include #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; imaxlevel ) 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; c2maxlevel ) 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; jlistname, 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 && (cnextinstn ) { 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 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), "", i ); snprintf( s2, sizeof(s2), "", 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%1$s", 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 )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; inradio; 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; imaxlen && iradio[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<target ); LetStr( s, "checked" ); } } break; case CGI_CHECKBOXLIST_ARRAY: // target is a ULONG 32-bit? // *(ULONG*)var->target = 0; for (i=0; imaxlen; i++) //&& iradio[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<target ); LetStr( s, "checked" ); } } t[n] = 0; if ( nminlen ) // 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 ( nminlen ) // 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; imaxlen && itarget & 1<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; i5) ? 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, "" ); }