00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "cgi.h"
00018
00019 #ifndef VPWSCGI
00020
00021 #ifdef EBCDIC
00022 static unsigned char ebcdic2ascii[] = {
00023 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 21, 11, 12, 13, 14,
00024 15,16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30,
00025 31,64, 90,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96,
00026 75,97,240,241,242,243,244,245,246,247,248,249,122,
00027 94,76,126,110,111,124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,
00028 214,215,216,217,226,227,228,229,230,231,232,233,173,224,189,
00029 95,109,121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150,151,152,
00030 153,162,163,164,165,166,167,168,169,192,79,208,161,
00031 7,32, 33, 34, 35, 36, 37, 6, 23, 40, 41, 42, 43, 44, 9, 10,27,48, 49,
00032 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4,
00033 20,62,255,65,170,74,177,159,178,106,181,187,180,154,138,176,202,175,188,144,
00034 143,234,250,190,160,182,179,157,218,155,139,183,184,185,171,100,101,
00035 98,102,99,103,158,104,116,113,114,115,120,117,118,119,172,105,237,238,235,
00036 239,236,191,128,253,254,251,252,186,174,
00037 89,68, 69, 66, 70, 67, 71,156, 72, 84, 81, 82, 83, 88, 85,
00038 86,87,140,73,205,206,203,207,204,225,112,221,222,219,220,141,142,223
00039 };
00040
00041 static unsigned char ascii2ebcdic[] = {
00042 0,1,2,3,236,9,202,127,226,210,211,11,12,13,14,169,16,17,18,19,
00043 239,197,8,203,24,25,220,216,28,29,30,31,183,184,185,187,196,10,23,27,
00044 204,205,207,208,209,5,6,7,217,218,22,221,222,223,224,4,227,229,233,235,
00045 176,177,158,26,32,201,131,132,133,160,242,134,135,164,213,46,60,40,43,179,
00046 38,130,136,137,138,161,140,139,141,225,33,36,42,41,59,94,45,47,178,142,
00047 180,181,182,143,128,165,124,44,37,95,62,63,186,144,188,189,190,243,192,193,
00048 194,96,58,35,64,39,61,34,195,97,98,99,100,101,102,103,104,105,174,175,
00049 198,199,200,241,248,106,107,108,109,110,111,112,113,114,166,167,145,206,146,15,
00050 230,126,115,116,117,118,119,120,121,122,173,168,212,91,214,215,155,156,157,250,
00051 159,21,20,172,171,252,170,254,228,93,191,231,123,65,66,67,68,69,70,71,
00052 72,73,232,147,148,149,162,237,125,74,75,76,77,78,79,80,81,82,238,150,
00053 129,151,163,152,92,240,83,84,85,86,87,88,89,90,253,245,153,247,246,249,
00054 48,49,50,51,52,53,54,55,56,57,219,251,154,244,234,255
00055 };
00056 #endif
00057
00058 void Translate(char*s,unsigned char* list)
00059 {
00060 unsigned char * x = (unsigned char*)s;
00061 while (*x) {*x = list[*x]; x++;}
00062 }
00063
00064 void LogConnection(char* program,char* host)
00065 {
00066 char Date[14],Time[14];
00067
00068 GetTime(Date,Time,0);
00069 LogMessage("Run\tPROGRAM=");
00070 LogMessage(program);
00071 LogMessage(",HOST=");
00072 LogMessage(host);
00073 LogMessage(",DATE=");
00074 LogMessage(Date);
00075 LogMessage(",TIME=");
00076 LogMessage(Time);
00077 LogMessage("\n");
00078 }
00079
00080 #ifdef WINCGI
00081
00082 char WinCGIFile[1024];
00083
00084 int InitWindowsCGI(char * setupfile,STREAM htmlin, STREAM htmlout)
00085 {
00086 char file[256];
00087
00088 if (setupfile)
00089 strcpy(WinCGIFile,setupfile);
00090 else
00091 {
00092 *WinCGIFile = 0;
00093 }
00094
00095 htmlin->t = htmlout->t = NULL;
00096
00097 #ifdef CONSOLECGI
00098 htmlin->f = stdin;
00099 htmlout->f = stdout;
00100 #else
00101 htmlin->f = NULL;
00102 htmlout->f = NULL;
00103 #endif
00104
00105 if (!*WinCGIFile) return 0;
00106
00107 if (GetPrivateProfileString("System","Output File",NULLSTR,file,256,WinCGIFile))
00108 {
00109 htmlout->f = CGIFOPEN(file,"wt");
00110 }
00111
00112 if (GetPrivateProfileString("System","Content File",NULLSTR,file,256,WinCGIFile))
00113 {
00114 htmlin->f = CGIFOPEN(file,"rt");
00115 }
00116
00117 #ifdef CONSOLECGI
00118 if (!htmlin->f) htmlin->f = stdin;
00119 if (!htmlout->f) htmlout->f = stdout;
00120 #endif
00121 if (!htmlout->f && !htmlin->f) return 0;
00122
00123 return 1;
00124 }
00125
00126 void DoneWindowsCGI(STREAM htmlin, STREAM htmlout)
00127 {
00128 #ifdef CONSOLECGI
00129 if (htmlin->f) if (htmlin->f != stdin) CGIFCLOSE(htmlin->f);
00130 if (htmlout->f) if (htmlout->f != stdout) CGIFCLOSE(htmlout->f);
00131 #else
00132 if (htmlin->f) CGIFCLOSE(htmlin->f);
00133 if (htmlout->f) CGIFCLOSE(htmlout->f);
00134 #endif
00135 }
00136 #endif
00137
00138 #ifndef ISAPICGI
00139 #if defined(WINCGI)
00140 int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
00141 LPSTR lpszCmdLine, int nShow)
00142 {
00143 int argc;
00144 char *argv[128];
00145 int IsCGI = 1;
00146 #else
00147 int main(int argc, char *argv[])
00148 {
00149 #ifdef FASTCGI
00150 int fcgiCount = 0;
00151 FCGISTREAM chtmlin,chtmlerr,chtmlout;
00152 STREAM htmlerr;
00153 #else
00154 EZSSTREAM ehtmlin, ehtmlout;
00155 #endif
00156 #endif
00157 CGINameValue * Params;
00158 int i;
00159 STREAM htmlin;
00160 STREAM htmlout;
00161 char * host;
00162
00163 #ifdef FASTCGI
00164 htmlin=&chtmlin;
00165 htmlout=&chtmlout;
00166 htmlerr=&chtmlerr;
00167 htmlin->envp = htmlout->envp = htmlerr->envp = NULL;
00168 while (FCGX_Accept(&htmlin->strp, &htmout->strp, &htmlerr->strp, &htmlout.envp) >= 0)
00169 {
00170 htmlin->envp = htmlerr->envp = htmlout->envp;
00171 fcgiCount++;
00172 }
00173 #else
00174 htmlin = &ehtmlin; htmlout = &ehtmlout;
00175 #ifdef WINCGI
00176 argc = SplitArgs(lpszCmdLine, argv,128);
00177 if (!InitWindowsCGI(argv[1],htmlin,htmlout)) return 1;
00178 #else
00179
00180 #ifdef XP_WIN
00181 swapchars(argv[0],'/','\\');
00182 setmode(fileno(stdout),O_BINARY);
00183 #endif
00184
00185 htmlin->t = NULL;
00186 htmlin->f = stdin;
00187
00188 htmlout->t = NULL;
00189 htmlout->f = stdout;
00190 #endif
00191 #endif
00192
00193 switch ( CheckCGISendMethod(htmlin) )
00194 {
00195 case 0: Params = ReadCGIPostData(htmlin,64); break;
00196 case 1: Params = ReadCGIGetData(htmlin,64); break;
00197 case 2: Params = 0; break;
00198 default:Params = argc ? ReadPairedValues(argc-1,argv+1,64) : 0;
00199 };
00200
00201 host = Params != NULL ? GetFieldValue(Params,"HOST") : "unknown";
00202
00203 #ifndef CGI_FAST
00204 LogStartup(htmlout,argv[0]);
00205 LogConnection(argv[0],host);
00206 if (Params) LogTrx(Params);
00207 #endif
00208
00209 if (!Params) Params = NewNVP(1);
00210
00211 i = CGImain(argv[0],Params,htmlout);
00212
00213 if (i)
00214 {
00215 char file[MAXPATH];
00216 ExpandLocalPath(argv[0],file,"error.html",NULLSTR);
00217 HTMLWriteFile(htmlout,file);
00218 }
00219
00220 if (i == 101)
00221 {
00222 HTMLWrite(htmlout,"<P>Error: Access denied.\n");
00223 HTMLWrite(htmlout,"<!-- Raosoft CGI " RAOSOFT_CGI_VERSION " -->");
00224 LogMessage(",ERROR=Access denied");
00225 }
00226 else if (i != 0)
00227 {
00228 char err[128];
00229 HTMLPrintf(htmlout,
00230 "<P><A href=http://www.raosoft.com/help/cgi/ezs/error.html#s%d>Error %d</a>\n",i,i);
00231 HTMLWrite(htmlout,"<!-- Raosoft CGI " RAOSOFT_CGI_VERSION " -->");
00232 sprintf(err,"\nCGImain returned %d",i);
00233 LogError(err);
00234 #ifndef CGI_FAST
00235 LogError("\nCGI parameters");
00236 for (i=0;Params[i].name; i++)
00237 {
00238 if (!Params[i].name[0]) continue;
00239 LogError("\n");LogError(Params[i].name);LogError("=");LogError(Params[i].value);
00240 }
00241 LogError("\nEnvironment\nContent_type=");
00242 LogError(GetEnvironment(htmlout,"CONTENT_TYPE"));
00243 LogError("\nQUERY_STRING=");
00244 LogError(GetEnvironment(htmlout,"QUERY_STRING"));
00245 LogError("\nREQUEST_METHOD=");
00246 LogError(GetEnvironment(htmlout,"REQUEST_METHOD"));
00247 LogError("\nCONTENT_LENGTH=");
00248 LogError(GetEnvironment(htmlout,"CONTENT_LENGTH"));
00249 #endif
00250 }
00251
00252 #ifdef WINCGI
00253 DoneWindowsCGI(htmlin,htmlout);
00254 #endif
00255 if (Params) DeleteNVP(Params);
00256
00257 return 0;
00258 }
00259 #endif
00260
00261 #ifndef ISAPICGI
00262 int SendCGIHeader(STREAM htmlout,char * header)
00263 {
00264 if (header != NULL)
00265 if (strlen(header))
00266 { HTMLWrite(htmlout,header); return 1;}
00267 HTMLWrite(htmlout,CGI_DEFAULT_HEADER);
00268 return 1;
00269 }
00270 #endif
00271
00272
00273 #define NEWALLOCSIZE 128
00274
00275 #ifdef FASTCGI
00276 #define NEXTCHAR(s) FCGX_GetChar(s->strp)
00277 #define TESTEOF(s) FCGX_HasSeenEOF(s->strp)
00278 #else
00279 #define NEXTCHAR(s) fgetc(s->f)
00280 #define TESTEOF(s) feof(s->f)
00281 #endif
00282
00283 #define MAXSIZE 65535
00284 #ifndef ISAPICGI
00285
00286 char *fmakeword(STREAM in, char stop, int *cl) {
00287 int wsize;
00288 char *word;
00289 int ll;
00290
00291 wsize = NEWALLOCSIZE;
00292 ll=0;
00293 word = (char *) CGIMALLOC(sizeof(char) * (wsize + 1));
00294
00295 while(1) {
00296 word[ll] = (char)NEXTCHAR(in);
00297 if(ll==wsize) {
00298 word[ll+1] = 0;
00299 wsize+=NEWALLOCSIZE;
00300 if (wsize > MAXSIZE)
00301 break;
00302 else
00303 {
00304 char* W2 = (char *)realloc(word,sizeof(char)*(wsize+1));
00305 if (!W2) break;
00306 word = W2;
00307 }
00308 }
00309 --(*cl);
00310 if((word[ll] == stop) || (TESTEOF(in)) || (!(*cl))) {
00311 if(word[ll] != stop) ll++;
00312 word[ll] = '\0';
00313 return word;
00314 }
00315 ++ll;
00316 }
00317
00318 free(word);
00319 return 0;
00320 }
00321
00322 #endif
00323
00324
00325
00326 #ifndef ISAPICGI
00327 #ifdef WINCGI
00328 char WINCGIenv[256];
00329 #endif
00330
00331
00332 extern int CGILogLevel;
00333
00334 char * GetEnvironment(STREAM htmlout,char* key)
00335 {
00336 #ifdef WINCGI
00337 GetPrivateProfileString("System",key,NULLSTR,WINCGIenv,256,WinCGIFile);
00338 return WINCGIenv;
00339 #elif defined(FASTCGI)
00340 return FCGX_GetParam(key,htmlout->envp);
00341 #else
00342 return getenv(key);
00343 #endif
00344 }
00345
00346 void SetupCGIData(STREAM htmlin,CGINameValue *data)
00347 {
00348
00349 char Date[14],Time[14];
00350 char * host;
00351 char temp[256];
00352 temp[0]=0;
00353
00354
00355
00356 #ifdef WINCGI
00357 GetPrivateProfileString("System","Remote Address",NULLSTR,temp,256,WinCGIFile);
00358 SetFieldValue(data,"HOST",temp);
00359 #else
00360 host = GetEnvironment(htmlin,"REMOTE_ADDR");
00361 if (host == NULL || host[0] == 0) host = GetEnvironment(htmlin,"HTTP_ADDR");
00362 if (host == NULL || host[0] == 0) host = GetEnvironment(htmlin,"REMOTE_HOST");
00363 if (host == NULL || host[0] == 0) host = GetEnvironment(htmlin,"HTTP_HOST");
00364 if (host == NULL || host[0] == 0) host = "unknown";
00365 SetFieldValue(data,"HOST",host);
00366 #endif
00367
00368 GetTime(Date,Time,0);
00369
00370 SetFieldValue(data,"DATE",Date);
00371
00372
00373 SetFieldValue(data,"TIME",Time);
00374 }
00375
00376 CGINameValue* ReadCGIGetData(STREAM htmlin,int extra)
00377 {
00378 char * c;
00379 CGINameValue* data;
00380 int x;
00381 #ifdef WINCGI
00382 c = CGIMALLOC(65535);
00383 GetPrivateProfileString("CGI","Query String",NULLSTR,c,65535,WinCGIFile);
00384 #else
00385 c = GetEnvironment(htmlin,"QUERY_STRING");
00386 #endif
00387
00388 if (c && *c)
00389 {
00390 #ifdef EBCDIC
00391 Translate(c,ascii2ebcdic);
00392 #endif
00393
00394
00395
00396 data = ReadPairedString(c,'&',3+extra);
00397 }
00398 else
00399 {
00400 #ifdef WINCGI
00401 GetPrivateProfileString("CGI","Logical Path",NULLSTR,c,65535,WinCGIFile);
00402 #else
00403 c = GetEnvironment(htmlin,"PATH_INFO");
00404 #endif
00405 if (c &&*c)
00406 {
00407 #ifdef EBCDIC
00408 Translate(c,ascii2ebcdic);
00409 #endif
00410 if (*c=='/') c++;
00411 if (!strchr(c,'&')) data = ReadPairedString(c,'/',3+extra);
00412 else data = ReadPairedString(c,'&',3+extra);
00413 }
00414 else return 0;
00415 }
00416
00417 if (!data) return 0;
00418 SetupCGIData(htmlin,data);
00419
00420 #ifndef WINCGI
00421 for (x = 3+extra; data[x].name; x++)
00422 {
00423 swapchars(data[x].name,'+',' ');
00424 swapchars(data[x].value,'+',' ');
00425 ExpandUrl(data[x].name);
00426 ExpandUrl(data[x].value);
00427
00428 if (strstr(data[x].name,"+AAA"))
00429 {
00430 UTF7toUTF8(data[x].name);
00431 UTF7toUTF8(data[x].value);
00432 }
00433 else if (ContainsANSIChars(data[x].value))
00434 {
00435 char* c = data[x].value;
00436 data[x].value = ANSItoUTF8(c);
00437 free(c);
00438 }
00439 swapchars(data[x].name,'\t',' ');
00440 swapchars(data[x].name,'\r',' ');
00441 swapchars(data[x].name,'\n',' ');
00442 swapchars(data[x].value,'\t',' ');
00443 swapchars(data[x].value,'\r',' ');
00444 swapchars(data[x].value,'\n',' ');
00445 }
00446 #endif
00447
00448 #ifdef WINCGI
00449 CGIFREE(c);
00450 #endif
00451 return data;
00452 }
00453
00454 #ifdef WINCGI
00455 CGINameValue* ReadCGIPostData(STREAM htmlin,int extra)
00456 {
00457 CGINameValue * data = 0;
00458 data = ReadINIFileSection(WinCGIFile,"Form Literal",3 + extra);
00459 if (data)
00460 SetupCGIData(htmlin,data);
00461 return data;
00462 }
00463 #else
00464
00465 #define MAX_ENTRIES 1000
00466 CGINameValue* ReadCGIPostData(STREAM htmlin,int reserve)
00467 {int cl;
00468 register int x;
00469 char * c;
00470 int maxsize = MAX_ENTRIES + reserve;
00471 int growcount = 0;
00472 #ifdef EBCDIC
00473 char stopstr[2];
00474 #endif
00475
00476 CGINameValue* data;
00477
00478 #ifdef EBCDIC
00479 stopstr[0]='&';
00480 stopstr[1]=0;
00481 Translate(stopstr,ebcdic2ascii);
00482 #endif
00483
00484 c = getenv("CONTENT_LENGTH");
00485 cl = c ? atoi(c) : 0;
00486
00487 if (cl == 0) return NULL;
00488 if (!htmlin->f) return NULL;
00489
00490
00491 data = NewNVP(maxsize);
00492
00493 for (x=0; x<reserve; x++)
00494 {
00495 data[x].name=strdup(NULLSTR);
00496 data[x].value=strdup(NULLSTR);
00497 }
00498
00499 SetupCGIData(htmlin,data);
00500 x=reserve;
00501
00502 while((cl > 0) && (!feof(htmlin->f)) && (growcount < 64 ))
00503 {
00504
00505 if (x == maxsize)
00506 {
00507 CGINameValue* newdata = NewNVP(maxsize+ MAX_ENTRIES);
00508 if (newdata == NULL) return data;
00509 memcpy(newdata,data,maxsize * sizeof(CGINameValue));
00510 CGIFREE(data);
00511 data = newdata;
00512 maxsize += MAX_ENTRIES;
00513 growcount++;
00514 }
00515
00516 #ifdef EBCDIC
00517
00518 c = fmakeword(htmlin,stopstr[0],&cl);
00519 #else
00520 c = fmakeword(htmlin,'&',&cl);
00521 #endif
00522
00523 #ifdef EBCDIC
00524 Translate(c,ascii2ebcdic);
00525 #endif
00526
00527 if (!c) {DeleteNVP(data); return NULL;}
00528 swapchars(c,'+',' ');
00529 ExpandUrl(c);
00530
00531 data[x].name = c;
00532
00533 c = strchr(c,'=');
00534 if ((c) && (*c))
00535 {
00536 *c++ = 0;
00537 data[x].value = strdup(c);
00538 }
00539 else
00540 {
00541 data[x].value = strdup(NULLSTR);
00542 }
00543
00544 if (strstr(data[x].name,"+AAA"))
00545 {
00546 UTF7toUTF8(data[x].name);
00547 UTF7toUTF8(data[x].value);
00548 }
00549 else if (ContainsANSIChars(data[x].value))
00550 {
00551 char* c = data[x].value;
00552 data[x].value = ANSItoUTF8(c);
00553 free(c);
00554 }
00555
00556 swapchars(data[x].name,'\t',' ');
00557 swapchars(data[x].name,'\r',' ');
00558 swapchars(data[x].name,'\n',' ');
00559 swapchars(data[x].value,'\t',' ');
00560 swapchars(data[x].value,'\r',' ');
00561 swapchars(data[x].value,'\n',' ');
00562
00563 x++;
00564 }
00565 return data;
00566 }
00567
00568 #endif
00569
00570
00571 int CheckCGISendMethod(STREAM htmlin)
00572 {
00573 #ifdef WINCGI
00574 char c[256],host[256];
00575 if (!*WinCGIFile) return 3;
00576 GetPrivateProfileString("CGI","Request Method",NULLSTR,c,256,WinCGIFile);
00577 #else
00578 char * c;
00579
00580 c = GetEnvironment(htmlin,"REQUEST_METHOD");
00581 #endif
00582
00583 if (!c) return 3;
00584
00585 if (c && (stricmp(c,"GET") == 0))
00586 {
00587 return 1;
00588 }
00589
00590 #ifndef WINCGI
00591 if (c && (stricmp(c,"POST") == 0))
00592 {
00593 c = getenv("CONTENT_TYPE");
00594
00595 if(c && strnicmp(c,"application/x-www-form-urlencoded",33))
00596 {
00597 return 2;
00598 }
00599 return 0;
00600 }
00601 return 0;
00602 #else
00603 return 0;
00604 #endif
00605 }
00606 #endif
00607
00608 #endif