cgi_isapi.c

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /* cgi_isap.c © Copyright 1998-2005 by Raosoft Inc. All Rights Reserved.      */
00003 /*                                                                            */
00004 /* You may use and modify this file for your own use, but may not distribute  */
00005 /* it or derivative works without the prior written consent of Raosoft, Inc.  */
00006 /*                                                                            */
00007 /* If you choose to share your modifications with Raosoft, Inc. the company   */
00008 /* will attempt to incorporate them into future versions of this file.        */
00009 /*                                                                            */
00010 /* This software is provided "as is," and Raosoft makes no warranty, express  */
00011 /* or implied, of fitness for a particular application. Every measure has been*/
00012 /* taken to anticipate risks inherent to computer networks, but we cannot     */
00013 /* guarantee safety or reliability of this program in every situation.        */
00014 /*                                                                            */
00015 /* This code was tested on Apache 1.3.4. If you encounter problems with other */
00016 /* servers, send email to raosoft@raosoft.com and we will endeavor to make    */
00017 /* corrections.                                                               */
00018 /*                                                                            */
00019 /******************************************************************************/
00020 
00021 #include "cgi.h"
00022 
00023 #ifdef ISAPICGI
00024 #include <httpext.h>
00025 
00026 #ifdef __BORLANDC__
00027 #pragma warn -par
00028 #endif
00029 
00030 int CountChars(char * c, int comp)
00031 {
00032  int i = 0;
00033  while (*c) { if (*c == comp) i++; c++;}
00034  return i;
00035 }
00036 
00037 int ExpandUrl(char *url);
00038 /* in cgi_cgi.c */
00039 
00040 void swapchars(char * str, char find, char repl);
00041 /* in cgi_cgi.c */
00042 
00043 void SetupCGIData(STREAM htmlout,CGINameValue *data)
00044 {
00045 /* Date/Time format: 19960214 124253 */
00046  char Date[14],Time[14];
00047  char temp[256];
00048  DWORD size = 256;
00049 
00050  temp[0]=0;
00051  htmlout->ecb->GetServerVariable(
00052              htmlout->ecb->ConnID, "REMOTE_ADDR",temp,&size);
00053 
00054  if (temp[0]==0) /* Apache */
00055  htmlout->ecb->GetServerVariable(
00056              htmlout->ecb->ConnID, "REMOTE_HOST",temp,&size);
00057 
00058  if (temp[0]==0) /* Apache */
00059  htmlout->ecb->GetServerVariable(
00060              htmlout->ecb->ConnID, "HTTP_ADDR",temp,&size);
00061 
00062  if (temp[0]==0) /* Apache */
00063  htmlout->ecb->GetServerVariable(
00064              htmlout->ecb->ConnID, "HTTP_HOST",temp,&size);
00065 
00066  data[0].value=strdup(temp);
00067  data[0].name=strdup("HOST");
00068 
00069  GetTime(Date,Time,0);
00070 
00071  data[1].value = strdup(Date);
00072  data[1].name = strdup("DATE");
00073 
00074  data[2].value = strdup(Time);
00075  data[2].name = strdup("TIME");
00076 }
00077 
00078 CGINameValue * DecodeTextBlock(int start, char * in_datap, int length, int extra)
00079 {
00080  CGINameValue * argv;
00081  int x;
00082  int i;
00083  char *c, *d, *e, *datap;
00084 
00085  if (in_datap == NULL) return NULL;
00086  if (length == 0) return NULL;
00087 
00088  datap = strndup(in_datap,length);
00089 
00090  /* count how many data entries there are, and allocate one extra */
00091  i = start + extra + CountChars(datap,'&') + 1;
00092 
00093  argv = NewNVP(i);
00094 
00095  if (argv == NULL) {CGIFREE(datap); return NULL;}
00096 
00097  for (i=0; i<extra; i++)
00098  {
00099   argv[start+i].name = strdup("");
00100   argv[start+i].value = strdup("");
00101  }
00102 
00103  x = start + extra;
00104 
00105  /* read the input fields */
00106  /* datap must be null-terminated. Both IIS and Apache do this. */
00107  i=0;
00108  d = datap;
00109 
00110  while (i < length)
00111       {
00112        e = strchr(d,'&'); /* end */
00113        if (e != NULL) *e = 0;
00114 
00115        i += strlen(d);
00116        i++;
00117 
00118        swapchars(d,'+',' '); /*plus to space*/
00119 
00120        c = strchr(d,'='); /* divider */
00121        if (c != NULL) { *c = 0; c++; }
00122        else           { c = NULLSTR; }
00123 
00124        ExpandUrl(d);
00125        swapchars(d,'\t',' '); /*remove tabs*/
00126        swapchars(d,'\r',' '); /*remove carriage-returns*/
00127        swapchars(d,'\n',' '); /*remove linefeeds*/
00128 
00129        if (c != NULL)
00130        {
00131         ExpandUrl(c);
00132         swapchars(c,'\t',' '); /*remove tabs*/
00133         swapchars(c,'\r',' '); /*remove carriage-returns*/
00134         swapchars(c,'\n',' '); /*remove linefeeds*/
00135        }
00136 
00137        if (d[0])
00138        {
00139         argv[x].name = strdup(d);
00140         argv[x].value = strdup(c);
00141         x++;
00142        }
00143 
00144        if (e == NULL) break;
00145        d = e + 1;
00146        while (i < length && datap[i] == '&') i++;
00147       }
00148 
00149  CGIFREE(datap);
00150  return argv;
00151 }
00152 
00153 HINSTANCE hInstance;
00154 
00155 BOOL WINAPI DllEntryPoint(
00156     HINSTANCE hinstDLL,
00157     DWORD reason,
00158     LPVOID reserved
00159    )
00160 {
00161  hInstance = hinstDLL;
00162  return TRUE;
00163 }
00164 
00165 char ISAPIenv[256];
00166 
00167 char * GetEnvironment(STREAM htmlout,char* key)
00168 {
00169  unsigned long size=256;
00170  if (htmlout->ecb->GetServerVariable(htmlout->ecb->ConnID, key,ISAPIenv,&size) == TRUE)
00171   return ISAPIenv;
00172  return NULL;
00173 }
00174 
00175 int SendCGIHeader(STREAM htmlout,char * hdr)
00176 {
00177  DWORD size = 6;
00178  if (hdr == NULL || !strlen(hdr)) hdr = CGI_DEFAULT_HEADER;
00179 
00180  if (strstr(hdr,"Location:"))
00181  {
00182    hdr += 9;
00183    while (hdr[0] == ' ') hdr++;
00184    size = strlen(hdr);
00185      htmlout->ecb->ServerSupportFunction(
00186     htmlout->ecb->ConnID, HSE_REQ_SEND_URL_REDIRECT_RESP,
00187     hdr,&size,0);
00188  }
00189  else
00190  {
00191    htmlout->ecb->ServerSupportFunction(
00192     htmlout->ecb->ConnID, HSE_REQ_SEND_RESPONSE_HEADER,
00193     "200 OK",&size,(DWORD*)(void*)hdr);
00194  }
00195  return 1;
00196 }
00197 
00198 /* main callback function */
00199 #ifdef __BORLANDC__
00200 DWORD WINAPI _export HttpExtensionProc(EXTENSION_CONTROL_BLOCK* ecb)
00201 #elif defined(__MWERKS__)
00202 DWORD WINAPI export HttpExtensionProc(EXTENSION_CONTROL_BLOCK* ecb)
00203 #else
00204 DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK* ecb)
00205 #endif
00206 {
00207     char argv0[MAXPATH],scriptname[MAXPATH];
00208     DWORD size;
00209     char temp[128];
00210     char host[128];
00211     int argc =0;
00212     int i;
00213     CGINameValue * argv =NULL;
00214     EZSSTREAM htmlout;
00215 
00216     htmlout.ecb = ecb;
00217     htmlout.pos = 0;
00218     htmlout.t = 0;
00219     htmlout.f = 0;
00220 
00221     host[0]=0;
00222     size=sizeof(host);
00223     ecb->GetServerVariable(ecb->ConnID, "REMOTE_ADDR",host,&size);
00224 
00225     if (!host[0])
00226     {
00227      size=sizeof(host);
00228      ecb->GetServerVariable(ecb->ConnID, "HTTP_ADDR",host,&size);
00229     }
00230     if (!host[0])
00231     {
00232      size=sizeof(host);
00233      ecb->GetServerVariable(ecb->ConnID, "REMOTE_HOST",host,&size);
00234     }
00235     if (!host[0])
00236     {
00237      size=sizeof(host);
00238      ecb->GetServerVariable(ecb->ConnID, "HTTP_HOST",host,&size);
00239     }
00240     /* The Apache group uses HTTP_HOST instead. */
00241 
00242     /* GetModuleFileName(GetModuleHandle(NULL),argv0,MAXPATH);*/
00243     /* GetModuleFileName(hInstance,argv0,MAXPATH);*/
00244 
00245     /* is it get GET or POST ? */
00246 
00247     temp[0]=0;
00248     size=sizeof(temp);
00249     ecb->GetServerVariable(
00250              ecb->ConnID, "REQUEST_METHOD",temp,&size);
00251 
00252     if (stricmp(temp,"POST") == 0)
00253     {/* It's post data. */
00254      /* Is it the right format? We don't read AcroForm data. */
00255      size=sizeof(temp);
00256 
00257      ecb->GetServerVariable(
00258               ecb->ConnID, "CONTENT_TYPE",temp,&size);
00259 
00260      if (strnicmp(temp,"application/x-www-form-urlencoded",33) != 0)
00261        return HSE_STATUS_ERROR;
00262 
00263         /* Parse the incoming data, up to 48k worth */
00264 
00265      if (ecb->cbTotalBytes && ecb->cbAvailable < ecb->cbTotalBytes && ecb->cbTotalBytes < 1024*512)
00266      {
00267       char* c = malloc(ecb->cbTotalBytes+1);
00268       size_t offset = ecb->cbAvailable;
00269       if (!c) return HSE_STATUS_ERROR;
00270       memcpy(c,(char*)ecb->lpbData,offset);
00271       while (offset < ecb->cbTotalBytes)
00272       {
00273        DWORD size=4096;
00274        if (!ecb->ReadClient(ecb->ConnID,c+offset,&size)) break;
00275        if (!size) break;
00276        offset += size;
00277       }
00278       c[offset]=0;
00279       argv = DecodeTextBlock(3,c,offset,64);
00280      }
00281      else
00282      {
00283       argv = DecodeTextBlock(3,(char*)ecb->lpbData,ecb->cbAvailable,64);
00284      }
00285      //3 for HOST,DATE,TIME, 4 for _PAGENEXT,_PAGEBACK, ...
00286     }
00287     else if (stricmp(temp,"GET") == 0)
00288     {/* It's get or an extended path. Either way, it's the same parser. */
00289      char * c = ecb->lpszQueryString;
00290      if (c != NULL && c[0]) /* blank queries ignored */
00291       {
00292        if (strchr(c,'&')==NULL) swapchars(c,'/','&');
00293         /* breaks up extended path variables into tokens */
00294        argv = DecodeTextBlock(3,c,strlen(c),64);
00295       }
00296     }
00297 
00298     if (argv != NULL)
00299       {
00300        SetupCGIData(&htmlout,argv);
00301        while (argv[argc].name) argc++;
00302       }
00303 
00304     size = sizeof(argv0);
00305     argv0[0]=0;
00306 
00307     {/* get the directory from the registry */
00308      HKEY Key;
00309      DWORD len=size,type;
00310      char * database = GetFieldValue(argv,"DATABASE");
00311      if (!*database) database = GetFieldValue(argv,"FILE"); /* for dbadmin.dll */
00312 
00313      if (RegOpenKey(HKEY_LOCAL_MACHINE,
00314                     "SOFTWARE\\Raosoft\\CGI\\Directories",
00315                     &Key) == ERROR_SUCCESS)
00316      {
00317       RegQueryValueEx(Key,database,0,&type,(LPBYTE)(char*)argv0,&len);
00318       RegCloseKey(Key); /* that should give a working directory */
00319       size = strlen(argv0);
00320       if (argv0[size-1] != '\\')
00321        strcat(argv0,"\\");
00322      }
00323     }
00324 
00325     /* we have a directory, now get the script name */
00326     size = sizeof(scriptname);
00327     scriptname[0]=0;
00328 
00329     ecb->GetServerVariable(    /* apache */
00330              ecb->ConnID, "SCRIPT_FILENAME",scriptname,&size);
00331 
00332     if (scriptname[0] == 0)
00333     ecb->GetServerVariable(    /* iis */
00334              ecb->ConnID, "SCRIPT_NAME",scriptname,&size);
00335 
00336     if (argv0 == 0)
00337     {
00338       strcpy(argv0,scriptname);
00339     }
00340     else if (scriptname[0] != 0)
00341     {
00342       char * end;
00343       swapchars(scriptname,'/','\\');
00344       end = strrchr(scriptname,'\\');
00345       if (end != NULL) strcat(argv0,end+1);
00346       else strcat(argv0,scriptname);
00347     }
00348     else
00349     {
00350       SendCGIHeader(&htmlout,NULL);
00351       HTMLWrite(&htmlout,"Error: Unable to determine the server working directory");
00352       LogError("\nISAPI: Unable to determine the working directory and script name ");
00353       LogError(host);
00354 
00355       if (argv != NULL) DeleteNVP(argv);
00356       return HSE_STATUS_SUCCESS;
00357     }
00358 
00359     /* ta da! Now we have a complete file name. */
00360 
00361 
00362     /* turn forward slashes into backslashes
00363     Security = GetSecurityFlags(argv0,host,GetFieldValue(argv,"DATABASE"),
00364                                            GetFieldValue(argv,"_PASSWORD"));
00365 
00366     */
00367 #ifndef CGI_FAST
00368     LogStartup(&htmlout,argv0);
00369     LogConnection(argv0,host);
00370     if (argv) LogTrx(argv);
00371 #endif
00372 
00373     if (argv == NULL)
00374      argv = NewNVP(1);
00375 
00376     i = CGImain(argv0,argv,&htmlout);
00377 
00378     if (argv != NULL)
00379      DeleteNVP(argv);
00380 
00381 
00382     if (i)
00383     {
00384         char file[MAXPATH];
00385         ExpandLocalPath(argv0,file,"error.html",NULLSTR);
00386         HTMLWriteFile(&htmlout,file);
00387     }
00388 
00389     if (i == 101) /* security violation */
00390      {
00391       HTMLWrite(&htmlout,"Error: Access denied.");
00392       LogConnection(argv0,host);
00393       LogMessage(",ERROR=Access denied");
00394       return HSE_STATUS_SUCCESS;
00395      }
00396     else if (i != 0)
00397      {
00398       ecb->dwHttpStatusCode = i;
00399       HTMLPrintf(&htmlout,
00400       "<P><A href=http://www.raosoft.com/help/cgi/ezs/error.html#s%d>Error %d</a>\n",i,i);
00401       HTMLWrite(&htmlout,"<!-- Raosoft CGI " RAOSOFT_CGI_VERSION " -->");
00402      }
00403 
00404     if (htmlout.pos)
00405       htmlout.ecb->WriteClient(htmlout.ecb->ConnID, (PVOID)htmlout.buffer, &htmlout.pos, 0 );
00406 
00407     return HSE_STATUS_SUCCESS;
00408     /* apache can't deal with error returns */
00409     /* return HSE_STATUS_ERROR;*/
00410 }
00411 
00412 #ifdef __BORLANDC__
00413 BOOL WINAPI _export GetExtensionVersion(OUT HSE_VERSION_INFO * pVer)
00414 #elif defined(__MWERKS__)
00415 BOOL WINAPI export GetExtensionVersion(OUT HSE_VERSION_INFO * pVer)
00416 #else
00417 BOOL WINAPI GetExtensionVersion(OUT HSE_VERSION_INFO * pVer)
00418 #endif
00419 {
00420  pVer->dwExtensionVersion = MAKELONG(HSE_VERSION_MINOR, HSE_VERSION_MAJOR);
00421  lstrcpyn((LPSTR) pVer->lpszExtensionDesc,
00422           "EZSURVEY - Raosoft CGI extensions",
00423           HSE_MAX_EXT_DLL_NAME_LEN);
00424  return TRUE;
00425 }
00426 
00427 #ifdef __BORLANDC__
00428 BOOL WINAPI _export TerminateExtension(DWORD foo)
00429 #elif defined(__MWERKS__)
00430 BOOL WINAPI export GetExtensionVersion(OUT HSE_VERSION_INFO * pVer)
00431 #else
00432 BOOL WINAPI TerminateExtension(DWORD foo)
00433 #endif
00434 {
00435     return TRUE;
00436 }
00437 
00438 
00439 #endif
00440 


Raosoft, Inc.
Raosoft EZReport, EZSurvey, InterForm, RapidReport, Raosoft, and SurveyWin are registered trademarks of Raosoft, Inc. Page contents © 1996-2007 by Raosoft, Inc. You may use and modify this file for your own use, but may not distribute it or derivative works without the prior written consent of Raosoft, Inc. This software is provided "as is," and Raosoft makes no warranty, express or implied, of fitness for a particular application. Every measure has been taken to anticipate risks inherent to computer networks, but we cannot guarantee safety or reliability of this program in every situation.
Tel: 206-525-4025 (US) Email: raosoft@raosoft.com
http://www.raosoft.com/