I am working with a connector for Lasso <http://lassosoft.com> that is a module compiled for Apache to connect it to a middleware like php. The code compiled works fine for apache <= 2.0 on CentOS just fine.
I've run into a situation where it works fine on CentOS 5.5 64bit with 2.2.3 ONLY when run on a real server. When its run in a VMWare VM I get issues where Apache freaks out and spawns TONS of instances until the machine comes to a halt. I was wondering if anyone on this list might have some insight as to what may cause this. Source code follows: _____________________________________ Lasso8ConnectorforApache2.cpp #include "Lasso8ConnectorforApache.h" #include "POSTReader.h" #include "osErrors.h" #ifndef WIN32 #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <syslog.h> #include <ctype.h> #define LP_OPEN_FLAGS (O_RDONLY) #else #include <winsock2.h> #define LP_OPEN_FLAGS (O_RDONLY | O_BINARY) #endif #include <vector> #include <sys/stat.h> #include <http_request.h> #include <http_log.h> #include <apr_strings.h> #if !defined(S_ISDIR) && defined(S_IFDIR) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifndef CRLF #define CRLF "\r\n"; #endif #ifndef INVALID_SOCKET #define INVALID_SOCKET (-1) #endif //static char * kConfFile = "/etc/lasso/lasso8apache.conf"; //static char * kServer = "server"; //static char * kPort = "port"; unsigned int gtime_out = 1000; unsigned short gLassoPort = 14552; struct sockaddr_in gLassoAddr; //static bool gHasInitted = false; //static short gPort = 14552; static char gAddress[128] = "127.0.0.1"; #define DEFAULT_BUFFER (1024*1024) //#define DO_SYSLOG #ifdef WIN32 _declspec(dllexport) #endif void register_hooks(apr_pool_t *p); void register_hooks(apr_pool_t *p) { ap_hook_handler(lasso_handler, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_child_init(child_init_handler,NULL,NULL,APR_HOOK_MIDDLE); } /* * This is the structure that is used to interface with Apache. Not all * parameters will be used. - CJS */ extern "C" { module AP_MODULE_DECLARE_DATA lasso8_module = { STANDARD20_MODULE_STUFF, NULL, /* dir config creater */ NULL, /* dir merger ensure strictness */ NULL, /* server config */ NULL, /* merge server config */ NULL, /* command table */ register_hooks, /* register hooks */ }; } int lasso_handler (request_rec *r) { int sock = INVALID_SOCKET; int res = 0; LPCommandBlock block; char * data = NULL; int reqOpen = 1; unsigned int timeout = 1000; READ_RESULT read = READ_ERROR; apr_off_t contentLen = 0; int return_value = DECLINED; if( strcmp(r->handler,"lasso8-handler") != 0 ) return DECLINED; std::string frak_ihate_apache; LP8POSTReader reader(apr_table_get(r->headers_in, "Content-Type")); if (!get_post(0, r, &reader)) return HTTP_INTERNAL_SERVER_ERROR; sock = open_connection(); if ( sock == INVALID_SOCKET ) { return HTTP_INTERNAL_SERVER_ERROR; } /* start reading command blocks from Lasso */ while ( reqOpen == 1 && (read = read_block(sock, &block, &data, &timeout)) == READ_OK ) { switch( block.fCmd ) { case cmdGetParam: { char * myData = data; int numParams = 0; // scan to see how many params for (unsigned int pos = 0; pos < block.fDataSize;) { ++numParams; pos += sizeof(RequestParamKeyword); int dSize = *(int*)(data+pos); pos += (ntohl(dSize)+sizeof(int)); } block.fCmd = cmdGetParamRep; block.fDataSize = 0; block.fResultCode = 0; struct ptr_size { char * data; int size; }; ptr_size * rec = (ptr_size*)malloc(numParams*sizeof(ptr_size)); for ( int x = 0; x < numParams; ++x ) { RequestParamKeyword word = (RequestParamKeyword)ntohl(*(RequestParamKeyword*)myData); int dLen = ntohl(*(int*)(myData+sizeof(RequestParamKeyword))); char * pData = NULL; int dSize = 0; myData += (sizeof(RequestParamKeyword) + sizeof(int)); if ( word == rpPostKeyword ) { const std::string * str = reader.GetPostArgs(); if ( str != NULL ) { pData = (char*)malloc(str->size()); dSize = str->size(); memcpy(pData, str->c_str(), str->size()); // pData[str->size()] = '\0'; } } else { int res = get_param(r, word, dLen > 0 ? myData : NULL, &pData, &dSize); if ( res < 0 ) block.fResultCode = res; } rec[x].data = pData; rec[x].size = dSize; block.fDataSize += (dSize + sizeof(int)); } /* alloc a buffer for the data portion of the block*/ char * pData = (char*)malloc(block.fDataSize); char * ppData = pData; for ( int i = 0; i < numParams; ++i ) { int mSize = htonl(rec[i].size); memcpy(ppData, &mSize, sizeof(int)); memcpy(ppData+sizeof(int), rec[i].data, rec[i].size); ppData += (sizeof(int) + rec[i].size); free(rec[i].data); } res = send_block(sock, &block, pData); // dispose rec and each pointer within! free(rec); free(pData); } break; case cmdPushData: if (block.fDataSize > 0) { char * cpy = data; // APACHE 2.0 // we now have to determine the HTTP response code that Lasso is wanting to send // and add headers manually... sigh if ( return_value == DECLINED ) { if ( strncasecmp("HTTP/1.", data, 7) == 0 ) // header start { return_value = atoi(data + 9); r->status = return_value; char * final = strstr(cpy, "\r\n\r\n"); final += 2; cpy = strstr(cpy, CRLF); cpy += 2; char * p(NULL); while(cpy != NULL && cpy != final) { p = strstr(cpy, ":"); if ( p == cpy ) { ++cpy; break; } *p = '\0'; ++p; while(isspace(*p)) ++p; char *tmp = strstr(p, CRLF); *tmp = '\0'; if ( strcasecmp(cpy, "Content-type") == 0 ) { ap_set_content_type(r, apr_pstrdup(r->pool, p)); } else { apr_table_add(r->headers_out, cpy, p); } cpy = tmp + 2; } cpy += 2; ap_send_http_header (r); } } if ( block.fDataSize - (cpy-data) > 0 ) { frak_ihate_apache.append(cpy, block.fDataSize - (cpy-data)); // int written = ap_rwrite(cpy, block.fDataSize - (cpy-data), r); // contentLen += written; } } break; case cmdCloseReq: if ( frak_ihate_apache.length() > 0 ) contentLen = ap_rwrite(frak_ihate_apache.data(), frak_ihate_apache.length(), r); reqOpen = 0; #ifdef WIN32 release_connection(sock); sock = INVALID_SOCKET; #endif ap_set_content_length(r, contentLen); ap_finalize_request_protocol(r); break; default: break; } free(data); data = NULL; } if ( read != READ_OK ) // error from the read; close this connection { // check if the browser is still connected (if possible) // if it's not, continue on your merry way // if it is, goto the shit above release_connection(sock, true); sock = INVALID_SOCKET; if (read == READ_TIMEOUT) { static const char * kErrMsg = "LassoConnectorforApache: timed out while waiting for data from LassoService."; ap_rwrite(kErrMsg, strlen(kErrMsg), r); } return HTTP_INTERNAL_SERVER_ERROR; } if ( sock != INVALID_SOCKET ) release_connection(sock, true); return OK; } static void copy_string(const char * in, char ** out, int * size ) { if ( in != NULL ) { *out = (char*)malloc(strlen(in)+1); *size = strlen(in); strcpy(*out, in); } } /* * Workaround for Client_Headers/Full_Request tags under Apache. * Produces concatenated sequence of substrings referenced as elements within * the array. The string will be empty if all substrings are empty or null, * or if there are no elements in the array. - 07.04.2001 - AK */ struct tabletracker { char * data; int maxlen; int curLen; }; int walktable(void * data, const char * key, const char * val) { const char * kDelim = ": "; const char * kEnd = "\r\n"; const int kDelimLen = 2; const int kEndLen = 2; tabletracker * tt = (tabletracker*)data; int keyLen = strlen(key); int valLen = strlen(val); int available = tt->maxlen - tt->curLen; while ( available < keyLen + valLen + kDelimLen + kEndLen ) { char * newP = (char*)malloc(tt->maxlen * 2); memcpy(newP, tt->data, tt->curLen); free(tt->data); tt->data = newP; tt->maxlen *= 2; available = tt->maxlen - tt->curLen; } memcpy(tt->data+tt->curLen, key, keyLen); tt->curLen += keyLen; memcpy(tt->data+tt->curLen, kDelim, kDelimLen); tt->curLen += kDelimLen; memcpy(tt->data+tt->curLen, val, valLen); tt->curLen += valLen; memcpy(tt->data+tt->curLen, kEnd, kEndLen); tt->curLen += kEndLen; return TRUE; } static void concat_headers(const apr_table_t * tab, char ** outData, int * outLen) { tabletracker tt; tt.data = (char*)malloc(1024); tt.maxlen = 1024; tt.curLen = 0; apr_table_do(walktable, &tt, tab, NULL); *outData = tt.data; *outLen = tt.curLen; } int get_param( request_rec * r, RequestParamKeyword word, const char * param, char ** data, int * outLen ) { int good = 1; switch( word ) { case rpPathArgKeyword: copy_string(r->path_info, data, outLen); break; case rpSearchArgKeyword: copy_string(r->args, data, outLen); break; case rpAuthorizationKeyword: { const char * str = apr_table_get(r->headers_in, "Authorization"); if (str) copy_string(str, data, outLen); else copy_string("", data, outLen); } break; case rpUserKeyword: { const char * str = apr_table_get(r->headers_in, "Authorization"); if ( str != NULL && strncasecmp("basic ", str, 6) == 0 ) { /* move past the first space */ while(*str && !isspace(*str)) ++str; if ( *str == ' ' ) { ++str; char * res = ap_pbase64decode(r->pool, str); char * res2 = res; /* terminate at the colon */ while( res && *res && *res != ':' ) ++res; if ( *res == ':' ) *res = '\0'; copy_string(res2, data, outLen); } break; } copy_string("", data, outLen); } break; case rpPasswordKeyword: { const char * str = apr_table_get(r->headers_in, "Authorization"); if ( str != NULL && strncasecmp("basic ", str, 6) == 0 ) { /* move past the first space */ while(*str && !isspace(*str)) ++str; if ( *str == ' ' ) { ++str; char * res = ap_pbase64decode(r->pool, const_cast<char*>(str)); /* use what's after the colon */ while( res && *res && *res != ':' ) ++res; if ( *res == ':' ) ++res; copy_string(res, data, outLen); } break; } copy_string("", data, outLen); } break; case rpFromUser: break; case rpAddressKeyword: copy_string(r->connection->remote_ip, data, outLen); break; case rpMethodKeyword: copy_string(r->method, data, outLen); break; case rpServerName: copy_string(ap_get_server_name(r), data, outLen); break; case rpServerPort: *data = (char*)malloc(20); sprintf(*data, "%d", (int)ap_get_server_port(r)); *outLen = strlen(*data); break; case rpScriptName: copy_string(r->uri, data, outLen); break; case rpContentType: copy_string(apr_table_get(r->headers_in, "Content-Type"), data, outLen); break; case rpContentLength: copy_string(apr_table_get(r->headers_in, "Content-Length"), data, outLen); break; case rpReferrerKeyword: { const char * res = apr_table_get(r->headers_in, "Referer"); if ( res == NULL ) res = apr_table_get(r->headers_in, "Referrer"); copy_string(res, data, outLen); } break; case rpUserAgentKeyword: copy_string(apr_table_get(r->headers_in, "User-Agent"), data, outLen); break; case rpActionKeyword: case rpActionPathKeyword: break; case rpClientIPAddress: copy_string(r->connection->remote_ip, data, outLen); break; case rpFullRequestKeyword: concat_headers( r->headers_in, data, outLen ); break; case rpRealmsKeyword: case rpCurrentRealmKeyword: break; case rpCookiesKeyword: copy_string(apr_table_get(r->headers_in, "Cookie"), data, outLen); break; case rpSessionRootPath: { const char * fn = r->uri;//filename;//uri char * found = strrchr(fn, '/'); if ( found != NULL ) { int num = (found-fn)+1; *data = (char*)malloc(num+1); strncpy(*data, fn, num); *outLen = num; } } break; case rpResolveFilePath: { if (param == NULL) param = "/"; request_rec * subrec = ap_sub_req_lookup_uri(param, r, NULL); bool isDir = false; struct stat st; if ( subrec->filename ) { // Apache 2 Only // if param ends with a slash and uri does not end with a slash // filename needs to get truncated to the last slash part bool doTrunc = param[strlen(param)-1] == '/' && subrec->uri[strlen(subrec->uri)-1] != '/'; *data = (char*)malloc( strlen(subrec->filename) + 2 + (subrec->path_info ? strlen(subrec->path_info) : 0) ); strcpy(*data, subrec->filename); if ( subrec->path_info ) strcat(*data, subrec->path_info); if (doTrunc) { int last = strlen(*data)-1; while(last > 0 && (*data)[last] != '/') --last; if (last >= 0) (*data)[last+1] = '\0'; } if ( (*data)[strlen(*data)-1] != '/' ) { isDir = ::stat(*data, &st) == 0 ? S_ISDIR(st.st_mode) : false; if ( !isDir ) isDir = param[strlen(param)-1] == '/'; if ( isDir ) strcat(*data, "/"); } *outLen = strlen(*data); } ap_destroy_sub_req(subrec); } break; case rpWebFileData: if ( param != NULL ) { char path[1024] = ""; if ( param[0] != '/' ) // relative from session root { const char * fn = r->filename; char * found = strrchr(fn, '/'); if ( found != NULL ) { strncat(path, fn, (found-fn)+1); } strcat(path, param); } else { request_rec * subrec = ap_sub_req_lookup_uri(param, r, NULL); strcat(path, subrec->filename); ap_destroy_sub_req(subrec); } int f = open(path, LP_OPEN_FLAGS, 0); if ( f != -1 ) { struct stat st; ::stat(path, &st); int filelen = st.st_size; *data = (char*)malloc(filelen+1); int res = read(f, *data, filelen); if ( res > -1 ) { (*data)[res] = '\0'; *outLen = filelen; } else { (*data)[0] = '\0'; *outLen = 0; } close(f); } else { good = osErrFileNotFound; } } break; case rpIndexFile: default: break; } // if ( *data == NULL ) // { // *data = (char*)malloc(1); // (*data)[0] = '\0'; // *outLen = 1; // } return good; } int get_post( int sock, request_rec * r, LP8POSTReader * reader ) { int toRead = 0; if ( ap_setup_client_block(r, REQUEST_CHUNKED_ERROR) == OK ) { if ( ap_should_client_block(r) == 1) { char * buffer = new char[(unsigned int)(DEFAULT_BUFFER+1)]; int readLen = 0; toRead = (int)r->remaining; int readSize = (int)DEFAULT_BUFFER; while ( (readLen = ap_get_client_block(r, buffer, readSize)) > 0 ) { buffer[readLen] = '\0'; reader->AddToBuffer(buffer, readLen); toRead -= readLen; readSize = toRead < DEFAULT_BUFFER ? toRead : DEFAULT_BUFFER; } delete [] buffer; } } return toRead == 0 ? 1 : 0; } void init_module(server_rec*, apr_pool_t*) { } #ifdef WIN32 #define ENTER_CS() EnterCriticalSection(&gSocketCacheLock) #define EXIT_CS() LeaveCriticalSection(&gSocketCacheLock) #else #define ENTER_CS() pthread_mutex_lock(&gSocketCacheLock) #define EXIT_CS() pthread_mutex_unlock(&gSocketCacheLock) #endif int open_connection() { int s = INVALID_SOCKET; /* open a socket and connect need to add support for resolving hostnames */ if( (s = socket(AF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET ) { if( connect(s, (struct sockaddr*)&gLassoAddr, sizeof(struct sockaddr_in)) == 0 ) { return s; } release_connection(s, true); } s = INVALID_SOCKET; return s; } void release_connection( int sock, bool justKillIt ) { if ( sock != INVALID_SOCKET ) // just close it { #ifdef WIN32 shutdown(sock, SD_BOTH); closesocket(sock); #else close(sock); #endif } } void child_term_handler(server_rec*s, apr_pool_t*p) { } void child_init_handler(apr_pool_t *pchild, server_rec *s) { gLassoAddr.sin_family = AF_INET; gLassoAddr.sin_port = htons(gLassoPort); gLassoAddr.sin_addr.s_addr = inet_addr( gAddress ); gLassoAddr.sin_zero[0] = gLassoAddr.sin_zero[1] = gLassoAddr.sin_zero[2] = gLassoAddr.sin_zero[3] = 0; } ___________________________ file: Lasso8ConnectorforApache2.h #include "Lasso8ConnectorforApache.h" #include "POSTReader.h" #include "osErrors.h" #ifndef WIN32 #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #include <syslog.h> #include <ctype.h> #define LP_OPEN_FLAGS (O_RDONLY) #else #include <winsock2.h> #define LP_OPEN_FLAGS (O_RDONLY | O_BINARY) #endif #include <vector> #include <sys/stat.h> #include <http_request.h> #include <http_log.h> #include <apr_strings.h> #if !defined(S_ISDIR) && defined(S_IFDIR) #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifndef CRLF #define CRLF "\r\n"; #endif #ifndef INVALID_SOCKET #define INVALID_SOCKET (-1) #endif //static char * kConfFile = "/etc/lasso/lasso8apache.conf"; //static char * kServer = "server"; //static char * kPort = "port"; unsigned int gtime_out = 1000; unsigned short gLassoPort = 14552; struct sockaddr_in gLassoAddr; //static bool gHasInitted = false; //static short gPort = 14552; static char gAddress[128] = "127.0.0.1"; #define DEFAULT_BUFFER (1024*1024) //#define DO_SYSLOG #ifdef WIN32 _declspec(dllexport) #endif void register_hooks(apr_pool_t *p); void register_hooks(apr_pool_t *p) { ap_hook_handler(lasso_handler, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_child_init(child_init_handler,NULL,NULL,APR_HOOK_MIDDLE); } /* * This is the structure that is used to interface with Apache. Not all * parameters will be used. - CJS */ extern "C" { module AP_MODULE_DECLARE_DATA lasso8_module = { STANDARD20_MODULE_STUFF, NULL, /* dir config creater */ NULL, /* dir merger ensure strictness */ NULL, /* server config */ NULL, /* merge server config */ NULL, /* command table */ register_hooks, /* register hooks */ }; } int lasso_handler (request_rec *r) { int sock = INVALID_SOCKET; int res = 0; LPCommandBlock block; char * data = NULL; int reqOpen = 1; unsigned int timeout = 1000; READ_RESULT read = READ_ERROR; apr_off_t contentLen = 0; int return_value = DECLINED; if( strcmp(r->handler,"lasso8-handler") != 0 ) return DECLINED; std::string frak_ihate_apache; LP8POSTReader reader(apr_table_get(r->headers_in, "Content-Type")); if (!get_post(0, r, &reader)) return HTTP_INTERNAL_SERVER_ERROR; sock = open_connection(); if ( sock == INVALID_SOCKET ) { return HTTP_INTERNAL_SERVER_ERROR; } /* start reading command blocks from Lasso */ while ( reqOpen == 1 && (read = read_block(sock, &block, &data, &timeout)) == READ_OK ) { switch( block.fCmd ) { case cmdGetParam: { char * myData = data; int numParams = 0; // scan to see how many params for (unsigned int pos = 0; pos < block.fDataSize;) { ++numParams; pos += sizeof(RequestParamKeyword); int dSize = *(int*)(data+pos); pos += (ntohl(dSize)+sizeof(int)); } block.fCmd = cmdGetParamRep; block.fDataSize = 0; block.fResultCode = 0; struct ptr_size { char * data; int size; }; ptr_size * rec = (ptr_size*)malloc(numParams*sizeof(ptr_size)); for ( int x = 0; x < numParams; ++x ) { RequestParamKeyword word = (RequestParamKeyword)ntohl(*(RequestParamKeyword*)myData); int dLen = ntohl(*(int*)(myData+sizeof(RequestParamKeyword))); char * pData = NULL; int dSize = 0; myData += (sizeof(RequestParamKeyword) + sizeof(int)); if ( word == rpPostKeyword ) { const std::string * str = reader.GetPostArgs(); if ( str != NULL ) { pData = (char*)malloc(str->size()); dSize = str->size(); memcpy(pData, str->c_str(), str->size()); // pData[str->size()] = '\0'; } } else { int res = get_param(r, word, dLen > 0 ? myData : NULL, &pData, &dSize); if ( res < 0 ) block.fResultCode = res; } rec[x].data = pData; rec[x].size = dSize; block.fDataSize += (dSize + sizeof(int)); } /* alloc a buffer for the data portion of the block*/ char * pData = (char*)malloc(block.fDataSize); char * ppData = pData; for ( int i = 0; i < numParams; ++i ) { int mSize = htonl(rec[i].size); memcpy(ppData, &mSize, sizeof(int)); memcpy(ppData+sizeof(int), rec[i].data, rec[i].size); ppData += (sizeof(int) + rec[i].size); free(rec[i].data); } res = send_block(sock, &block, pData); // dispose rec and each pointer within! free(rec); free(pData); } break; case cmdPushData: if (block.fDataSize > 0) { char * cpy = data; // APACHE 2.0 // we now have to determine the HTTP response code that Lasso is wanting to send // and add headers manually... sigh if ( return_value == DECLINED ) { if ( strncasecmp("HTTP/1.", data, 7) == 0 ) // header start { return_value = atoi(data + 9); r->status = return_value; char * final = strstr(cpy, "\r\n\r\n"); final += 2; cpy = strstr(cpy, CRLF); cpy += 2; char * p(NULL); while(cpy != NULL && cpy != final) { p = strstr(cpy, ":"); if ( p == cpy ) { ++cpy; break; } *p = '\0'; ++p; while(isspace(*p)) ++p; char *tmp = strstr(p, CRLF); *tmp = '\0'; if ( strcasecmp(cpy, "Content-type") == 0 ) { ap_set_content_type(r, apr_pstrdup(r->pool, p)); } else { apr_table_add(r->headers_out, cpy, p); } cpy = tmp + 2; } cpy += 2; ap_send_http_header (r); } } if ( block.fDataSize - (cpy-data) > 0 ) { frak_ihate_apache.append(cpy, block.fDataSize - (cpy-data)); // int written = ap_rwrite(cpy, block.fDataSize - (cpy-data), r); // contentLen += written; } } break; case cmdCloseReq: if ( frak_ihate_apache.length() > 0 ) contentLen = ap_rwrite(frak_ihate_apache.data(), frak_ihate_apache.length(), r); reqOpen = 0; #ifdef WIN32 release_connection(sock); sock = INVALID_SOCKET; #endif ap_set_content_length(r, contentLen); ap_finalize_request_protocol(r); break; default: break; } free(data); data = NULL; } if ( read != READ_OK ) // error from the read; close this connection { // check if the browser is still connected (if possible) // if it's not, continue on your merry way // if it is, goto the shit above release_connection(sock, true); sock = INVALID_SOCKET; if (read == READ_TIMEOUT) { static const char * kErrMsg = "LassoConnectorforApache: timed out while waiting for data from LassoService."; ap_rwrite(kErrMsg, strlen(kErrMsg), r); } return HTTP_INTERNAL_SERVER_ERROR; } if ( sock != INVALID_SOCKET ) release_connection(sock, true); return OK; } static void copy_string(const char * in, char ** out, int * size ) { if ( in != NULL ) { *out = (char*)malloc(strlen(in)+1); *size = strlen(in); strcpy(*out, in); } } /* * Workaround for Client_Headers/Full_Request tags under Apache. * Produces concatenated sequence of substrings referenced as elements within * the array. The string will be empty if all substrings are empty or null, * or if there are no elements in the array. - 07.04.2001 - AK */ struct tabletracker { char * data; int maxlen; int curLen; }; int walktable(void * data, const char * key, const char * val) { const char * kDelim = ": "; const char * kEnd = "\r\n"; const int kDelimLen = 2; const int kEndLen = 2; tabletracker * tt = (tabletracker*)data; int keyLen = strlen(key); int valLen = strlen(val); int available = tt->maxlen - tt->curLen; while ( available < keyLen + valLen + kDelimLen + kEndLen ) { char * newP = (char*)malloc(tt->maxlen * 2); memcpy(newP, tt->data, tt->curLen); free(tt->data); tt->data = newP; tt->maxlen *= 2; available = tt->maxlen - tt->curLen; } memcpy(tt->data+tt->curLen, key, keyLen); tt->curLen += keyLen; memcpy(tt->data+tt->curLen, kDelim, kDelimLen); tt->curLen += kDelimLen; memcpy(tt->data+tt->curLen, val, valLen); tt->curLen += valLen; memcpy(tt->data+tt->curLen, kEnd, kEndLen); tt->curLen += kEndLen; return TRUE; } static void concat_headers(const apr_table_t * tab, char ** outData, int * outLen) { tabletracker tt; tt.data = (char*)malloc(1024); tt.maxlen = 1024; tt.curLen = 0; apr_table_do(walktable, &tt, tab, NULL); *outData = tt.data; *outLen = tt.curLen; } int get_param( request_rec * r, RequestParamKeyword word, const char * param, char ** data, int * outLen ) { int good = 1; switch( word ) { case rpPathArgKeyword: copy_string(r->path_info, data, outLen); break; case rpSearchArgKeyword: copy_string(r->args, data, outLen); break; case rpAuthorizationKeyword: { const char * str = apr_table_get(r->headers_in, "Authorization"); if (str) copy_string(str, data, outLen); else copy_string("", data, outLen); } break; case rpUserKeyword: { const char * str = apr_table_get(r->headers_in, "Authorization"); if ( str != NULL && strncasecmp("basic ", str, 6) == 0 ) { /* move past the first space */ while(*str && !isspace(*str)) ++str; if ( *str == ' ' ) { ++str; char * res = ap_pbase64decode(r->pool, str); char * res2 = res; /* terminate at the colon */ while( res && *res && *res != ':' ) ++res; if ( *res == ':' ) *res = '\0'; copy_string(res2, data, outLen); } break; } copy_string("", data, outLen); } break; case rpPasswordKeyword: { const char * str = apr_table_get(r->headers_in, "Authorization"); if ( str != NULL && strncasecmp("basic ", str, 6) == 0 ) { /* move past the first space */ while(*str && !isspace(*str)) ++str; if ( *str == ' ' ) { ++str; char * res = ap_pbase64decode(r->pool, const_cast<char*>(str)); /* use what's after the colon */ while( res && *res && *res != ':' ) ++res; if ( *res == ':' ) ++res; copy_string(res, data, outLen); } break; } copy_string("", data, outLen); } break; case rpFromUser: break; case rpAddressKeyword: copy_string(r->connection->remote_ip, data, outLen); break; case rpMethodKeyword: copy_string(r->method, data, outLen); break; case rpServerName: copy_string(ap_get_server_name(r), data, outLen); break; case rpServerPort: *data = (char*)malloc(20); sprintf(*data, "%d", (int)ap_get_server_port(r)); *outLen = strlen(*data); break; case rpScriptName: copy_string(r->uri, data, outLen); break; case rpContentType: copy_string(apr_table_get(r->headers_in, "Content-Type"), data, outLen); break; case rpContentLength: copy_string(apr_table_get(r->headers_in, "Content-Length"), data, outLen); break; case rpReferrerKeyword: { const char * res = apr_table_get(r->headers_in, "Referer"); if ( res == NULL ) res = apr_table_get(r->headers_in, "Referrer"); copy_string(res, data, outLen); } break; case rpUserAgentKeyword: copy_string(apr_table_get(r->headers_in, "User-Agent"), data, outLen); break; case rpActionKeyword: case rpActionPathKeyword: break; case rpClientIPAddress: copy_string(r->connection->remote_ip, data, outLen); break; case rpFullRequestKeyword: concat_headers( r->headers_in, data, outLen ); break; case rpRealmsKeyword: case rpCurrentRealmKeyword: break; case rpCookiesKeyword: copy_string(apr_table_get(r->headers_in, "Cookie"), data, outLen); break; case rpSessionRootPath: { const char * fn = r->uri;//filename;//uri char * found = strrchr(fn, '/'); if ( found != NULL ) { int num = (found-fn)+1; *data = (char*)malloc(num+1); strncpy(*data, fn, num); *outLen = num; } } break; case rpResolveFilePath: { if (param == NULL) param = "/"; request_rec * subrec = ap_sub_req_lookup_uri(param, r, NULL); bool isDir = false; struct stat st; if ( subrec->filename ) { // Apache 2 Only // if param ends with a slash and uri does not end with a slash // filename needs to get truncated to the last slash part bool doTrunc = param[strlen(param)-1] == '/' && subrec->uri[strlen(subrec->uri)-1] != '/'; *data = (char*)malloc( strlen(subrec->filename) + 2 + (subrec->path_info ? strlen(subrec->path_info) : 0) ); strcpy(*data, subrec->filename); if ( subrec->path_info ) strcat(*data, subrec->path_info); if (doTrunc) { int last = strlen(*data)-1; while(last > 0 && (*data)[last] != '/') --last; if (last >= 0) (*data)[last+1] = '\0'; } if ( (*data)[strlen(*data)-1] != '/' ) { isDir = ::stat(*data, &st) == 0 ? S_ISDIR(st.st_mode) : false; if ( !isDir ) isDir = param[strlen(param)-1] == '/'; if ( isDir ) strcat(*data, "/"); } *outLen = strlen(*data); } ap_destroy_sub_req(subrec); } break; case rpWebFileData: if ( param != NULL ) { char path[1024] = ""; if ( param[0] != '/' ) // relative from session root { const char * fn = r->filename; char * found = strrchr(fn, '/'); if ( found != NULL ) { strncat(path, fn, (found-fn)+1); } strcat(path, param); } else { request_rec * subrec = ap_sub_req_lookup_uri(param, r, NULL); strcat(path, subrec->filename); ap_destroy_sub_req(subrec); } int f = open(path, LP_OPEN_FLAGS, 0); if ( f != -1 ) { struct stat st; ::stat(path, &st); int filelen = st.st_size; *data = (char*)malloc(filelen+1); int res = read(f, *data, filelen); if ( res > -1 ) { (*data)[res] = '\0'; *outLen = filelen; } else { (*data)[0] = '\0'; *outLen = 0; } close(f); } else { good = osErrFileNotFound; } } break; case rpIndexFile: default: break; } // if ( *data == NULL ) // { // *data = (char*)malloc(1); // (*data)[0] = '\0'; // *outLen = 1; // } return good; } int get_post( int sock, request_rec * r, LP8POSTReader * reader ) { int toRead = 0; if ( ap_setup_client_block(r, REQUEST_CHUNKED_ERROR) == OK ) { if ( ap_should_client_block(r) == 1) { char * buffer = new char[(unsigned int)(DEFAULT_BUFFER+1)]; int readLen = 0; toRead = (int)r->remaining; int readSize = (int)DEFAULT_BUFFER; while ( (readLen = ap_get_client_block(r, buffer, readSize)) > 0 ) { buffer[readLen] = '\0'; reader->AddToBuffer(buffer, readLen); toRead -= readLen; readSize = toRead < DEFAULT_BUFFER ? toRead : DEFAULT_BUFFER; } delete [] buffer; } } return toRead == 0 ? 1 : 0; } void init_module(server_rec*, apr_pool_t*) { } #ifdef WIN32 #define ENTER_CS() EnterCriticalSection(&gSocketCacheLock) #define EXIT_CS() LeaveCriticalSection(&gSocketCacheLock) #else #define ENTER_CS() pthread_mutex_lock(&gSocketCacheLock) #define EXIT_CS() pthread_mutex_unlock(&gSocketCacheLock) #endif int open_connection() { int s = INVALID_SOCKET; /* open a socket and connect need to add support for resolving hostnames */ if( (s = socket(AF_INET, SOCK_STREAM, 0)) != INVALID_SOCKET ) { if( connect(s, (struct sockaddr*)&gLassoAddr, sizeof(struct sockaddr_in)) == 0 ) { return s; } release_connection(s, true); } s = INVALID_SOCKET; return s; } void release_connection( int sock, bool justKillIt ) { if ( sock != INVALID_SOCKET ) // just close it { #ifdef WIN32 shutdown(sock, SD_BOTH); closesocket(sock); #else close(sock); #endif } } void child_term_handler(server_rec*s, apr_pool_t*p) { } void child_init_handler(apr_pool_t *pchild, server_rec *s) { gLassoAddr.sin_family = AF_INET; gLassoAddr.sin_port = htons(gLassoPort); gLassoAddr.sin_addr.s_addr = inet_addr( gAddress ); gLassoAddr.sin_zero[0] = gLassoAddr.sin_zero[1] = gLassoAddr.sin_zero[2] = gLassoAddr.sin_zero[3] = 0; } __________________________ Thanks Steffan --------------------------------------------------------------- T E L 6 0 2 . 7 9 3 . 0 0 1 4 | F A X 6 0 2 . 9 7 1 . 1 6 9 4 Steffan A. Cline stef...@execuchoice.net Phoenix, Az http://www.ExecuChoice.net USA AIM : SteffanC ICQ : 57234309 YAHOO : Steffan_Cline MSN : stef...@hldns.com GOOGLE: Steffan.Cline Lasso Partner Alliance Member ---------------------------------------------------------------