httpd-modules-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Steffan A. Cline" <stef...@hldns.com>
Subject Lasso Connector
Date Sun, 31 Oct 2010 21:51:59 GMT
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  
Steffan@ExecuChoice.net                             Phoenix, Az   
http://www.ExecuChoice.net                                  USA  
AIM : SteffanC          ICQ : 57234309   
YAHOO : Steffan_Cline   MSN : steffan@hldns.com  
GOOGLE: Steffan.Cline             Lasso Partner Alliance Member 
--------------------------------------------------------------- 





Mime
View raw message