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
[email protected] Phoenix, Az
http://www.ExecuChoice.net USA
AIM : SteffanC ICQ : 57234309
YAHOO : Steffan_Cline MSN : [email protected]
GOOGLE: Steffan.Cline Lasso Partner Alliance Member
---------------------------------------------------------------