00001 #include <string.h>
00002 #include <stdlib.h>
00003 #include <stdio.h>
00004 #ifdef WIN32
00005 #include <process.h>
00006 #include <winsock2.h>
00007 #include <winbase.h>
00008 #include <tlhelp32.h>
00009
00010 #include "service.h"
00011
00012 VOID CmdInstallService();
00013 VOID CmdRemoveService();
00014 void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
00015
00016 #else
00017 #include <sys/time.h>
00018 #include <sys/types.h>
00019 #include <netinet/in.h>
00020 #include <netdb.h>
00021 #include <unistd.h>
00022 #include <signal.h>
00023 #include <sys/wait.h>
00024 #endif
00025
00026 #include "../../thread.h"
00027 #include "../../filesys.h"
00028 #include "../../httpd.h"
00029 #include "../../logger.h"
00030 #include "../../scriba.h"
00031
00032 #if WIN32
00033
00034
00035 static BOOL AmIService(void){
00036 DWORD dwMyPid,dwParentPid;
00037 PROCESSENTRY32 pe;
00038 HANDLE th;
00039
00040
00041 dwMyPid = GetCurrentProcessId();
00042 th = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
00043 if( INVALID_HANDLE_VALUE == th )return FALSE;
00044
00045 pe.dwSize = sizeof(PROCESSENTRY32);
00046
00047 if( ! Process32First(th,&pe) )return FALSE;
00048
00049
00050 while( pe.th32ProcessID != dwMyPid ){
00051 pe.dwSize = sizeof(PROCESSENTRY32);
00052 if( ! Process32Next(th,&pe) )break;
00053 }
00054 if( pe.th32ProcessID == dwMyPid ){
00055 dwParentPid = pe.th32ParentProcessID;
00056 }else{
00057 return FALSE;
00058 }
00059
00060 if( ! Process32First(th,&pe) ){
00061 return FALSE;
00062 }
00063
00064
00065 while( pe.th32ProcessID != dwParentPid ){
00066 pe.dwSize = sizeof(PROCESSENTRY32);
00067 if( ! Process32Next(th,&pe) )break;
00068 }
00069 if( pe.th32ProcessID == dwParentPid ){
00070
00071 if( 0 == strnicmp("SERVICES",pe.szExeFile,8) )return TRUE;
00072 return FALSE;
00073 }else{
00074 return FALSE;
00075 }
00076 }
00077 #endif
00078
00079 #define FULL_PATH_BUFFER_LENGTH 256
00080 #define INBLEN 10
00081
00082
00083
00084
00085
00086 typedef struct _WebData {
00087 pSbProgram pProgramConfig;
00088 char *pszHome;
00089 char szPort[10];
00090 int XForwarded;
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 tLogger HitLog,StatLog,AppLog,ErrLog,PanicLog;
00112
00113
00114
00115
00116
00117
00118 int nolog;
00119
00120
00121
00122 char *msg404;
00123
00124
00125
00126
00127 char *code404;
00128
00129
00130
00131
00132 char *run404;
00133
00134
00135 unsigned long cVdir;
00136
00137
00138 char **ppszVdir;
00139
00140
00141 char *pszPid;
00142
00143
00144 unsigned long lWaitLoop;
00145
00146
00147 #define ERRMSGCLIENT 0x01
00148 #define ERRMSGERRLOG 0x02
00149 unsigned long bErrMsgDest;
00150
00151 pHttpdThread pHT;
00152 } WebData, *pWebData;
00153
00154
00155
00156
00157 typedef struct _ApplicationThreadData {
00158 char *pszPathTranslated;
00159 char *pszClientIP;
00160 char *pszRemoteUser;
00161 char *pszPassword;
00162 #define OBLEN 20
00163 #define ENVLEN 256
00164 unsigned char szBuffer[OBLEN];
00165 unsigned char szEnvBuf[ENVLEN];
00166 unsigned char cbBuffer;
00167 unsigned char szInBuffer[INBLEN];
00168 unsigned long cbInBuffer;
00169 unsigned char *pszInBuffer;
00170 char *pszFtpCommand;
00171 char szThreadIndex[20];
00172 int FirstHeaderLine;
00173 }ApplicationThreadData, *pApplicationThreadData;
00174
00175 #ifdef WIN32
00176 static pHttpdThread pHT_Service;
00177 #endif
00178
00179 static char six2pr[64] = {
00180 'A','B','C','D','E','F','G','H','I','J','K','L','M',
00181 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
00182 'a','b','c','d','e','f','g','h','i','j','k','l','m',
00183 'n','o','p','q','r','s','t','u','v','w','x','y','z',
00184 '0','1','2','3','4','5','6','7','8','9','+','/'
00185 };
00186 static unsigned char pr2six[256];
00187 static int uudecode(char *bufcoded,
00188 unsigned char *bufplain,
00189 int outbufsize){
00190
00191 #define DEC(c) pr2six[(int)c]
00192 #define MAXVAL 63
00193
00194 static int first = 1;
00195 char a[4];
00196 int j;
00197 char *bufin = bufcoded;
00198 unsigned char *bufout = bufplain;
00199
00200
00201
00202 if(first) {
00203 first = 0;
00204 for(j=0; j<256; j++) pr2six[j] = MAXVAL+1;
00205 for(j=0; j<64; j++) pr2six[(int)six2pr[j]] = (unsigned char) j;
00206 }
00207
00208 bufin = bufcoded;
00209
00210 while( *bufin && outbufsize ){
00211 for( j = 0 ; j < 4 ; j++ )
00212 if( *bufin && pr2six[*bufin] <= MAXVAL )a[j] = *bufin++; else a[j] = 'A';
00213 *(bufout++) = (unsigned char) (DEC(*a) << 2 | DEC(a[1]) >> 4);
00214 outbufsize--;
00215 if( outbufsize < 2 ) break;
00216 *(bufout++) = (unsigned char) (DEC(a[1]) << 4 | DEC(a[2]) >> 2);
00217 outbufsize--;
00218 if( outbufsize < 2) break;
00219 *(bufout++) = (unsigned char) (DEC(a[2]) << 6 | DEC(a[3]));
00220 outbufsize--;
00221 if( outbufsize < 2) break;
00222 }
00223
00224 *bufout = (char)0;
00225
00226 return 0;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 static char *prefix(char *t, char *p){
00238
00239 if( t == NULL )return NULL;
00240 if( p == NULL )return NULL;
00241 while( *t && *p && *p != ':' ){
00242 if( *p != *t )return NULL;
00243 p++;
00244 t++;
00245 }
00246 if( ! *p )return NULL;
00247 if( *p == ':' )return ++p;
00248 return NULL;
00249 }
00250
00251
00252
00253
00254
00255 static int maskip(char *s, unsigned long *ip, unsigned long *mask){
00256 int i;
00257 int digit;
00258
00259 *ip = 0;
00260 for( i = 0 ; i < 4 ; i++ ){
00261 digit = 0;
00262 while( isdigit( *s ) ){
00263 digit = 10*digit + *s++ -'0';
00264 }
00265 if( digit > 255 || (*s != '.' && *s != '/' ) )return 1;
00266 if( *s == '.' )s++;
00267 *ip = 256* *ip + digit;
00268 }
00269
00270 if( *s != '/' )return 1;
00271 s++;
00272 *mask = 0;
00273 for( i = 0 ; i < 4 ; i++ ){
00274 digit = 0;
00275 while( isdigit( *s ) ){
00276 digit = 10*digit + *s++ -'0';
00277 }
00278 if( digit > 255 || (*s != '.' && *s != (char)0 ) )return 1;
00279 if( *s == '.' )s++;
00280 *mask = 256* *mask + digit;
00281 }
00282 return 0;
00283 }
00284
00285
00286 static void httpd_report(void *pEmbedPointer,
00287 char *FileName,
00288 long LineNumber,
00289 unsigned int iErrorCode,
00290 int iErrorSeverity,
00291 int *piErrorCounter,
00292 char *szErrorString,
00293 unsigned long *fFlags
00294 ){
00295 pThreadData pT = pEmbedPointer;
00296 pHttpdThread pHT = pT->pThreadLocalData;
00297 pWebData pWD = pHT->AppData;
00298 char buf[256],*s;
00299
00300 if( iErrorSeverity >= REPORT_ERROR && piErrorCounter )(*piErrorCounter)++;
00301
00302 if( pWD->bErrMsgDest & ERRMSGCLIENT ){
00303 if( !((*fFlags) & REPORT_F_FRST) ){
00304 WriteClientText("HTTP/1.0 200 OK\nContent-Type: text/html\n\n"
00305 "<HTML><HEAD>\n"
00306 "<title>Error page, syntax error</title>\n"
00307 "</HEAD><BODY>\n"
00308 "<H1>Error has happened in the code</H1>"
00309 "<pre>\n");
00310 }
00311 if( szErrorString && strlen(szErrorString) > 80 )szErrorString[79] = (char)0;
00312 if( FileName ){
00313 sprintf(buf,"%s(%ld):",FileName,LineNumber);
00314 WriteClientText(buf);
00315 }
00316 sprintf(buf,(iErrorCode < MAX_ERROR_CODE ? " error &H%x:" : " error 0x%08x:"),iErrorCode);
00317 WriteClientText(buf);
00318 if( iErrorCode >= MAX_ERROR_CODE )iErrorCode = COMMAND_ERROR_EXTENSION_SPECIFIC;
00319 if( szErrorString ){
00320 sprintf(buf,en_error_messages[iErrorCode],szErrorString);
00321 WriteClientText(buf);
00322 WriteClientText("\n");
00323 }else{
00324 sprintf(buf,"%s\n",en_error_messages[iErrorCode]);
00325 WriteClientText(buf);
00326 }
00327 }
00328 if( pWD->bErrMsgDest & ERRMSGERRLOG ){
00329 if( szErrorString && strlen(szErrorString) > 80 )szErrorString[79] = (char)0;
00330 s = buf;
00331 if( FileName ){
00332 sprintf(s,"%s(%ld):",FileName,LineNumber);
00333 s += strlen(s);
00334 }
00335 sprintf(s,(iErrorCode < MAX_ERROR_CODE ? " error &H%x:" : " error 0x%08x:"),iErrorCode);
00336 s += strlen(s);
00337 if( szErrorString ){
00338 sprintf(s,en_error_messages[iErrorCode],szErrorString);
00339 }else{
00340 sprintf(s,"%s",en_error_messages[iErrorCode]);
00341 }
00342 s = buf;
00343 while( *s ){
00344 if( *s == '\n' )*s = ' ';
00345 s++;
00346 }
00347 log_printf(&(pWD->ErrLog),"%s",buf);
00348 }
00349
00350 *fFlags |= REPORT_F_FRST;
00351 }
00352
00353 static void ftp_report(void *pEmbedPointer,
00354 char *FileName,
00355 long LineNumber,
00356 unsigned int iErrorCode,
00357 int iErrorSeverity,
00358 int *piErrorCounter,
00359 char *szErrorString,
00360 unsigned long *fFlags
00361 ){
00362 pThreadData pT = pEmbedPointer;
00363 pHttpdThread pHT = pT->pThreadLocalData;
00364 pWebData pWD = pHT->AppData;
00365 char buf[256],*s;
00366
00367 if( iErrorSeverity >= REPORT_ERROR && piErrorCounter )(*piErrorCounter)++;
00368
00369 if( pWD->bErrMsgDest & ERRMSGCLIENT ){
00370 if( !((*fFlags) & REPORT_F_FRST) ){
00371 WriteClientText("421 Service not available, closing control connection.\r\n");
00372 }
00373 }
00374
00375 if( pWD->bErrMsgDest & ERRMSGERRLOG ){
00376 if( szErrorString && strlen(szErrorString) > 80 )szErrorString[79] = (char)0;
00377 s = buf;
00378 if( FileName ){
00379 sprintf(s,"%s(%ld):",FileName,LineNumber);
00380 s += strlen(s);
00381 }
00382 sprintf(s,(iErrorCode < MAX_ERROR_CODE ? " error &H%x:" : " error 0x%08x:"),iErrorCode);
00383 s += strlen(s);
00384 if( szErrorString ){
00385 sprintf(s,en_error_messages[iErrorCode],szErrorString);
00386 }else{
00387 sprintf(s,"%s",en_error_messages[iErrorCode]);
00388 }
00389 s = buf;
00390 while( *s ){
00391 if( *s == '\n' )*s = ' ';
00392 s++;
00393 }
00394 log_printf(&(pWD->ErrLog),"%s",buf);
00395 }
00396
00397 *fFlags |= REPORT_F_FRST;
00398 }
00399
00400 #define CONFIG(X) cft_GetString(pWD->pProgramConfig->pCONF,(X))
00401
00402 int AppInit(int argc,char *argv[],pHttpdThread pHT,void **AppData){
00403 pWebData pWD;
00404 long myV,i;
00405 CFT_NODE ClientRootNode,ServerRootNode,ServerStartNode,Node;
00406 char *s;
00407 void *pM_Log;
00408 FILE *fpanic;
00409 int iError;
00410
00411 iError = 0;
00412
00413
00414
00415
00416 pWD = malloc(sizeof(WebData));
00417 if( pWD == NULL )return 1;
00418
00419 pWD->pHT = pHT;
00420
00421 *AppData = pWD;
00422
00423
00424 pWD->XForwarded = 0;
00425 pWD->nolog = 0;
00426
00427
00428 pWD->pProgramConfig = scriba_new(malloc,free);
00429 if( pWD->pProgramConfig == NULL ) return 2;
00430
00431 if( scriba_LoadConfiguration(pWD->pProgramConfig,NULL) ){
00432 fprintf(stderr,"Can not initialize the configuration management system.\n");
00433 fprintf(stderr,"The expected configuration file \"%s\" can not be read.\n",pWD->pProgramConfig->pCONF->pszConfigFileName);
00434 fpanic = fopen("panic.txt","w");
00435 if( fpanic ){
00436 fprintf(fpanic,"Can not initialize the configuration management system.\n");
00437 fprintf(fpanic,"The expected configuration file \"%s\" can not be read.\n",pWD->pProgramConfig->pCONF->pszConfigFileName);
00438 fclose(fpanic);
00439 }
00440 return 1;
00441 }
00442
00443 scriba_InitModuleInterface(pWD->pProgramConfig);
00444
00445
00446 for( i= 1 ; i < MAX_SERVERS ; i++ ){
00447 pHT->server[i].ip = HTTPD_IP;
00448 pHT->server[i].port = 0;
00449 pHT->server[i].type = SERVER_NONE;
00450 }
00451
00452
00453 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,"servers.nolog",NULL,NULL,&myV,NULL,NULL) )
00454 pWD->nolog = myV;
00455
00456 pWD->bErrMsgDest = 2;
00457 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,"servers.errmsgdest",NULL,NULL,&myV,NULL,NULL) )
00458 pWD->bErrMsgDest = myV;
00459
00460 if( pWD->nolog ){
00461 log_init(&(pWD->PanicLog),NULL,NULL,NULL,NULL,LOGTYPE_SYNCHRONOUS);
00462 log_init(&(pWD->AppLog),NULL,NULL,NULL,NULL,LOGTYPE_SYNCHRONOUS);
00463 }else{
00464
00465
00466
00467
00468 pM_Log = alloc_InitSegment(malloc,free);
00469 if( pM_Log == NULL ){
00470 fprintf(stderr,"Low memory allocating segment for panic logging.\n");
00471 fpanic = fopen("panic.txt","w");
00472 if( fpanic ){
00473 fprintf(fpanic,"Low memory allocating segment for panic logging.\n");
00474 fclose(fpanic);
00475 }
00476 return 1;
00477 }
00478
00479 if( (s = CONFIG("servers.log.panic.file")) == NULL ||
00480 log_init(&(pWD->PanicLog),
00481 alloc_Alloc,
00482 alloc_Free,
00483 pM_Log,
00484 s,
00485 LOGTYPE_SYNCHRONOUS) ){
00486 fprintf(stderr,"Can not open panic log \"%s\".\n",s);
00487 fpanic = fopen("panic.txt","w");
00488 if( fpanic ){
00489 fprintf(fpanic,"Can not open panic log \"%s\".\n",s);
00490 fclose(fpanic);
00491 }
00492 return 1;
00493 }
00494
00495
00496
00497 if( (s = CONFIG("servers.log.app.file")) == NULL ||
00498 log_init(&(pWD->AppLog),
00499 alloc_Alloc,
00500 alloc_Free,
00501 pM_Log,
00502 s,
00503 LOGTYPE_SYNCHRONOUS) ){
00504 log_printf(&(pWD->PanicLog),
00505 "Can not open the application log >>%s<<",
00506 CONFIG("servers.log.app.file"));
00507 iError = 1;
00508 }
00509
00510 log_printf(&(pWD->AppLog),"Eszter SB Application Engine start up initiated.");
00511 }
00512
00513 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,"servers.port",NULL,NULL,&myV,NULL,NULL) )
00514 pHT->server[0].port = (port_t)myV;
00515
00516
00517 if( s = CONFIG("servers.ip") )
00518 pHT->server[0].ip = inet_addr(s);
00519
00520 sprintf(pWD->szPort,"%d",pHT->server[0].port);
00521 log_printf(&(pWD->AppLog),"Listening on port %d",pHT->server[0].port);
00522
00523 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,"servers.threads",NULL,NULL,&myV,NULL,NULL) )
00524 pHT->threadmax = myV;
00525 log_printf(&(pWD->AppLog),"Maximum number of serving threads: %d",pHT->threadmax);
00526
00527 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,"servers.proxyip",NULL,NULL,&myV,NULL,NULL) )
00528 pWD->XForwarded = myV;
00529 log_printf(&(pWD->AppLog), pWD->XForwarded
00530 ? "Using Apache X-Forwarded-For header to determine client IP"
00531 : "Using TCP/IP reported IP to determine client IP" );
00532
00533 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,"servers.listenbacklog",NULL,NULL,&myV,NULL,NULL) )
00534 pHT->listenmax = myV;
00535 log_printf(&(pWD->AppLog),"Listen backlog is %d",pHT->listenmax);
00536
00537 pWD->pszHome = CONFIG("servers.home");
00538 if( pWD->pszHome == NULL )pWD->pszHome = "./";
00539 log_printf(&(pWD->AppLog),"http home directory is %s",pWD->pszHome);
00540
00541 pWD->code404 = CONFIG("servers.code404");
00542 if( pWD->code404 )
00543 log_printf(&(pWD->AppLog),"Page not found error code is %s",pWD->code404);
00544
00545 pWD->msg404 = CONFIG("servers.msg404");
00546 log_printf(&(pWD->AppLog), pWD->msg404
00547 ? "404 error page text is defined."
00548 : "404 error page text is default.");
00549
00550 pWD->run404 = CONFIG("servers.run404");
00551 if( pWD->run404 && strlen(pWD->run404) > FULL_PATH_BUFFER_LENGTH ){
00552 log_printf(&(pWD->PanicLog),"run404 file name is too long, ignored.");
00553 pWD->run404 = NULL;
00554 }
00555 log_printf(&(pWD->AppLog), pWD->run404
00556 ? "404 error program is %s"
00557 : "no 404 error program defined",pWD->run404);
00558
00559 pHT->lWaitSec = 10;
00560 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,"servers.pid.wait.period",NULL,NULL,&myV,NULL,NULL) )
00561 pHT->lWaitSec = myV;
00562
00563 pHT->lWaitCount = 2;
00564 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,"servers.pid.wait.length",NULL,NULL,&myV,NULL,NULL) )
00565 pHT->lWaitCount = myV;
00566
00567
00568 ServerRootNode = cft_FindNode(pWD->pProgramConfig->pCONF,CFT_ROOT_NODE,"servers");
00569 ServerRootNode = cft_EnumFirst(pWD->pProgramConfig->pCONF,ServerRootNode);
00570 pHT->c_servers = 0;
00571 for( ; ServerRootNode ; ServerRootNode = cft_EnumNext(pWD->pProgramConfig->pCONF,ServerRootNode) ){
00572 s = cft_GetKey(pWD->pProgramConfig->pCONF,ServerRootNode);
00573 if( ! strcmp(s,"server") )
00574 pHT->c_servers++;
00575 }
00576 if( pHT->c_servers >= MAX_SERVERS ){
00577 log_printf(&(pWD->ErrLog),"There are %d servers configured. Max %d are allowed.",pHT->c_servers,MAX_SERVERS);
00578 return 1;
00579 }
00580 log_printf(&(pWD->AppLog),"There are %d server(s) configured",pHT->c_servers);
00581 ServerRootNode = cft_FindNode(pWD->pProgramConfig->pCONF,CFT_ROOT_NODE,"servers");
00582 ServerRootNode = cft_EnumFirst(pWD->pProgramConfig->pCONF,ServerRootNode);
00583 i = 0;
00584 for( ; ServerRootNode ; ServerRootNode = cft_EnumNext(pWD->pProgramConfig->pCONF,ServerRootNode) ){
00585 s = cft_GetKey(pWD->pProgramConfig->pCONF,ServerRootNode);
00586 if( ! strcmp(s,"server") ){
00587
00588 ServerStartNode = cft_EnumFirst(pWD->pProgramConfig->pCONF,ServerRootNode);
00589
00590 Node = cft_FindNode(pWD->pProgramConfig->pCONF,ServerStartNode,"port");
00591 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,NULL,&Node,NULL,&myV,NULL,NULL) )
00592 pHT->server[i].port = (port_t)myV;
00593
00594 Node = cft_FindNode(pWD->pProgramConfig->pCONF,ServerStartNode,"ip");
00595 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,NULL,&Node,&s,NULL,NULL,NULL) )
00596 pHT->server[i].ip = inet_addr(s);
00597
00598 Node = cft_FindNode(pWD->pProgramConfig->pCONF,ServerStartNode,"protocol");
00599 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,NULL,&Node,&s,NULL,NULL,NULL) ){
00600 if( ! stricmp(s,"http") )
00601 pHT->server[i].type = SERVER_HTTP;
00602 if( ! stricmp(s,"ftp") )
00603 pHT->server[i].type = SERVER_FTP;
00604 }else
00605 pHT->server[i].type = SERVER_HTTP;
00606
00607 Node = cft_FindNode(pWD->pProgramConfig->pCONF,ServerStartNode,"salute");
00608 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,NULL,&Node,&s,NULL,NULL,NULL) )
00609 pHT->server[i].salute = s;
00610 else
00611 pHT->server[i].salute = "220 Eszter SB application Engine";
00612
00613 Node = cft_FindNode(pWD->pProgramConfig->pCONF,ServerStartNode,"codebase");
00614 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,NULL,&Node,&s,NULL,NULL,NULL) )
00615 pHT->server[i].codebase = s;
00616 else
00617 pHT->server[i].codebase = NULL;
00618
00619 #define GET_FTP_PARAMETER(X) Node = cft_FindNode(pWD->pProgramConfig->pCONF,ServerStartNode,"programs." #X);\
00620 if( ! cft_GetEx(pWD->pProgramConfig->pCONF,NULL,&Node,&s,NULL,NULL,NULL) ){\
00621 pHT->server[i].X = s;\
00622 }else pHT->server[i].X = NULL;
00623 if( SERVER_FTP == pHT->server[i].type ){
00624 GET_FTP_PARAMETER(USER)
00625 GET_FTP_PARAMETER(PASS)
00626 GET_FTP_PARAMETER(ACCT)
00627 GET_FTP_PARAMETER(CWD)
00628 GET_FTP_PARAMETER(CDUP)
00629 GET_FTP_PARAMETER(SMNT)
00630 GET_FTP_PARAMETER(REIN)
00631 GET_FTP_PARAMETER(QUIT)
00632 GET_FTP_PARAMETER(PORT)
00633 GET_FTP_PARAMETER(PASV)
00634 GET_FTP_PARAMETER(TYPE)
00635 GET_FTP_PARAMETER(STRU)
00636 GET_FTP_PARAMETER(MODE)
00637 GET_FTP_PARAMETER(RETR)
00638 GET_FTP_PARAMETER(STOR)
00639 GET_FTP_PARAMETER(STOU)
00640 GET_FTP_PARAMETER(APPE)
00641 GET_FTP_PARAMETER(ALLO)
00642 GET_FTP_PARAMETER(REST)
00643 GET_FTP_PARAMETER(RNFR)
00644 GET_FTP_PARAMETER(RNTO)
00645 GET_FTP_PARAMETER(ABOR)
00646 GET_FTP_PARAMETER(DELE)
00647 GET_FTP_PARAMETER(MKD)
00648 GET_FTP_PARAMETER(PWD)
00649 GET_FTP_PARAMETER(LIST)
00650 GET_FTP_PARAMETER(NLST)
00651 GET_FTP_PARAMETER(SITE)
00652 GET_FTP_PARAMETER(SYST)
00653 GET_FTP_PARAMETER(STAT)
00654 GET_FTP_PARAMETER(HELP)
00655 GET_FTP_PARAMETER(NOOP)
00656
00657 }
00658
00659 ClientRootNode = cft_FindNode(pWD->pProgramConfig->pCONF,cft_EnumFirst(pWD->pProgramConfig->pCONF,ServerRootNode),"client");
00660 ClientRootNode = cft_EnumFirst(pWD->pProgramConfig->pCONF,ClientRootNode);
00661 pHT->server[i].cAllowed = 0;
00662 pHT->server[i].cDenied = 0;
00663 for( ; ClientRootNode ; ClientRootNode = cft_EnumNext(pWD->pProgramConfig->pCONF,ClientRootNode) ){
00664 s = cft_GetKey(pWD->pProgramConfig->pCONF,ClientRootNode);
00665 if( ! strcmp(s,"allowed") )
00666 pHT->server[i].cAllowed++;
00667 else
00668 if( ! strcmp(s,"denied") )
00669 pHT->server[i].cDenied++;
00670 }
00671
00672 log_printf(&(pWD->AppLog),
00673 "Allowed %d Denied %d IP/MASK pairs configured for server %d",
00674 pHT->server[i].cAllowed,pHT->server[i].cDenied,i+1);
00675
00676 if( pHT->server[i].cAllowed ){
00677 pHT->server[i].plAllowedIP = (unsigned long *)alloc_Alloc(pHT->server[i].cAllowed * sizeof(unsigned long),pWD->pProgramConfig->pMEM);
00678 if( pHT->server[i].plAllowedIP == NULL ){
00679 log_printf(&(pWD->PanicLog),"Memory allocation error 0001");
00680 return 1;
00681 }
00682 pHT->server[i].plAllowedMask = (unsigned long *)alloc_Alloc(pHT->server[i].cAllowed * sizeof(unsigned long),pWD->pProgramConfig->pMEM);
00683 if( pHT->server[i].plAllowedMask == NULL ){
00684 log_printf(&(pWD->PanicLog),"Memory allocation error 0002");
00685 return 1;
00686 }
00687 }
00688
00689 if( pHT->server[i].cDenied ){
00690 pHT->server[i].plDeniedIP = (unsigned long *)alloc_Alloc(pHT->server[i].cDenied * sizeof(unsigned long),pWD->pProgramConfig->pMEM);
00691 if( pHT->server[i].plDeniedIP == NULL ){
00692 log_printf(&(pWD->PanicLog),"Memory allocation error 0003");
00693 return 1;
00694 }
00695 pHT->server[i].plDeniedMask = (unsigned long *)alloc_Alloc(pHT->server[i].cDenied * sizeof(unsigned long),pWD->pProgramConfig->pMEM);
00696 if( pHT->server[i].plDeniedMask == NULL ){
00697 log_printf(&(pWD->PanicLog),"Memory allocation error 0004");
00698 return 1;
00699 }
00700 }
00701 pHT->server[i].cAllowed = 0;
00702 pHT->server[i].cDenied = 0;
00703 ClientRootNode = cft_FindNode(pWD->pProgramConfig->pCONF,cft_EnumFirst(pWD->pProgramConfig->pCONF,ServerRootNode),"client");
00704 ClientRootNode = cft_EnumFirst(pWD->pProgramConfig->pCONF,ClientRootNode);
00705 for( ; ClientRootNode ; ClientRootNode = cft_EnumNext(pWD->pProgramConfig->pCONF,ClientRootNode) ){
00706 if( ! strcmp(cft_GetKey(pWD->pProgramConfig->pCONF,ClientRootNode),"allowed") ){
00707 if( cft_GetEx(pWD->pProgramConfig->pCONF,NULL,&ClientRootNode,&s,NULL,NULL,NULL) ){
00708 log_printf(&(pWD->PanicLog),
00709 "cgt_GetEx( ..., %s, ... ) retuned error second time. This is an internal error.");
00710 fprintf(stderr,
00711 "cgt_GetEx( ..., %s, ... ) retuned error second time. This is an internal error.");
00712 return 1;
00713 }
00714 if( maskip(s,pHT->server[i].plAllowedIP+pHT->server[i].cAllowed,pHT->server[i].plAllowedMask+pHT->server[i].cAllowed) ){
00715 log_printf(&(pWD->PanicLog),"Invalid allowed ip/mask syntax: %s",s);
00716 iError = 1;
00717 }
00718 pHT->server[i].cAllowed++;
00719 }else
00720 if( ! strcmp(cft_GetKey(pWD->pProgramConfig->pCONF,ClientRootNode),"denied") ){
00721 if( cft_GetEx(pWD->pProgramConfig->pCONF,NULL,&ClientRootNode,&s,NULL,NULL,NULL) ){
00722 log_printf(&(pWD->PanicLog),
00723 "cgt_GetEx( ..., %s, ... ) retuned error second time. This is an internal error.");
00724 fprintf(stderr,
00725 "cgt_GetEx( ..., %s, ... ) retuned error second time. This is an internal error.");
00726 return 1;
00727 }
00728 if( maskip(s,pHT->server[i].plDeniedIP+pHT->server[i].cDenied,pHT->server[i].plDeniedMask+pHT->server[i].cDenied) ){
00729 log_printf(&(pWD->PanicLog),"Invalid denied ip/mask syntax: %s",s);
00730 iError = 1;
00731 }
00732 pHT->server[i].cDenied++;
00733 }
00734 }
00735 i++;
00736 }
00737 }
00738
00739
00740 ClientRootNode = cft_FindNode(pWD->pProgramConfig->pCONF,CFT_ROOT_NODE,"servers.vdirs");
00741 ClientRootNode = cft_EnumFirst(pWD->pProgramConfig->pCONF,ClientRootNode);
00742 pWD->cVdir = 0;
00743 for( Node = ClientRootNode ; Node ; Node = cft_EnumNext(pWD->pProgramConfig->pCONF,Node) ){
00744 s = cft_GetKey(pWD->pProgramConfig->pCONF,Node);
00745 if( ! strcmp(s,"dir") )
00746 pWD->cVdir++;
00747 }
00748 if( pWD->cVdir ){
00749 pWD->ppszVdir = (char **)alloc_Alloc(pWD->cVdir*sizeof(char *),pWD->pProgramConfig->pMEM);
00750 if( pWD->ppszVdir == NULL ){
00751 log_printf(&(pWD->PanicLog),"Memory allocation error 0005");
00752 return 1;
00753 }
00754 }
00755 else
00756 pWD->ppszVdir = NULL;
00757 if( pWD->cVdir ){
00758 i = 0;
00759 for( Node = ClientRootNode ; Node ; Node = cft_EnumNext(pWD->pProgramConfig->pCONF,Node) ){
00760 s = cft_GetKey(pWD->pProgramConfig->pCONF,Node);
00761 if( ! strcmp(s,"dir") ){
00762 if( cft_GetEx(pWD->pProgramConfig->pCONF,NULL,&Node,&s,NULL,NULL,NULL) ){
00763 log_printf(&(pWD->PanicLog),
00764 "cgt_GetEx( ..., %s, ... ) retuned error second time. This is an internal error.");
00765 fprintf(stderr,
00766 "cgt_GetEx( ..., %s, ... ) retuned error second time. This is an internal error.");
00767 return 1;
00768 }
00769 pWD->ppszVdir[i++] = s;
00770 }
00771 }
00772 }
00773
00774 log_printf(&(pWD->AppLog),"AppInit returns %d",iError);
00775
00776 log_shutdown(&(pWD->AppLog));
00777 return iError;
00778 }
00779
00780 #ifdef WIN32
00781 static void sleep(int x){ Sleep(1000*x); }
00782 #endif
00783
00784
00785
00786
00787
00788
00789
00790
00791 static void GuardThread(void *p){
00792 pHttpdThread pHT;
00793 pWebData pWD;
00794 FILE *fp;
00795 SOCKET Client;
00796 char buf[80];
00797 int i;
00798
00799 pHT = p;
00800 pWD = pHT->AppData;
00801
00802 while(1){
00803 fp = fopen(pWD->pszPid,"r");
00804 if( fp == NULL ){
00805 thread_LockMutex(&(pHT->mxState));
00806 pHT->iState = STATE_SHUT;
00807 thread_UnlockMutex(&(pHT->mxState));
00808
00809
00810
00811 for( i=0 ; i < pHT->c_servers ; i++ ){
00812 struct in_addr sip;
00813 memcpy(&sip,&(pHT->server[i].ip),sizeof(struct in_addr));
00814 sprintf(buf,"%s:%d",inet_ntoa(sip),pHT->server[i].port);
00815 log_printf(&(pWD->AppLog),"Connecting to server %s",buf);
00816 file_tcpconnect(&Client,buf);
00817 }
00818
00819
00820 return;
00821 }
00822 fclose(fp);
00823 sleep(pWD->lWaitLoop);
00824 }
00825 }
00826
00827 struct _RunServiceProgram {
00828 pWebData pWD;
00829 char *pszProgramFileName;
00830 int iRestart;
00831 };
00832
00833 static void ExecuteProgramThread(void *p){
00834 pSbProgram pProgram;
00835 int binarycode;
00836 char szInputFile[FULL_PATH_BUFFER_LENGTH];
00837 int iErrorCode;
00838 struct _RunServiceProgram *pRSP;
00839
00840 pRSP = p;
00841 while( 1 ){
00842 strcpy(szInputFile,pRSP->pszProgramFileName);
00843 pProgram = scriba_new(malloc,free);
00844 if( pProgram == NULL )return;
00845
00846 scriba_SetProcessSbObject(pProgram,pRSP->pWD->pProgramConfig);
00847 scriba_SetEmbedPointer(pProgram,pRSP->pWD);
00848 scriba_SetFileName(pProgram,szInputFile);
00849 binarycode = 0;
00850 if( scriba_UseCacheFile(pProgram) == SCRIBA_ERROR_SUCCESS )binarycode = 1;
00851 if( binarycode || scriba_IsFileBinaryFormat(pProgram) ){
00852 scriba_LoadBinaryProgram(pProgram);
00853 }else{
00854 if( scriba_RunExternalPreprocessor(pProgram,NULL) ){
00855 log_printf(&(pRSP->pWD->ErrLog),"External preprocessor failed for %s",szInputFile);
00856 return;
00857 }
00858 if( scriba_LoadSourceProgram(pProgram) ){
00859 log_printf(&(pRSP->pWD->ErrLog),"Source program loading error %s",szInputFile);
00860 return;
00861 }
00862 scriba_SaveCacheFile(pProgram);
00863 }
00864 log_printf(&(pRSP->pWD->AppLog),"Executing %s",szInputFile);
00865 iErrorCode = scriba_Run(pProgram,NULL);
00866 if( iErrorCode )
00867 log_printf(&(pRSP->pWD->ErrLog),"Program %s terminated with error %d",szInputFile,iErrorCode);
00868 scriba_destroy(pProgram);
00869 if( ! pRSP->iRestart )return;
00870 }
00871 }
00872
00873 static void ExecuteProgram(pWebData pWD,
00874 char *pszProgramFileName,
00875 int iRestart ){
00876 struct _RunServiceProgram *pRSP;
00877 THREADHANDLE T;
00878
00879 pRSP = (struct _RunServiceProgram *)malloc( sizeof(struct _RunServiceProgram) );
00880 if( pRSP == NULL ){
00881 log_printf(&(pRSP->pWD->ErrLog),
00882 "No memory to allocate RSP structure when trying to run %s",pszProgramFileName);
00883 return;
00884 }
00885 pRSP->pszProgramFileName = (char *)malloc(strlen(pszProgramFileName) + 1);
00886 if( pRSP->pszProgramFileName == NULL ){
00887 log_printf(&(pRSP->pWD->ErrLog),
00888 "No memory to allocate pszProgramFileName when trying to run %s",pszProgramFileName);
00889 return;
00890 }
00891 strcpy(pRSP->pszProgramFileName,pszProgramFileName);
00892 pRSP->iRestart = iRestart;
00893 pRSP->pWD = pWD;
00894 thread_CreateThread(&T,ExecuteProgramThread,pRSP);
00895 }
00896
00897 int AppStart(void **AppData){
00898 void *pM_HitLog,*pM_StatLog,*pM_AppLog,*pM_ErrLog;
00899 pWebData pWD;
00900 CFT_NODE ConfNode,Node;
00901 int iError;
00902 FILE *fp;
00903 THREADHANDLE hThread;
00904 char *s;
00905 int iRestart;
00906 #ifndef WIN32
00907 uid_t uid;
00908 struct passwd *pw;
00909 char *pszEffectiveUser;
00910 #endif
00911
00912 iError = 0;
00913 pWD = *AppData;
00914
00915 if( pWD->nolog ){
00916 log_init(&(pWD->HitLog),NULL,NULL,NULL,NULL,LOGTYPE_NORMAL);
00917 log_init(&(pWD->StatLog),NULL,NULL,NULL,NULL,LOGTYPE_NORMAL);
00918 log_init(&(pWD->AppLog),NULL,NULL,NULL,NULL,LOGTYPE_NORMAL);
00919 log_init(&(pWD->ErrLog),NULL,NULL,NULL,NULL,LOGTYPE_NORMAL);
00920 }else{
00921
00922 pM_HitLog = alloc_InitSegment(malloc,free);
00923 if( pM_HitLog == NULL ){
00924 log_printf(&(pWD->PanicLog),"Memory error allocating pM_HitLog");
00925 return 1;
00926 }
00927 pM_StatLog = alloc_InitSegment(malloc,free);
00928 if( pM_StatLog == NULL ){
00929 log_printf(&(pWD->PanicLog),"Memory error allocating pM_StatLog");
00930 return 1;
00931 }
00932 pM_AppLog = alloc_InitSegment(malloc,free);
00933 if( pM_AppLog == NULL ){
00934 log_printf(&(pWD->PanicLog),"Memory error allocating pM_AppLog");
00935 return 1;
00936 }
00937 pM_ErrLog = alloc_InitSegment(malloc,free);
00938 if( pM_ErrLog == NULL ){
00939 log_printf(&(pWD->PanicLog),"Memory error allocating pM_ErrLog");
00940 return 1;
00941 }
00942
00943 #ifndef WIN32
00944 pszEffectiveUser = CONFIG("servers.user");
00945 if( pszEffectiveUser ){
00946 pw = getpwnam(pszEffectiveUser);
00947 if( pw ){
00948 if( setuid(pw->pw_uid) ){
00949 log_printf(&(pWD->PanicLog),"ESBAE configured to run as user (%s/%d). I can not set this uid for some reason.",
00950 pszEffectiveUser,uid);
00951 iError = 1;
00952 }
00953 }else{
00954 log_printf(&(pWD->PanicLog),"ESBAE configured to run as user (%s). This user does not exists on this machine.",pszEffectiveUser);
00955 iError = 1;
00956 }
00957 }
00958 #endif
00959
00960 if( log_init(&(pWD->ErrLog),alloc_Alloc,alloc_Free,pM_ErrLog,CONFIG("servers.log.err.file"),LOGTYPE_NORMAL) ){
00961 log_printf(&(pWD->PanicLog),"Can not initialize error log.");
00962 return 1;
00963 }
00964 if( cft_GetEx(pWD->pProgramConfig->pCONF,"servers.log.err.span",&ConfNode,NULL,&(pWD->ErrLog.TimeSpan),NULL,NULL) )
00965 pWD->ErrLog.TimeSpan = 0;
00966
00967 if( log_init(&(pWD->HitLog),alloc_Alloc,alloc_Free,pM_HitLog,CONFIG("servers.log.hit.file"),LOGTYPE_NORMAL) ){
00968 log_printf(&(pWD->PanicLog),"HitLog (%s) cannot be opened.",CONFIG("servers.log.hit.file"));
00969 return 1;
00970 }
00971 if( cft_GetEx(pWD->pProgramConfig->pCONF,"servers.log.hit.span",&ConfNode,NULL,&(pWD->HitLog.TimeSpan),NULL,NULL) )
00972 pWD->HitLog.TimeSpan = 0;
00973
00974 if( log_init(&(pWD->StatLog),alloc_Alloc,alloc_Free,pM_StatLog,CONFIG("servers.log.stat.file"),LOGTYPE_NORMAL) ){
00975 log_printf(&(pWD->PanicLog),"StatLog (%s) cannot be opened.",CONFIG("servers.log.stat.file"));
00976 return 1;
00977 }
00978 if( cft_GetEx(pWD->pProgramConfig->pCONF,"servers.log.stat.span",&ConfNode,NULL,&(pWD->StatLog.TimeSpan),NULL,NULL) )
00979 pWD->StatLog.TimeSpan = 0;
00980
00981 if( log_init(&(pWD->AppLog),alloc_Alloc,alloc_Free,pM_AppLog,CONFIG("servers.log.app.file"),LOGTYPE_NORMAL) ){
00982 log_printf(&(pWD->PanicLog),"AppLog (%s) cannot be opened.",CONFIG("servers.log.app.file"));
00983 return 1;
00984 }
00985 if( cft_GetEx(pWD->pProgramConfig->pCONF,"servers.log.app.span",&ConfNode,NULL,&(pWD->AppLog.TimeSpan),NULL,NULL) )
00986 pWD->AppLog.TimeSpan = 0;
00987
00988 log_printf(&(pWD->AppLog),"All logs successfully intialized.");
00989 }
00990
00991 pWD->pszPid = CONFIG("servers.pid.file");
00992 fp = NULL;
00993 if( pWD->pszPid )fp = fopen(pWD->pszPid,"w");
00994 if( fp == NULL ){
00995 log_printf(&(pWD->PanicLog),"Pid file (%s) cannot be opened.",pWD->pszPid);
00996 if( ! pWD->nolog )iError = 1;
00997 pWD->pszPid = NULL;
00998 }else{
00999 fprintf(fp,"%d\n",getpid());
01000 fclose(fp);
01001 fp = NULL;
01002 }
01003
01004 thread_InitMutex(&(pWD->pHT->mxState));
01005 pWD->pHT->iState = STATE_NORMAL;
01006
01007 if( cft_GetEx(pWD->pProgramConfig->pCONF,"servers.pid.delay",&ConfNode,NULL,&(pWD->lWaitLoop),NULL,NULL) )
01008 pWD->lWaitLoop = 5;
01009
01010 if( !iError && pWD->pszPid )
01011 thread_CreateThread(&hThread,GuardThread,pWD->pHT);
01012
01013 #ifdef WIN32
01014 pHT_Service = pWD->pHT;
01015 #endif
01016
01017 ConfNode = cft_FindNode(pWD->pProgramConfig->pCONF,CFT_ROOT_NODE,"servers.run");
01018 if( ConfNode )ConfNode = cft_EnumFirst(pWD->pProgramConfig->pCONF,ConfNode);
01019 if( ConfNode ){
01020 for( Node = ConfNode ; Node ; Node = cft_EnumNext(pWD->pProgramConfig->pCONF,Node) ){
01021 s = cft_GetKey(pWD->pProgramConfig->pCONF,Node);
01022 if( ! strcmp(s,"start") )iRestart = 0;
01023 else if( ! strcmp(s,"restart") )iRestart = 1;
01024 else{
01025 log_printf(&(pWD->ErrLog),"Unknow RUN command in the config file %s",s);
01026 continue;
01027 }
01028 cft_GetEx(pWD->pProgramConfig->pCONF,NULL,&Node,&s,NULL,NULL,NULL);
01029 ExecuteProgram(pWD,s,iRestart);
01030 }
01031 }
01032
01033
01034 log_printf(&(pWD->AppLog),"AppStart returns %d",iError);
01035 return iError;
01036 }
01037
01038 static void pfFtpOut(int ch,
01039 void *pE){
01040 pThreadData pT = pE;
01041
01042 ch = (char)ch;
01043
01044 WriteClient(&ch,1);
01045 return;
01046 }
01047 static int pfFtpIn(void *pE){
01048 return EOF;
01049 }
01050
01051 static void pfStdOut(int ch,
01052 void *pE){
01053 pThreadData pT;
01054 pApplicationThreadData pATD;
01055
01056 ch = (char)ch;
01057
01058 pT = pE;
01059 pATD = pT->AppThreadData;
01060 if( ! pATD->FirstHeaderLine ){
01061 WriteClient(&ch,1);
01062 return;
01063 }
01064
01065 if( pATD->cbBuffer == OBLEN ){
01066 WriteClient(pATD->szBuffer,pATD->cbBuffer);
01067 pATD->cbBuffer = 0;
01068 pATD->FirstHeaderLine = 0;
01069 WriteClient(&ch,1);
01070 return;
01071 }
01072
01073 pATD->szBuffer[pATD->cbBuffer++] = ch;
01074
01075 if( ch == '\n' ){
01076 pATD->FirstHeaderLine = 0;
01077 if( pATD->cbBuffer > 7 && ! strncmp(pATD->szBuffer,"Status:",7) ){
01078 WriteClient("HTTP/1.0",8);
01079 WriteClient(pATD->szBuffer+7,pATD->cbBuffer-7);
01080 pATD->cbBuffer = 0;
01081 return;
01082 }else{
01083 WriteClient(pATD->szBuffer,pATD->cbBuffer);
01084 pATD->cbBuffer = 0;
01085 }
01086 }
01087
01088 }
01089
01090 static int pfStdIn(void *pE){
01091 pThreadData pT;
01092 pApplicationThreadData pATD;
01093
01094 pT = pE;
01095 if( pT->cbAvailable ){
01096 pT->cbAvailable--;
01097 return (unsigned int)*(pT->pszData++);
01098 }
01099
01100 pATD = pT->AppThreadData;
01101
01102 if( pATD->cbInBuffer ){
01103 pATD->cbInBuffer--;
01104 return (unsigned int)*pATD->pszInBuffer++;
01105 }
01106
01107
01108 pATD->cbInBuffer = ReadClient(pATD->szInBuffer,INBLEN);
01109 pATD->pszInBuffer = pATD->szInBuffer;
01110 if( pATD->cbInBuffer ){
01111 pATD->cbInBuffer--;
01112 return (unsigned int)*(pATD->pszInBuffer++);
01113 }else return EOF;
01114 }
01115
01116 static char *pfFtpEnv(void *pE, char *pszEVN, long lEVSN){
01117 pThreadData pT;
01118 pApplicationThreadData pATD;
01119 int isLong;
01120 char *pszRet;
01121
01122 pT = pE;
01123 pATD = pT->AppThreadData;
01124
01125 if( isLong = (pszEVN == NULL) )
01126 switch( lEVSN ){
01127 #define X(a,b) case a: pszEVN = b; strcpy(pATD->szEnvBuf,b); strcat(pATD->szEnvBuf,"=");break;
01128 X(0,"FTP_COMMAND")
01129 X(1,"THREAD_INDEX")
01130 default: return NULL;
01131 }
01132 #define envRETURN(X) do{ pszRet=X;\
01133 if( isLong ){\
01134 if( pszRet && strlen(pszRet) < ENVLEN - strlen(pATD->szEnvBuf) -1 )\
01135 strcat(pATD->szEnvBuf,pszRet);\
01136 return pATD->szEnvBuf;\
01137 }else return pszRet;\
01138 }while(0)
01139
01140 if( !strcmp(pszEVN,"FTP_COMMAND") ){
01141 envRETURN( pATD->pszFtpCommand );
01142 }
01143 if( !strcmp(pszEVN,"THREAD_INDEX") ){
01144 envRETURN( pATD->szThreadIndex );
01145 }
01146
01147 return NULL;
01148 }
01149
01150 static char *pfEnv(void *pE, char *pszEVN, long lEVSN){
01151 pThreadData pT;
01152 pApplicationThreadData pATD;
01153 pWebData pWD;
01154 char *s;
01155 int isLong;
01156 char *pszRet;
01157
01158 pT = pE;
01159 pATD = pT->AppThreadData;
01160 pWD = pT->pHT->AppData;
01161
01162 if( isLong = (pszEVN == NULL) )
01163 switch( lEVSN ){
01164 #define X(a,b) case a: pszEVN = b; strcpy(pATD->szEnvBuf,b); strcat(pATD->szEnvBuf,"=");break;
01165 X(0,"HTTP_COOKIE")
01166 X(1,"SERVER_SOFTWARE")
01167 X(2,"SERVER_NAME")
01168 X(3,"GATEWAY_INTERFACE")
01169 X(4,"SERVER_PROTOCOL")
01170 X(5,"SERVER_PORT")
01171 X(6,"REQUEST_METHOD")
01172 X(7,"PATH_INFO")
01173 X(8,"PATH_TRANSLATED")
01174 X(9,"SCRIPT_NAME")
01175 X(10,"QUERY_STRING")
01176 X(11,"REMOTE_HOST")
01177 X(12,"REMOTE_ADDR")
01178 X(13,"AUTH_TYPE")
01179 X(14,"REMOTE_USER")
01180 X(15,"REMOTE_IDENT")
01181 X(16,"CONTENT_TYPE")
01182 X(17,"CONTENT_LENGTH")
01183 X(18,"HTTP_USER_AGENT")
01184 X(19,"HTTP_REFERER")
01185 X(20,"HTTP_PASSWORD")
01186 X(21,"HTTP_AUTHORIZATION")
01187 #undef X
01188 default: return NULL;
01189 }
01190
01191 #define envRETURN(X) do{ pszRet=X;\
01192 if( isLong ){\
01193 if( pszRet && strlen(pszRet) < ENVLEN - strlen(pATD->szEnvBuf) -1 )\
01194 strcat(pATD->szEnvBuf,pszRet);\
01195 return pATD->szEnvBuf;\
01196 }else return pszRet;\
01197 }while(0)
01198
01199 if( !strcmp(pszEVN,"HTTP_COOKIE") ){
01200 envRETURN( GetServerVariable("Cookie") );
01201 }
01202 if( !strcmp(pszEVN,"SERVER_SOFTWARE") ){
01203 envRETURN( "Eszter SB Engine 1.0" );
01204 }
01205 if( !strcmp(pszEVN,"SERVER_NAME") ){
01206 if( isLong )return "SERVER_NAME=";
01207 return NULL;
01208 }
01209 if( !strcmp(pszEVN,"GATEWAY_INTERFACE") ){
01210 envRETURN( "CGI/1.1" );
01211 }
01212 if( !strcmp(pszEVN,"SERVER_PROTOCOL") ){
01213 envRETURN( "HTTP/1.1" );
01214 }
01215 if( !strcmp(pszEVN,"SERVER_PORT") ){
01216
01217 envRETURN( pWD->szPort );
01218 }
01219 if( !strcmp(pszEVN,"REQUEST_METHOD") ){
01220 envRETURN( pT->pszMethod );
01221 }
01222 if( !strcmp(pszEVN,"PATH_INFO") ){
01223 if( isLong )return "PATH_INFO=";
01224 return NULL;
01225 }
01226 if( !strcmp(pszEVN,"PATH_TRANSLATED") ){
01227 envRETURN( pATD->pszPathTranslated );
01228 }
01229 if( !strcmp(pszEVN,"SCRIPT_NAME") ){
01230 envRETURN( ScriptName() );
01231 }
01232 if( !strcmp(pszEVN,"QUERY_STRING") ){
01233 s = pT->pszQueryString;
01234 while( *s && *s != '?' )s++;
01235 if( *s )s++;
01236 envRETURN( s );
01237 }
01238 if( !strcmp(pszEVN,"REMOTE_HOST") ){
01239 envRETURN( pATD->pszClientIP );
01240 }
01241 if( !strcmp(pszEVN,"REMOTE_ADDR") ){
01242 envRETURN( pATD->pszClientIP );
01243 }
01244 if( !strcmp(pszEVN,"AUTH_TYPE") ){
01245 envRETURN( GetServerVariable("Authorization") );
01246 }
01247 if( !strcmp(pszEVN,"REMOTE_USER") ){
01248 envRETURN( pATD->pszRemoteUser );
01249 }
01250 if( !strcmp(pszEVN,"REMOTE_IDENT") ){
01251 if( isLong )return "REMOTE_IDENT=";
01252 return NULL;
01253 }
01254 if( !strcmp(pszEVN,"CONTENT_TYPE") ){
01255 envRETURN( GetServerVariable("Content-Type") );
01256 }
01257 if( !strcmp(pszEVN,"CONTENT_LENGTH") ){
01258 envRETURN( GetServerVariable("Content-Length") );
01259 }
01260 if( !strcmp(pszEVN,"HTTP_USER_AGENT") ){
01261 envRETURN( GetServerVariable("User-Agent") );
01262 }
01263 if( !strcmp(pszEVN,"HTTP_REFERER") ){
01264 envRETURN( GetServerVariable("Referer") );
01265 }
01266 if( !strcmp(pszEVN,"HTTP_PASSWORD") ){
01267 envRETURN( pATD->pszPassword );
01268 }
01269 if( !strcmp(pszEVN,"HTTP_AUTHORIZATION") ){
01270 envRETURN( GetServerVariable("Authorization") );
01271 }
01272
01273 return NULL;
01274 }
01275
01276
01277 static void send404(pHttpdThread pHT,pThreadData pT){
01278 pWebData pWD;
01279
01280 pWD = pHT->AppData;
01281 if( pWD->code404 ){
01282 WriteClientText("HTTP/1.0 ");
01283 WriteClientText(pWD->code404);
01284 WriteClientText("\nContent-Type: text/html\n\n");
01285 }else{
01286 WriteClientText("HTTP/1.0 404 Page not found\nContent-Type: text/html\n\n");
01287 }
01288 if( pWD->msg404 ){
01289 WriteClientText(pWD->msg404);
01290 }else{
01291
01292 WriteClientText(
01293 "<HTML><HEAD><TITLE>Page not found error 404</TITLE></HEAD>"
01294 "<BODY>The requested page is not found on this server.</BODY></HTML>"
01295 );
01296 }
01297
01298 }
01299
01300 int FtpProc(pHttpdThread pHT,pThreadData pT,char *Buffer){
01301 char *s,*r,last_c;
01302 int inpfnlen;
01303 pSbProgram pProgram;
01304 char szInputFile[FULL_PATH_BUFFER_LENGTH];
01305 int binarycode;
01306 pWebData pWD;
01307 pApplicationThreadData pATD;
01308 unsigned long iErrorCode;
01309 FILE *fp;
01310
01311 pWD = pHT->AppData;
01312 if( NULL == pT->AppThreadData ){
01313 pT->AppThreadData = malloc( sizeof(ApplicationThreadData) );
01314 if( NULL == pT->AppThreadData )return 1;
01315 }
01316 pATD = pT->AppThreadData;
01317 pT->pThreadLocalData = pHT;
01318
01319 s = NULL;
01320 #define GET_BAS_P_NAME(X,Y) if( ! strnicmp(Buffer,#X,Y) )s = pHT->server[pT->server_index].X;
01321 GET_BAS_P_NAME(USER,4)
01322 GET_BAS_P_NAME(PASS,4)
01323 GET_BAS_P_NAME(ACCT,4)
01324 GET_BAS_P_NAME(CWD,3)
01325 GET_BAS_P_NAME(CDUP,4)
01326 GET_BAS_P_NAME(SMNT,4)
01327 GET_BAS_P_NAME(REIN,4)
01328 GET_BAS_P_NAME(QUIT,4)
01329 GET_BAS_P_NAME(PORT,4)
01330 GET_BAS_P_NAME(PASV,4)
01331 GET_BAS_P_NAME(TYPE,4)
01332 GET_BAS_P_NAME(STRU,4)
01333 GET_BAS_P_NAME(MODE,4)
01334 GET_BAS_P_NAME(RETR,4)
01335 GET_BAS_P_NAME(STOR,4)
01336 GET_BAS_P_NAME(STOU,4)
01337 GET_BAS_P_NAME(APPE,4)
01338 GET_BAS_P_NAME(ALLO,4)
01339 GET_BAS_P_NAME(REST,4)
01340 GET_BAS_P_NAME(RNFR,4)
01341 GET_BAS_P_NAME(RNTO,4)
01342 GET_BAS_P_NAME(ABOR,4)
01343 GET_BAS_P_NAME(DELE,4)
01344 GET_BAS_P_NAME(MKD,3)
01345 GET_BAS_P_NAME(PWD,3)
01346 GET_BAS_P_NAME(LIST,4)
01347 GET_BAS_P_NAME(NLST,4)
01348 GET_BAS_P_NAME(SITE,4)
01349 GET_BAS_P_NAME(SYST,4)
01350 GET_BAS_P_NAME(STAT,4)
01351 GET_BAS_P_NAME(HELP,4)
01352 GET_BAS_P_NAME(NOOP,4)
01353
01354 if( NULL == s ){
01355
01356
01357
01358
01359
01360 if( NULL == pHT->server[pT->server_index].codebase ){
01361 if( pT->AppThreadData ){ free(pT->AppThreadData);pT->AppThreadData = NULL;}
01362 log_printf(&(pWD->ErrLog),"no code base is defined for server %d and the command \"%s\" is not handled",pT->server_index,Buffer);
01363 return 1;
01364 }
01365 if( strlen(pHT->server[pT->server_index].codebase) >= FULL_PATH_BUFFER_LENGTH ){
01366 if( pT->AppThreadData ){ free(pT->AppThreadData);pT->AppThreadData = NULL;}
01367 log_printf(&(pWD->ErrLog),"code base for server %d is too long, max %d is allowed",pT->server_index,FULL_PATH_BUFFER_LENGTH);
01368 return 1;
01369 }
01370 strcpy(szInputFile,pHT->server[pT->server_index].codebase);
01371 inpfnlen=strlen(szInputFile);
01372 r = szInputFile+inpfnlen;
01373 if( inpfnlen )
01374 last_c = *( r-1 );
01375 else
01376 last_c = (char)0;
01377 if( inpfnlen >= FULL_PATH_BUFFER_LENGTH ){
01378 if( pT->AppThreadData ){ free(pT->AppThreadData);pT->AppThreadData = NULL;}
01379 log_printf(&(pWD->ErrLog),"file name becomes too long server %d, max %d chars are allowed",pT->server_index,FULL_PATH_BUFFER_LENGTH);
01380 return 1;
01381 }
01382 if( '\\' != last_c && '/' != last_c )strcat(szInputFile,"/");
01383 s = Buffer;
01384 while( *s && !isspace(*s) ){
01385 inpfnlen++;
01386 if( inpfnlen >= FULL_PATH_BUFFER_LENGTH-4 ){
01387 if( pT->AppThreadData ){ free(pT->AppThreadData);pT->AppThreadData = NULL;}
01388 log_printf(&(pWD->ErrLog),"file name becomes too long server %d, max %d chars are allowed",pT->server_index,FULL_PATH_BUFFER_LENGTH);
01389 return 1;
01390 }
01391 *r++ = isupper(*s) ? tolower(*s) : *s ;
01392 *r = (char)0;
01393 s++;
01394 }
01395 strcpy(r,".bas");
01396 }else{
01397 if( strlen(s) >= FULL_PATH_BUFFER_LENGTH ){
01398 if( pT->AppThreadData ){ free(pT->AppThreadData);pT->AppThreadData = NULL;}
01399 log_printf(&(pWD->ErrLog),"Configured file name for basic program is too long for server %d, max %d chars are allowed.",pT->server_index,FULL_PATH_BUFFER_LENGTH);
01400 return 1;
01401 }
01402 strcpy(szInputFile,s);
01403 }
01404
01405
01406 if( NULL == (fp = file_fopen(szInputFile,"r")) ){
01407 WriteClientText("500 Syntax error, command unrecognized really.\r\n");
01408 return 0;
01409 }
01410 file_fclose(fp);
01411
01412 pProgram = scriba_new(malloc,free);
01413 if( pProgram == NULL ){
01414 log_printf(&(pWD->ErrLog),"scriba_new returned null");
01415 if( pT->AppThreadData ){ free(pT->AppThreadData);pT->AppThreadData = NULL;}
01416 return 1;
01417 }
01418
01419 scriba_SetProcessSbObject(pProgram,pWD->pProgramConfig);
01420 scriba_SetStdin(pProgram,pfFtpIn);
01421 scriba_SetStdout(pProgram,pfFtpOut);
01422
01423 pATD->pszFtpCommand = Buffer;
01424 sprintf(pATD->szThreadIndex,"%d",pT->ThreadIndex);
01425 scriba_SetEnvironment(pProgram,pfFtpEnv);
01426 scriba_SetEmbedPointer(pProgram,pT);
01427 scriba_SetReportPointer(pProgram,pT);
01428 scriba_SetReportFunction(pProgram,ftp_report);
01429
01430 scriba_SetFileName(pProgram,szInputFile);
01431
01432 binarycode = 0;
01433 if( scriba_UseCacheFile(pProgram) == SCRIBA_ERROR_SUCCESS )binarycode = 1;
01434 if( binarycode || scriba_IsFileBinaryFormat(pProgram) ){
01435 scriba_LoadBinaryProgram(pProgram);
01436 }else{
01437 if( scriba_RunExternalPreprocessor(pProgram,NULL) ){
01438 log_printf(&(pWD->ErrLog),"External preprocessor failed for %s",szInputFile);
01439 if( pT->AppThreadData ){ free(pT->AppThreadData);pT->AppThreadData = NULL;}
01440 return 1;
01441 }
01442
01443 if( scriba_LoadSourceProgram(pProgram) ){
01444 scriba_destroy(pProgram);
01445 if( pT->AppThreadData ){ free(pT->AppThreadData);pT->AppThreadData = NULL;}
01446 log_printf(&(pWD->ErrLog),"There was error loading the program \"%s\"",szInputFile);
01447 return 1;
01448 }
01449 scriba_SaveCacheFile(pProgram);
01450 }
01451 log_printf(&(pWD->HitLog),"Executing %s",szInputFile);
01452 iErrorCode = scriba_Run(pProgram,NULL);
01453 scriba_destroy(pProgram);
01454 if( iErrorCode && pT->AppThreadData ){ free(pT->AppThreadData);pT->AppThreadData = NULL;}
01455 return iErrorCode;
01456 }
01457
01458 void HttpProc(pHttpdThread pHT,pThreadData pT){
01459 char *sn,*s;
01460 pSbProgram pProgram;
01461 char szInputFile[FULL_PATH_BUFFER_LENGTH];
01462 char szOriginalInputFile[FULL_PATH_BUFFER_LENGTH];
01463 char szAuthStringBuffer[FULL_PATH_BUFFER_LENGTH];
01464 char szClientIP[16];
01465 int binarycode;
01466 pWebData pWD;
01467 ApplicationThreadData ATD;
01468 unsigned long i,iErrorCode;
01469 int iErrorCounter;
01470 FILE *fProgramSource;
01471
01472 pWD = pHT->AppData;
01473 pT->AppThreadData = &ATD;
01474 pT->pThreadLocalData = pHT;
01475
01476 if( pWD->XForwarded ){
01477 ATD.pszClientIP = GetServerVariable("X-Forwarded-For");
01478 }else{
01479 sprintf(szClientIP,"%d.%d.%d.%d",pT->ClientIP[0],pT->ClientIP[1],pT->ClientIP[2],pT->ClientIP[3]);
01480 ATD.pszClientIP = szClientIP;
01481 }
01482 ATD.cbBuffer = 0;
01483 ATD.FirstHeaderLine = 1;
01484 ATD.cbInBuffer = 0;
01485
01486
01487
01488
01489 s = GetServerVariable("Authorization");
01490 if( s ){
01491 while( *s && isspace(*s) )s++;
01492 while( *s && ! isspace(*s) )s++;
01493 while( *s && isspace(*s) )s++;
01494 uudecode(s,szAuthStringBuffer,FULL_PATH_BUFFER_LENGTH);
01495 }else *szAuthStringBuffer = (char)0;
01496 ATD.pszRemoteUser = szAuthStringBuffer;
01497 s = szAuthStringBuffer;
01498 while( *s && *s != ':' )s++;
01499 if( *s )*s++ = (char)0;
01500 ATD.pszPassword = s;
01501
01502
01503 sn = ScriptName();
01504
01505 pProgram = scriba_new(malloc,free);
01506 if( pProgram == NULL )return;
01507
01508 scriba_SetProcessSbObject(pProgram,pWD->pProgramConfig);
01509 scriba_SetCgiFlag(pProgram);
01510 scriba_SetStdin(pProgram,pfStdIn);
01511 scriba_SetStdout(pProgram,pfStdOut);
01512 scriba_SetEnvironment(pProgram,pfEnv);
01513 scriba_SetEmbedPointer(pProgram,pT);
01514 scriba_SetReportPointer(pProgram,pT);
01515 scriba_SetReportFunction(pProgram,httpd_report);
01516
01517 s = NULL;
01518 for( i = 0 ; i < pWD->cVdir ; i++ ){
01519 if( s = prefix(pT->pszQueryString,pWD->ppszVdir[i]) )
01520 break;
01521 }
01522
01523 if( s ){
01524 strcpy(szInputFile,s);
01525 strcat(szInputFile,sn);
01526 }else{
01527 strcpy(szInputFile,pWD->pszHome);
01528 s = sn;
01529 if( *s == '/' )s++;
01530 strcat(szInputFile,s);
01531 }
01532
01533 scriba_SetFileName(pProgram,szInputFile);
01534 ATD.pszPathTranslated = szInputFile;
01535 binarycode = 0;
01536 if( scriba_UseCacheFile(pProgram) == SCRIBA_ERROR_SUCCESS )binarycode = 1;
01537 if( binarycode || scriba_IsFileBinaryFormat(pProgram) ){
01538 scriba_LoadBinaryProgram(pProgram);
01539 }else{
01540 if( scriba_RunExternalPreprocessor(pProgram,NULL) ){
01541 log_printf(&(pWD->ErrLog),"External preprocessor failed for %s",szInputFile);
01542 return;
01543 }
01544
01545
01546 if( NULL == (fProgramSource = file_fopen(pProgram->pszFileName,"r")) ){
01547 if( ! (pWD->bErrMsgDest & ERRMSGERRLOG) )
01548 log_printf(&(pWD->ErrLog),"Source program loading error %s",szInputFile);
01549 if( pWD->run404 ){
01550 strcpy(szOriginalInputFile,szInputFile);
01551 strcpy(szInputFile,pWD->run404);
01552 scriba_SetFileName(pProgram,szInputFile);
01553 ATD.pszPathTranslated = szOriginalInputFile;
01554 binarycode = 0;
01555 if( scriba_UseCacheFile(pProgram) == SCRIBA_ERROR_SUCCESS )binarycode = 1;
01556 if( binarycode || scriba_IsFileBinaryFormat(pProgram) ){
01557 scriba_LoadBinaryProgram(pProgram);
01558 }else{
01559 if( scriba_RunExternalPreprocessor(pProgram,NULL) ){
01560 log_printf(&(pWD->ErrLog),"External preprocessor failed for \"%s\"",szInputFile);
01561 scriba_destroy(pProgram);
01562 return;
01563 }
01564 if( scriba_LoadSourceProgram(pProgram) ){
01565 if( ! (pWD->bErrMsgDest & ERRMSGERRLOG) ){
01566 log_printf(&(pWD->ErrLog),"404 program loading error \"%s\"",szInputFile);
01567 send404(pHT,pT);
01568 scriba_destroy(pProgram);
01569 return;
01570 }
01571 }
01572 }
01573 }else{
01574 if( ! (pWD->bErrMsgDest & ERRMSGCLIENT) ){
01575 log_printf(&(pWD->ErrLog),"404 program loading error \"%s\"",szInputFile);
01576 }
01577 send404(pHT,pT);
01578 return;
01579 }
01580 }
01581
01582 if( fProgramSource )file_fclose(fProgramSource);
01583 if( scriba_LoadSourceProgram(pProgram) ){
01584 scriba_destroy(pProgram);
01585 return;
01586 }
01587 scriba_SaveCacheFile(pProgram);
01588 }
01589 log_printf(&(pWD->HitLog),"Executing %s",szInputFile);
01590 iErrorCode = scriba_Run(pProgram,NULL);
01591 if( iErrorCode )
01592 httpd_report(pT,szInputFile,0,iErrorCode,REPORT_ERROR,&iErrorCounter,
01593 pProgram->pEXE->pszModuleError ? pProgram->pEXE->pszModuleError : "program terminated with error",&iErrorCode);
01594 scriba_destroy(pProgram);
01595 }
01596
01597 #if BCC32
01598 char *_pgmptr;
01599 #endif
01600
01601 main(int argc, char *argv[]){
01602 int do_fork, do_safe;
01603 int i;
01604 #ifdef WIN32
01605 SERVICE_TABLE_ENTRY dispatchTable[] ={
01606 { "sbhttpd", (LPSERVICE_MAIN_FUNCTION)service_main },
01607 { NULL, NULL }
01608 };
01609 #else
01610 int cpid;
01611 #endif
01612
01613
01614
01615
01616
01617 CommandFunction[CMD_CHDIR - START_CMD ] = NULL;
01618
01619 #ifdef WIN32
01620
01621 #if BCC32
01622 _pgmptr = argv[0];
01623 #endif
01624 if( argc > 1 && !strcmp(argv[1],"-install")){
01625 CmdInstallService();
01626 return 0;
01627 }
01628
01629 if( argc > 1 && !strcmp(argv[1],"-remove")){
01630 CmdRemoveService();
01631 return 0;
01632 }
01633
01634
01635
01636 if( (argc > 1 && ! strcmp(argv[1],"-start")) || AmIService() )
01637 if( StartServiceCtrlDispatcher(dispatchTable) )return 0;
01638
01639 #endif
01640
01641 scriba_InitStaticModules();
01642
01643 do_fork = argc > 1 && !strcmp(argv[1],"-start");
01644 do_safe = argc > 1 && !strcmp(argv[1],"-safe");
01645 if( do_safe )do_fork = 1;
01646
01647 #ifndef WIN32
01648
01649
01650
01651 if( do_fork ){
01652 if( fork() )exit(0);
01653 }
01654 if( do_safe ){
01655 while( cpid = fork() ){
01656 waitpid( cpid , NULL , WUNTRACED );
01657 }
01658 }
01659 #endif
01660
01661
01662
01663 if( argc > 1 && ( !strcmp(argv[1],"-start") || !strcmp(argv[1],"-safe") ) ){
01664 for( i = 1 ; i < argc - 1 ; i++ )argv[i] = argv[i+1];
01665 argc--;
01666 }
01667
01668 httpd(argc,argv,AppInit,AppStart,HttpProc,FtpProc);
01669 return 0;
01670 }
01671
01672 #ifdef WIN32
01673 VOID ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv){
01674 char *argv[2] = { "sbhttpd","-start" };
01675
01676 if( ReportStatusToSCMgr(SERVICE_RUNNING,NO_ERROR,0) ){
01677 main(2,argv);
01678 }
01679 }
01680 VOID ServiceStop(){
01681 pHttpdThread pHT;
01682 pWebData pWD;
01683 SOCKET Client;
01684 char buf[80];
01685 int i;
01686
01687 pHT = pHT_Service;
01688 pWD = pHT->AppData;
01689
01690 thread_LockMutex(&(pHT->mxState));
01691 pHT->iState = STATE_SHUT;
01692 thread_UnlockMutex(&(pHT->mxState));
01693
01694
01695
01696 log_printf(&(pWD->AppLog),"Shutting down %d servers",pHT->c_servers);
01697 for( i=0 ; i < pHT->c_servers ; i++ ){
01698 struct in_addr sip;
01699 memcpy(&sip,&(pHT->server[i].ip),sizeof(struct in_addr));
01700 sprintf(buf,"%s:%d",inet_ntoa(sip),pHT->server[i].port);
01701 log_printf(&(pWD->AppLog),"Connecting to server %s",buf);
01702 file_tcpconnect(&Client,buf);
01703 }
01704 }
01705 #endif
01706