[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]
/* * This program is intended to be run by a HTTP server script in order to * convert the CGILIB environment to CLI symbols. An optional argument * is a prefix string for the created symbols (default="WWW_"). * * The HTTP request information is obtained by getting the values of P1, P2, * and P3 (method, path, protocol). The script running this program should * not modify these symbols. * * Additional execution options are specifing a bitmask as an integer value * in parameter P4: * bit 0 - If set, inhibit sending of <DNETCGI> * * This program puts the link to the HTTP server into CGI mode and flags * the environment so that WWWEXEC will automatically send the CGI terminator * when the DCL script exits. Note that in the CGI mode, the writes to * net_link must explicitly include the carriage control. The first line * output must be either and content-type: header or a location: header * followed by a blank line (newline sequence). * * Usage: * cgi_symbols prefix [form_prefix] * cgi_symbols table [filename] ! filename must contain period * * If (and only if) you specify a form prefix as argument 2 on the command * line, the program interprets the request contents as form input,creating a * series of symbols for it. The symbols created will be (xxx is form_prefix): * * xxxFIELDS Comma-separated list of field names parsed * from form input. For every name in list * a DCL symbol of form xxxFLD_name will be * created. Note that the form writer must * garantee that the field names will result in * valid DCL symbol names (e.g. no hyphens). * This list is truncated to 255 characters. * * xxxFLD_yyyy Field value of field yyyy parsed from form * input. Value is truncated to 255 characters. * * If you specify a filename as argument 2 on the command line, the request * content data (possible none) is saved in a file by that name and argument * 1 is a logical name table to save the environment variables in rather than * creating DCL symbols. * * Examples: * $ run cgi_symbols * * $ mcr sys$disk:[]cgi_symbols http_ cgiform_ * * $ mcr sys$disk:[]cgi_symbols lnm$process form_content044.tmp * * Author: David Jones * Date: 26-SEP-1994 * Revised: 25-OCT-1994 Add option to interpret form input into symbols. * Revised: 28-OCT-1994 Bug fixes. * Revised: 16-MAY-1995 Support multiple occureces of form values. * If value appears more than once, concatenate * values and separate by commas. * Revised: 8-SEP-1995 Fix bug in handling of plus signs in input * fields. To revert to old behaviour compile * with KEEP_PLUSES macro symbol defined. * Revised: 14-NOV-1995 Bug fix, terminate namlist in add_symbol(). * Revised: 21-MAR-1996 Add alternate (logical name) command syntax. * Revised: 15-NOV-1997 Add P4 hack. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <descrip.h> #include <libclidef.h> #include "scriptlib.h" #include "cgilib.h" int cgi_show_env(); static void set_form_symbols ( char *prefix ); int main ( int argc, char **argv ) { int i, status, LIB$GET_SYMBOL(), table, length, virtual_argc, flags; char *virtual_argv[4], *base_prefix, *form_prefix; char param_name[4], param_value[256]; $DESCRIPTOR(pname,""); $DESCRIPTOR(pvalue,""); /* * Check for invalid invocation */ if ( argc > 3 ) { printf( "Too many arguments, this program must be run from a DCL script\n"); exit (20); } /* * Build dummy argument list from P1 through P3 to get the values WWWEXEC * passed to the script. */ virtual_argc = 4; virtual_argv[0] = argv[0]; /* for lack of anything better! */ pname.dsc$w_length = 2; pname.dsc$a_pointer = param_name; pvalue.dsc$w_length = sizeof(param_value)-1; pvalue.dsc$a_pointer = param_value; for ( i = 1; i < virtual_argc; i++ ) { sprintf ( param_name, "P%d", i ); length = 0; status = LIB$GET_SYMBOL ( &pname, &pvalue, &length ); if ( (status&1) == 1 ) { /* * Allocate new buffer to hold value. */ virtual_argv[i] = malloc ( length+1 ); param_value[length] = '\0'; strcpy ( virtual_argv[i], param_value ); } else virtual_argv[i] = ""; } /* * Retrieve flags for execution options from P4. */ flags = 0; strcpy ( param_name, "P4" ); status = LIB$GET_SYMBOL ( &pname, &pvalue, &length ); if ( (status&1) == 1 ) { param_value[length] = '\0'; if ( length > 0 ) flags = atoi ( param_value ); } /* * Load CGI environment and convert to DCL */ if ( (flags&1) ) { status = cgi_init_env ( virtual_argc, virtual_argv ); } else { status = cgi_init ( virtual_argc, virtual_argv ); } base_prefix = argc > 1 ? argv[1] : ""; if ( !*base_prefix ) base_prefix = "WWW_"; form_prefix = argc > 2 ? argv[2] : ""; if ( strchr ( form_prefix, '.') ) { /* * A period in form_prefix means it is an output filename. * base_prefix becomes the table name. */ cgi_set_cli_env ( "", base_prefix ); if ( *form_prefix ) { /* Second argument is filename to receive post data */ FILE *pdata; char *var, buffer[4096]; int seg, length, content_length; var = cgi_info ( "CONTENT_LENGTH" ); content_length = var ? atoi(var) : 0; if ( content_length <= 0 ) return 3; /* no content. */ pdata = fopen ( argv[2], "w", "mbc=64" ); if ( !pdata ) { perror ( "Error creating content file\n" ); return 0; } for ( ; content_length > 0; content_length -= seg ) { seg = (content_length > sizeof(buffer) ) ? sizeof(buffer) : content_length; length = cgi_read ( buffer, seg ); fwrite ( buffer, length, 1, pdata ); if ( length <= 0 ) break; } fclose ( pdata ); } } else { cgi_set_dcl_env ( base_prefix ); /* * Check if form input parse wanted. */ if ( *form_prefix ) set_form_symbols ( form_prefix ); } return 1; } /***************************************************************************/ /* Search comma-delimited list of names (namlist) for specified name * and add to end of list if not found. If found, fetch value of DCL symbol * given by prefix+symname and return that to caller. * * Return values: * 0 Name too large to add to list, vallen set to 0. * 1 Name appended to end of list, vallen set to 0. * 2 Name found, symbol value stored symval, length in vallen. */ static int add_symbol ( char *prefix, char *symname, char *namlist, int *nl_len, char *symval, int *vallen ) { int i,j,k, status, prefix_len, LIB$GET_SYMBOL(), table; /* * Search list from back. */ *vallen = 0; for ( i = *nl_len-1; i >= 0; --i ) { if ( (i == 0) || namlist[i] == ',' ) { /* * namlist[i] or namlist[i+1] is start of name. */ j = (i==0) ? i : i+1; for ( k = 0; symname[k] != '='; k++ ) { if ( symname[k] != namlist[j] ) break; j++; } if ( (symname[k]=='=') && (namlist[j] == ',' || namlist[j] == '\0') ) { /* * found match, retrieve DCL symbol */ $DESCRIPTOR(symbol,""); $DESCRIPTOR(value,""); char prefixed_sym[256]; /* Build symbol name from prefix */ prefix_len = strlen(prefix); symbol.dsc$w_length = k + prefix_len; if ( symbol.dsc$w_length > 255 ) symbol.dsc$w_length = 255; strncpy ( prefixed_sym, prefix, symbol.dsc$w_length ); strncpy ( &prefixed_sym[prefix_len], symname, symbol.dsc$w_length - prefix_len); symbol.dsc$a_pointer = prefixed_sym; /* * Make descriptor for result and fetch. */ value.dsc$w_length = 255; value.dsc$a_pointer = symval; status = LIB$GET_SYMBOL ( &symbol, &value, vallen, &table ); if ( (status&1) == 0 ) *vallen = 0; return 2; } } } /* * No match, append name to namlist. */ i = *nl_len; if ( i > 0 && i < 255 ) namlist[i++] = ','; for ( j = 0; symname[j] && symname[j] != '='; j++ ) if ( i < 255 ) { namlist[i++] = symname[j]; } else return 0; namlist[i] = '\0'; *nl_len = i; return 1; } /***************************************************************************/ /* Generate list of symbols for FORM input. */ static void set_form_symbols ( char *prefix ) { char *var, *fdata; int status, table, i, j, k, vallen; int content_length, slist_len, length, prefix_len, LIB$SET_SYMBOL(); $DESCRIPTOR(symbol,""); $DESCRIPTOR(value,""); char sym_list[256], symname[256], symval[256]; /* * Initialize */ strcpy ( symname, prefix ); strcat ( symname, "FLD_" ); prefix_len = strlen ( symname ); table = LIB$K_CLI_LOCAL_SYM; symbol.dsc$a_pointer = symname; slist_len = 0; /* * See if any content present first checking for POST data and using * query string as fallback. */ var = cgi_info ( "CONTENT_LENGTH" ); content_length = var ? atoi(var) : 0; if ( content_length > 0 ) { /* * Allocate buffer and read entire form data into it, forcing final &. */ fdata = malloc ( content_length+1 ); if ( !fdata ) return; length = cgi_read ( fdata, content_length ); } else { var = cgi_info ( "QUERY_STRING" ); if ( var ) { length = strlen ( var ); fdata = malloc ( length + 1 ); if ( !fdata ) return; strcpy ( fdata, var ); } else length = 0; } if ( length > 0 ) { int start, finish, flen; /* * Parse the data. */ if ( fdata[length-1] != '&' ) fdata[length++] = '&'; start = 0; finish = 0; for ( i = 0; i < length; i++ ) if ( !fdata[i] || (fdata[i] == '&') ) { /* * Value parsed. Unescape characters and look for first '=' * to delimit field name from value. */ flen = i - start; #ifndef KEEP_PLUSES for ( j = start; j < i; j++ ) if ( fdata[j] == '+' ) fdata[j] = ' '; #endif net_unescape_string ( &fdata[start], &flen ); finish = start + flen; for ( j = start; j < finish; j++ ) if ( fdata[j] == '=' ) { /* * Append name to field list or retrieve current DCL symbol * value if already defined once. */ symname[prefix_len] = '\0'; k = add_symbol ( symname, &fdata[start], sym_list, &slist_len, symval, &vallen ); /* * Make DCL symbol. Construct symbol name from prefix * and portion before =, value is portion after. */ symbol.dsc$w_length = j - start + prefix_len; if ( symbol.dsc$w_length > 255 ) symbol.dsc$w_length = 255; strncpy ( &symname[prefix_len], &fdata[start], symbol.dsc$w_length ); if ( j < finish ) if ( (vallen + finish-j) < 254 ) { /* Append new value to string */ if ( vallen > 0 ) symval[vallen++] = ','; strncpy(&symval[vallen], &fdata[j+1], finish-j-1 ); vallen += (finish-j-1); } value.dsc$w_length = vallen; value.dsc$a_pointer = symval; status = LIB$SET_SYMBOL ( &symbol, &value, &table ); if ( (status&1) == 0 ) fprintf(stderr, "Error defining CGI form symbol: %d\n", status ); break; } else { /* make field name upcase */ fdata[j] = _toupper(fdata[j]); if ( fdata[j] == '-' ) fdata[j] = '_'; } start = i+1; } } /* * Set final symbol, which is list of fields. */ prefix_len = strlen ( prefix ); strcpy ( &symname[prefix_len], "FIELDS" ); symbol.dsc$w_length = strlen ( symname ); value.dsc$w_length = slist_len; value.dsc$a_pointer = sym_list; status = LIB$SET_SYMBOL ( &symbol, &value, &table ); }