[0001] [0002] [0003] [0004] [0005] [0006] [0007] [0008] [0009] [0010] [0011] [0012] [0013] [0014] [0015] [0016] [0017] [0018] [0019] [0020] [0021] [0022] [0023] [0024] [0025] [0026] [0027] [0028] [0029] [0030] [0031] [0032] [0033] [0034] [0035] [0036] [0037] [0038] [0039] [0040] [0041] [0042] [0043] [0044] [0045] [0046] [0047] [0048] [0049] [0050] [0051] [0052] [0053] [0054] [0055] [0056] [0057] [0058] [0059] [0060] [0061] [0062] [0063] [0064] [0065] [0066] [0067] [0068] [0069] [0070] [0071] [0072] [0073] [0074] [0075] [0076] [0077] [0078] [0079] [0080] [0081] [0082] [0083] [0084] [0085] [0086] [0087] [0088] [0089] [0090] [0091] [0092] [0093] [0094] [0095] [0096] [0097] [0098] [0099] [0100] [0101] [0102] [0103] [0104] [0105] [0106] [0107] [0108] [0109] [0110] [0111] [0112] [0113] [0114] [0115] [0116] [0117] [0118] [0119] [0120] [0121] [0122] [0123] [0124] [0125] [0126] [0127] [0128] [0129] [0130] [0131] [0132] [0133] [0134] [0135] [0136] [0137] [0138] [0139] [0140] [0141] [0142] [0143] [0144] [0145] [0146] [0147] [0148] [0149] [0150] [0151] [0152] [0153] [0154] [0155] [0156] [0157] [0158] [0159] [0160] [0161] [0162] [0163] [0164] [0165] [0166] [0167] [0168] [0169] [0170] [0171] [0172] [0173] [0174] [0175] [0176] [0177] [0178] [0179] [0180] [0181] [0182] [0183] [0184] [0185] [0186] [0187] [0188] [0189] [0190] [0191] [0192] [0193] [0194] [0195] [0196] [0197] [0198] [0199] [0200] [0201] [0202] [0203] [0204] [0205] [0206] [0207] [0208] [0209] [0210] [0211] [0212] [0213] [0214] [0215] [0216] [0217] [0218] [0219] [0220] [0221] [0222] [0223] [0224] [0225] [0226] [0227] [0228] [0229] [0230] [0231] [0232] [0233] [0234] [0235] [0236] [0237] [0238] [0239] [0240] [0241] [0242] [0243] [0244] [0245] [0246] [0247] [0248] [0249] [0250] [0251] [0252] [0253] [0254] [0255] [0256] [0257] [0258] [0259] [0260] [0261] [0262] [0263] [0264] [0265] [0266] [0267] [0268] [0269] [0270] [0271] [0272] [0273] [0274] [0275] [0276] [0277] [0278] [0279] [0280] [0281] [0282] [0283] [0284] [0285] [0286] [0287] [0288] [0289] [0290] [0291] [0292] [0293] [0294] [0295] [0296] [0297] [0298] [0299] [0300] [0301] [0302] [0303] [0304] [0305] [0306] [0307] [0308] [0309] [0310] [0311] [0312] [0313] [0314] [0315] [0316] [0317] [0318] [0319] [0320] [0321] [0322] [0323] [0324] [0325] [0326] [0327] [0328] [0329] [0330] [0331] [0332] [0333] [0334] [0335] [0336] [0337] [0338] [0339] [0340] [0341] [0342] [0343] [0344] [0345] [0346] [0347] [0348] [0349] [0350] [0351] [0352] [0353] [0354] [0355] [0356] [0357] [0358] [0359] [0360] [0361] [0362] [0363] [0364] [0365] [0366] [0367] [0368] [0369] [0370] [0371] [0372] [0373] [0374] [0375] [0376] [0377] [0378] [0379] [0380] [0381] [0382] [0383] [0384] [0385] [0386] [0387] [0388] [0389] [0390] [0391] [0392] [0393] [0394] [0395] [0396] [0397] [0398] [0399] [0400] [0401] [0402] [0403] [0404] [0405] [0406] [0407] [0408] [0409] [0410] [0411] [0412] [0413] [0414] [0415] [0416] [0417] [0418] [0419] [0420] [0421] [0422] [0423] [0424] [0425] [0426] [0427] [0428] [0429] [0430] [0431] [0432] [0433] [0434] [0435] [0436] [0437] [0438] [0439] [0440] [0441] [0442] [0443] [0444] [0445] [0446] [0447] [0448] [0449] [0450] [0451] [0452] [0453] [0454] [0455] [0456] [0457] [0458] [0459] [0460] [0461] [0462] [0463] [0464] [0465] [0466] [0467] [0468] [0469] [0470] [0471] [0472] [0473] [0474] [0475] [0476] [0477] [0478] [0479] [0480] [0481] [0482] [0483] [0484] [0485] [0486] [0487] [0488] [0489] [0490] [0491] [0492] [0493] [0494] [0495] [0496] [0497] [0498] [0499] [0500] [0501] [0502] [0503] [0504] [0505] [0506] [0507] [0508] [0509] [0510] [0511] [0512] [0513] [0514] [0515] [0516] [0517] [0518] [0519] [0520] [0521] [0522] [0523] [0524] [0525] [0526] [0527] [0528] [0529] [0530] [0531] [0532] [0533] [0534] [0535] [0536] [0537] [0538] [0539] [0540] [0541] [0542] [0543] [0544] [0545] [0546] [0547] [0548] [0549] [0550] [0551] [0552] [0553] [0554] [0555] [0556] [0557] [0558] [0559] [0560] [0561] [0562] [0563] [0564] [0565] [0566] [0567] [0568] [0569] [0570] [0571] [0572] [0573] [0574] [0575] [0576] [0577] [0578] [0579] [0580] [0581] [0582] [0583] [0584] [0585] [0586] [0587] [0588] [0589] [0590] [0591] [0592] [0593] [0594] [0595] [0596] [0597] [0598] [0599] [0600] [0601] [0602] [0603] [0604] [0605] [0606] [0607] [0608] [0609] [0610] [0611] [0612] [0613] [0614] [0615] [0616] [0617] [0618] [0619] [0620] [0621] [0622] [0623] [0624] [0625] [0626] [0627] [0628] [0629] [0630] [0631] [0632] [0633] [0634] [0635] [0636] [0637] [0638] [0639] [0640] [0641] [0642] [0643] [0644] [0645] [0646] [0647] [0648] [0649] [0650] [0651] [0652] [0653] [0654] [0655] [0656] [0657] [0658] [0659] [0660] [0661] [0662] [0663] [0664] [0665] [0666] [0667] [0668] [0669] [0670] [0671] [0672] [0673] [0674] [0675] [0676] [0677] [0678] [0679] [0680] [0681] [0682] [0683] [0684] [0685] [0686] [0687] [0688] [0689] [0690] [0691] [0692] [0693] [0694] [0695] [0696] [0697] [0698] [0699] [0700] [0701] [0702] [0703] [0704] [0705] [0706] [0707] [0708] [0709] [0710] [0711] [0712] [0713] [0714] [0715] [0716] [0717] [0718]
/* * CGI script for sending mail, driven by a template file that inserts * form fields at specified spots. * * Usage: * Create HTML form that specifies this script as the action with the * template file as the path_info following the script name. * * Template file format: * Template file consists of a header followed by the body section, the * end of header is indicated by a blank line. At any point in the * file you can specify a form field name surrounded by square brackets * and the corresponding field from the form will be substituted. * * Template header fields: * To: address * Subject: string * Success: url * * Fail: url * * AUTHORS: * * Dick Munroe Original CGIMAILTO program. * Acorn Software, Inc. * munroe@acornsw.com * * David Jones * Ohio State University * * CREATION DATE: 04-Dec-94 * Date: 13-JUN-1996 * Revised: 16-JUN-1996 * Revised: 30-MAY-1997 */ #if defined(__ALPHA) /* Some structures needed by mail are not aligned */ #pragma nomember_alignment #endif /** MGD **/ #if defined(__ia64) #pragma nomember_alignment #endif #include <stdio.h> #include <stat.h> #include "cgilib.h" struct ItemList { short int length, code; char *buffer; long returnLength; }; #include <descrip.h> #include <jpidef.h> #include <lib$routines.h> #include <maildef.h> #include <ssdef.h> #include <stdlib.h> #include <str$routines.h> #include <string.h> #include <ctype.h> #include <stsdef.h> /* * Prototypes for callable mail API. */ extern unsigned long mail$send_begin() ; extern unsigned long mail$send_add_attribute() ; extern unsigned long mail$send_add_address() ; extern unsigned long mail$send_add_bodypart() ; extern unsigned long mail$send_message() ; extern unsigned long mail$send_end() ; /* * Miscellaneous data structures used to store form data and text lines. */ struct field_def { struct field_def *next; char *key, *value; int klen; }; typedef struct field_def *field_def_p; struct scanctx { char *body; char *subline; }; struct outrec { struct outrec *next; int length; char data[1]; /* variable length actually allocated */ }; static int ent_flag = 0; /* if true, entify chars "<>&" in expansions */ /* * Forward function references. */ static int scan_body ( struct scanctx *context, field_def_p fields, char *buffer, int bufsize, int *length ); static char *expand_line ( char *, field_def_p ); static char *reformat_value ( char *source, char *format, int fmt_len ); static char *entify_string ( char *source ); static field_def_p form_data(); static void send_fail ( char *stsline, char *reason, void *arg ) { char fmt[256]; sprintf(fmt,"context-type: text/plain\nstatus: %s\n\nSend failed: %s\n", stsline, reason ); cgi_printf(fmt,arg,arg); exit(1); } /****************************************************************************/ /* Main routine. */ int main ( int argc, char **argv ) { char buffer[1024], body_line[256]; char *template_name, *template_file, *template; char *method, *personal_name, *t_body, *expanded, *cp ; struct scanctx context; struct ItemList itemList[10], nullItemList = {0, 0, 0, 0} ; unsigned long sendContext = 0 ; char *to, *subj, *version, *success, *failure, *line; FILE *tfile; field_def_p field_list, fld; struct outrec rec_list, *last_rec, *cur_rec; int i, j, status, length, t_used, t_alloc, succ_sts; /* * Initialize CGI and load content into memory. */ status = cgi_init ( argc, argv ); if ( (status&1) == 0 ) return status; field_list = form_data(); if ( !field_list ) return 1; /* * Get template file name and attempt to open. */ template_name = cgi_info ( "PATH_INFO" ); template_file = cgi_info ( "PATH_TRANSLATED" ); if ( !template_name || !template_file ) send_fail ( "500 bad template", "Bad template name (%s)\n", template_name ? template_name : "???" ); tfile = fopen ( template_file, "r" ); if ( !tfile ) send_fail ( "500 open failure", "open failure on template file (%s)", template_file ); /* * Read template data into memory. */ t_alloc = 8192; template = malloc(t_alloc); t_used = 0; while (0 < (length=fread(&template[t_used], 1, t_alloc - t_used, tfile))) { t_used += length; if ( t_used >= t_alloc ) { t_alloc = t_alloc + 20000; if ( t_alloc > 100000 ) send_fail ( "500 error", "template file too big (%s)", template_name ); template = realloc ( template, t_alloc ); } } fclose ( tfile ); /* * Parse header out of template, check that first line is version. */ t_body = version = (char *) 0; for ( i = 0; i < t_used; i++ ) if ( template[i] == '\n' ) { if ( !version ) { /* First line must be "tmail" */ for ( j = 0; template[j] && template[j] != ':'; j++ ) template[j] = tolower(template[j]); if ( 0 != strncmp(template,"tmail:", 6) ) send_fail ( "500 invalid template", "first line of template must be tmail: header", 0 ); version = &template[7]; } if ( template[i+1] == '\n' ) { template[i+1] = '\0'; t_body = &template[i+2]; break; } } if ( !t_body ) send_fail ( "500 invalid template", "Invalid template format - no body", 0 ); /* * Parse header lines. */ to = subj = success = failure = (char *) 0; succ_sts = 0; for ( i = 0, line = template; template[i]; i++ ) { if (template[i] == '\n') { template[i] = '\0'; for ( j = 0; line[j] && line[j] != ':'; j++ ) line[j] = tolower(line[j]); if ( strncmp(line,"to:",3)==0 ) to = expand_line(&line[3],field_list); else if ( strncmp(line,"subject:",8) == 0 ) subj = expand_line(&line[8], field_list); else if ( strncmp(line,"success:",8) == 0 ) success = expand_line ( &line[8], field_list ); else if ( strncmp(line,"success-status:",15) == 0 ) succ_sts = atoi(&line[15]); else if ( strncmp(line,"failure:",8) == 0 ) failure = expand_line ( &line[8], field_list ); line = &template[i+1]; } } if ( !to ) send_fail ( "500 invalid template", "invalid template file header - no to: line", 0) ; /* * Parse the body lines and generate list of records. */ context.body = t_body; context.subline = (char *) 0; for ( last_rec = &rec_list; ; last_rec = cur_rec ) { status = scan_body (&context, field_list, body_line, sizeof(body_line)-1, &length ); if ( status > 0 ) { /* * Add record to list. */ cur_rec = (struct outrec *) malloc (sizeof(struct outrec)+length); last_rec->next = cur_rec; if ( !cur_rec ) return 0; cur_rec->next = (struct outrec *) 0; cur_rec->length = length; memcpy ( cur_rec->data, body_line, length ); cur_rec->data[length] = '\0'; /* not really necessary */ } else if ( status == 0 ) { break; /* status == 0 ==> EOD */ } else { /* Error */ return 1; } } /* * Initiate mail message, construct a personal name for the * message from the path used to invoke it. */ personal_name = malloc ( strlen(template_name) + 20 ); sprintf ( personal_name, "tmail: %s", template_name ); i = -1; itemList[++i].length = strlen(personal_name); itemList[i].code = MAIL$_SEND_PERS_NAME ; itemList[i].buffer = personal_name; itemList[i].returnLength = 0 ; itemList[++i].length = 0 ; itemList[i].code = 0 ; status = mail$send_begin ( &sendContext, &itemList, &nullItemList) ; /* Set up to construct the mail context. */ if (!$VMS_STATUS_SUCCESS(status)) send_fail ( "500 mail error", "MAIL$SEND_BEGIN returned %%X%0X",(void *) status) ; /* ** Now build up the attributes of the message. */ i = -1 ; while ( isspace(*to) && *to ) to++; /* trim leading spaced */ itemList[++i].length = strlen(to) ; itemList[i].code = MAIL$_SEND_TO_LINE ; itemList[i].buffer = to ; itemList[i].returnLength = 0 ; if ( !subj ) subj = "Mail from tmail script"; while ( isspace(*subj) && *subj ) subj++; /* trim leading spaced */ itemList[++i].length = strlen(subj); itemList[i].code = MAIL$_SEND_SUBJECT ; itemList[i].buffer = subj; itemList[i].returnLength = 0 ; itemList[++i].length = 0 ; itemList[i].code = 0 ; status = mail$send_add_attribute ( &sendContext, &itemList, &nullItemList) ; /* Add the the message header. */ if (!$VMS_STATUS_SUCCESS(status)) send_fail ( "500 mail error", "MAIL$SEND_ADD_ATTRIBUTE returned %%X%0X,\ncheck template's subject: line", (void *) status ); /* * Set destination for to: header line. */ i = -1 ; itemList[++i].length = strlen(to) ; itemList[i].code = MAIL$_SEND_USERNAME ; itemList[i].buffer = to ; itemList[i].returnLength = 0 ; itemList[++i] = nullItemList ; /* The itemlist describes an address of a receipient. */ status = mail$send_add_address ( &sendContext, &itemList, &nullItemList) ; /* Add the sender of the message to the list of receipients. */ if (!$VMS_STATUS_SUCCESS(status)) send_fail ( "500 mail error", "MAIL$SEND_ADD_ADDRESS returned %%X%0X,\ncheck template's to: header line", (void *) status); /* * Send the items. */ itemList[0].code = MAIL$_SEND_RECORD; itemList[0].returnLength = 0; itemList[1] = nullItemList; for ( cur_rec = rec_list.next; cur_rec; cur_rec = cur_rec->next ) { itemList[0].length = cur_rec->length; itemList[0].buffer = cur_rec->data; status = mail$send_add_bodypart (&sendContext, &itemList, &nullItemList) ; if ( !$VMS_STATUS_SUCCESS(status) ) send_fail ( "500 mail error", "MAIL$SEND_ADD_BODYPART returned %%X%0X", (void *) status) ; } /* * Message complete, queue to delivery system. */ status = mail$send_message ( &sendContext, &nullItemList, &nullItemList) ; /* Send the message. */ if (!$VMS_STATUS_SUCCESS(status)) send_fail ( "500 mail error", "MAIL$SEND_MESSAGE returned %%X%0X", (void *) status) ; status = mail$send_end ( &sendContext, &nullItemList, &nullItemList) ; /* Set up to construct the mail context. */ if (!$VMS_STATUS_SUCCESS(status)) send_fail ( "500 mail error", "MAIL$SEND_END returned %%X%0X", (void *) status); if ( success ) { cgi_printf ( "location: %s\n\n", success ); } else if ( context.body[0] ) { /* * Non-null body remaining means it holds data to return, assume * it includes CGI headers. */ ent_flag = 1; while ( scan_body (&context, field_list, body_line, sizeof(body_line)-1, &length ) > 0 ) { cgi_printf ( "%s\n", body_line ); } } else { cgi_printf("content-type: text/plain\n"); /* CGI header */ if ( (succ_sts < 200) || (succ_sts > 299) ) succ_sts = 200; cgi_printf("status: %d mail delivered\n\n", succ_sts ); cgi_printf("Sending form data as MAIL to: %s\n",to); cgi_printf("Send Succeeded: submitted form data mailed\n") ; } return 1; } /*****************************************************************************/ /* Scan template body for tags and expand from form fields data, return * result in line-oriented fashion. */ static int scan_body ( struct scanctx *context, field_def_p fields, char *buffer, int bufsize, int *length ) { int i; /* * Load next subline if none currently. */ if ( !context->subline ) { /* scan next body line. */ for ( i = 0; context->body[i] != '\n'; i++ ) { if ( !context->body[i] ) return 0; /* no more body */ } context->body[i] = '\0'; context->subline = expand_line ( context->body, fields ); context->body[i] = '\n'; context->body = &context->body[i+1]; if ( !context->subline ) return 0; } /* * parse data out of subline. */ for ( i = 0; i < bufsize; i++ ) { buffer[i] = context->subline[i]; if ( buffer[i] == '\n' ) { context->subline = &context->subline[i+1]; break; } else if ( context->subline[i] == '\r' ) { if ( context->subline[i+1] == '\n' ) context->subline = &context->subline[i+2]; else context->subline = &context->subline[i+1]; break; } else if ( !context->subline[i] ) { context->subline += i; break; } } buffer[i] = '\0'; *length = i; if ( i >= bufsize ) context->subline = &context->subline[i]; if ( context->subline[0] == '\0' ) { /* Done processing subline, force load of next */ context->subline = (char *) 0; } return 1; } /****************************************************************************/ /* Convert escaped characters in string */ static int htmlStrcpy ( char *out, char *in) { int i, j; for ( j=0; *in; in++) { if (*in == '%') { int xxx ; if ( (in[1]=='\0') || (in[2]=='\0') ) break; /* too short */ sscanf (&in[1], "%02x", &xxx) ; out[j++] = (char) xxx ; in += 2 ; } else { out[j++] = *in; } } return j; } /****************************************************************************/ /* Read form data and parse into list of key/value pairs. Plus-to-space * conversion is performed but escaped chars are not converted. * Full CGI responses are generated on error. */ static field_def_p form_data() { char *method, *content_data, *cp; field_def_p field_list, fld; int i, content_length, status; /* * Determine what form data is being delivered by client. */ method = cgi_info ( "REQUEST_METHOD" ); if ( 0 == strcmp ( method, "POST" ) ) { /* * Data was posted. */ content_length = atoi(cgi_info ("CONTENT_LENGTH")); if (content_length == 0) send_fail ( "500 missing content", "No data in CONTENT_LENGTH (%s)", cgi_info("CONTENT_LENGTH") ); content_data = (char *) malloc(sizeof(char)*(content_length+1)); status = cgi_read(content_data, content_length); if (status == 0) send_fail ( "500 missing content", "No data from cgi_read", 0 ); content_data[content_length] = '\0'; } else if ( 0 == strcmp ( method, "GET" ) ) { /* * Form method was GET, data is supplied as query string. */ cp = cgi_info ( "QUERY_STRING" ); if ( !cp ) send_fail ( "500 missing content", "no data from cgi_read\n", 0 ) ; if ( *cp == '?' ) cp++; content_length = strlen ( cp ); content_data = (char *) malloc ( content_length + 1 ); strcpy ( content_data, cp ); /* printf("GET Content: '%s' l: %d\n", content_data, content_length);*/ } else { send_fail("501 unsupported method","Method %s is unsupported", method ); } /* * Parse the content into key/value pairs. */ field_list = (field_def_p) 0; if ( content_data[0] != '&' ) { fld = (field_def_p) malloc ( sizeof(struct field_def) ); fld->next = field_list; fld->key = content_data; fld->klen = 0; field_list = fld; } for ( i = 0; i < content_length; i++ ) if ( content_data[i] == '&' ) { fld = (field_def_p) malloc ( sizeof(struct field_def) ); fld->next = field_list; fld->key = &content_data[i+1]; fld->klen = 0; content_data[i] = '\0'; field_list = fld; } for ( fld = field_list; fld; fld = fld->next ) { fld->value = ""; for ( cp = fld->key, i = 0; cp[i]; i++ ) { if ( cp[i] == '=' ) { cp[i] = '\0'; fld->klen = i; fld->value = &cp[i+1]; } } for ( cp = fld->value; *cp; cp++ ) if ( *cp == '+' ) *cp = ' '; /* printf("Parsed key '%s' = '%s'\n", fld->key, fld->value ); */ } return field_list; } /*****************************************************************************/ /* Scan line for tags ([tag-name]) and replace with the corresponding value * from flist or cgi_info for that tag. */ static char *expand_line ( char *line, field_def_p flist ) { char *new; field_def_p fld; int i, j, k, size, length, lbrack, rbrack; /* * Allocate buffer to hold result, use size+256 as initial guess. */ size = 256 + strlen ( line ); new = malloc ( size ); /* * Scan string for tags. */ for ( i = j = 0; line[i]; i++ ) { if ( line[i] == '[' ) { /* * Start of tag detected */ if ( line[i+1] == '[' ) { /* Treat "[[" specially: insert single "[" */ k = 1; if ( j+1 >= size ) { size += 256; new = realloc ( new, size ); } new[j++] = '['; } else if ( line[i+1] == ']' ) { /* Treat [] specially: insert single "]" */ k = 1; if ( j+1 >= size ) { size += 256; new = realloc ( new, size ); } new[j++] = ']'; } else for ( k = 1; line[i+k]; k++) if ( line[i+k] == ']' ) { /* * Found end of tag. */ int saved_j = j; if ( line[i+1] == '%' && (k < 65) && (k > 1) ) { /* * string following % is CGI environment variable * unless it is %end. */ char varname[64], *var; strncpy ( varname, &line[i+2], k-2 ); varname[k-2] = '\0'; if ( varname[0] == '%' ) { /* special variable */ int l; for (l=0; varname[l]; l++) varname[l] = tolower(varname[l]); length = 0; if ( strcmp ( varname, "%end" ) == 0 ) { /* Magic tag to force EOD */ free ( new ); return (char *) 0; } else if ( strcmp ( varname, "%noentify" ) == 0 ) { ent_flag = 0; } else if ( strcmp ( varname, "%entify" ) == 0 ) { ent_flag = 1; } } else { /* CGI variable */ var = cgi_info ( varname ); if ( !var ) var = "%unknown"; if ( ent_flag ) var = entify_string ( var ); length = strlen(var); if ( length+j+1 >= size ) { size = j + length + 256; new = realloc ( new, size ); } strcpy ( &new[j], var ); } j += length; } else { /* * Check tag for format specifiers: * tag:string value is string or null * tag?string value is string if field 'on' */ int klen, fmt_flag; for (klen=fmt_flag=0; klen<k-1; klen++ ) if ( line[i+klen+1] == ':' || line[i+klen+1] == '?' ) { fmt_flag = 1; break; } /* * Scan fields supplied by caller for match. */ for (fld=flist; fld; fld=fld->next) if (fld->klen==klen ) { if ( strncmp(&line[i+1],fld->key,klen) == 0 ) { char *value; value = fld->value; if ( fmt_flag ) value = reformat_value ( value, &line[i+klen+1], k-1-klen ); length = strlen ( value ); if ( length + j+1 >= size ) { size = j + length + 256; new = realloc ( new, size ); } length = htmlStrcpy ( &new[j], value ); if ( ent_flag ) { /* Convert <s and >s */ value = entify_string(&new[j]); if ( value != &new[j] ) { length = strlen ( value ); if ( length + j+1 >= size ) { size = j + length + 256; new = realloc ( new, size ); } strcpy ( &new[j], value ); } } j += length; if ( fmt_flag ) break; /* only expand once */ } } } if ( saved_j = j ) if ( strncmp("required-",&line[i+1],9)==0 ) { /* * Required field was missing, aobrt with error message. */ send_fail ( "500 error", "Required field not supplied: %s", &line[i] ); } break; } if ( line[i+k] != '\0' ) i += k; } else { /* * Add character not part of tags to output. */ if ( j+1 >= size ) { size = size + 256; new = realloc ( new, size ); } new[j++] = line[i]; } } /* * Ensure result is terminated and return in to caller. */ new[j] = '\0'; return new; } /****************************************************************************/ /* Substitute value according to format string. */ static char *reformat_value ( char *value, char *format, int fmt_len ) { char *result; /* * Perform tests based upon first character of format string, * returning empty string on test failure. */ result = ""; if ( *format == '?' ) { /* test value for 'on' */ if ( tolower(value[0]) != 'o' ) return result; if ( tolower(value[1]) != 'n' ) return result; if ( value[2] != '\0' ) return result; } else if ( *format == ':' ) { /* test for non-null */ if ( !*value ) return result; } /* * Copy chars in format string after 1st to result string. */ result = malloc ( fmt_len ); if ( !result ) return ""; strncpy ( result, &format[1], fmt_len-1 ); result[fmt_len-1] = '\0'; return result; } /****************************************************************************/ /* Convert strings containing punctuation characters into escaped strings. */ static char *entify_string ( char *source ) { int i, j,brack_count; char *dest; dest = source; brack_count = 0; for ( i = 0; source[i]; i++ ) { if ( (source[i] == '<') || (source[i] == '>') || (source[i] == '&') ) brack_count++; } if ( brack_count > 0 ) { dest = malloc ( i + brack_count*4 + 1 ); if ( !dest ) return source; for ( i = j = 0; source[i]; i++ ) { if ( source[i] == '<' ) { dest[j++] = '&'; dest[j++] = 'l'; dest[j++] = 't'; dest[j++] = ';'; } else if ( source[i] == '>' ) { dest[j++] = '&'; dest[j++] = 'g'; dest[j++] = 't'; dest[j++] = ';'; } else if ( source[i] == '&' ) { dest[j++] = '&'; dest[j++] = 'a'; dest[j++] = 'm'; dest[j++] = 'p'; dest[j++] = ';'; } else dest[j++] = source[i]; } dest[j] = '\0'; } return dest; }