libs-gsweb/GSWAdaptors/Apache/mod_gsweb.c
Manuel Guesdon f9ecb43b28 *** empty log message ***
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@6293 72102866-910b-0410-8b05-ffd578937521
2000-03-16 16:16:49 +00:00

557 lines
17 KiB
C

/* mod_gsweb.c - GSWeb: Apache Module
Copyright (C) 1999 Free Software Foundation, Inc.
Written by: Manuel Guesdon <mguesdon@sbuilders.com>
Date: Jully 1999
This file is part of the GNUstep Web Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/param.h>
#include "config.h"
#include "GSWUtil.h"
#include "GSWDict.h"
#include "GSWString.h"
#include "GSWConfig.h"
#include "GSWURLUtil.h"
#include "GSWHTTPHeaders.h"
#include "GSWAppRequestStruct.h"
#include "GSWAppConnect.h"
#include "GSWHTTPRequest.h"
#include "GSWHTTPResponse.h"
#include "GSWAppRequest.h"
#include "httpd.h"
#include <http_config.h>
#include <http_request.h>
#include <http_core.h>
// Module Definition:
// Declare the module
module GSWeb_Module;
typedef struct _GSWeb_Config
{
const char* pszGSWeb; // default = GSWeb
const char* pszConfigPath; // path to GSWeb.conf
// const char* pszRoot; // normally htdocs/GSWeb
} GSWeb_Config;
//TODO: remove ??
struct table
{
/* This has to be first to promote backwards compatibility with
* older modules which cast a table * to an array_header *...
* they should use the table_elts() function for most of the
* cases they do this for.
*/
array_header a;
#ifdef MAKE_TABLE_PROFILE
void *creator;
#endif
};
//static CONST char* GSWeb_SetDocRoot(cmd_parms* p_pCmdParams,void* p_pUnused,char *p_pszArg);
static CONST char* GSWeb_SetScriptAlias(cmd_parms *p_pCmdParams, void *p_pUnused, char *p_pszArg);
static CONST char *GSWeb_SetConfig(cmd_parms *p_pCmdParams, void *p_pUnused, char *p_pszArg);
static int GSWeb_Handler(request_rec* p_pRequestRec);
//--------------------------------------------------------------------
// Init
static void GSWeb_Init(server_rec* p_pServerRec, pool *p)
{
GSWDict* pDict=GSWDict_New(0);
GSWeb_Config* pConfig=NULL;
pConfig=(GSWeb_Config*)ap_get_module_config(p_pServerRec->module_config,
&GSWeb_Module);
GSWLog_Init(NULL,GSW_INFO);
GSWLog(GSW_INFO,p_pServerRec,"GSWeb Init Start Config" GSWEB_HANDLER);
if (pConfig && pConfig->pszConfigPath)
GSWDict_AddStringDup(pDict,
g_szGSWeb_Conf_ConfigFilePath,
pConfig->pszConfigPath);
/* if (pConfig && pConfig->pszRoot)
GSWDict_AddStringDup(pDict,
g_szGSWeb_Conf_DocRoot,
pConfig->pszRoot);*/
GSWLog(GSW_INFO,p_pServerRec,"GSWeb Init LB Init" GSWEB_HANDLER);
GSWConfig_Init(pDict);
GSWLog(GSW_INFO,p_pServerRec,"GSWeb Init" GSWEB_HANDLER);
GSWDict_Free(pDict);
};
//--------------------------------------------------------------------
// Create Config
static void* GSWeb_CreateConfig(pool* p_pPool,
server_rec* p_pServerRec)
{
GSWeb_Config *pConfig = (GSWeb_Config*)ap_palloc(p_pPool,sizeof(GSWeb_Config));
pConfig->pszGSWeb = g_szGSWeb_Prefix;
pConfig->pszConfigPath = NULL;
// pConfig->pszRoot = NULL;
return pConfig;
};
/*
//--------------------------------------------------------------------
// Set Param: DocRoot
static CONST char* GSWeb_SetDocRoot(cmd_parms* p_pCmdParams,void* p_pUnused,char *p_pszArg)
{
server_rec* pServerRec = p_pCmdParams->server;
GSWeb_Config* pConfig = NULL;
GSWLog(GSW_DEBUG,pServerRec,"Start GSWeb_SetDocRoot");
pConfig=(GSWeb_Config *)ap_get_module_config(pServerRec->module_config,
&GSWeb_Module);
pConfig->pszRoot = p_pszArg;
GSWLog(GSW_DEBUG,pServerRec,"Start GSWeb_SetDocRoot");
return NULL;
};
*/
//--------------------------------------------------------------------
// Set Param: ScriptAlias
static CONST char* GSWeb_SetScriptAlias(cmd_parms *p_pCmdParams, void *p_pUnused, char *p_pszArg)
{
server_rec* pServerRec = p_pCmdParams->server;
GSWeb_Config* pConfig = NULL;
GSWLog(GSW_DEBUG,pServerRec,"Start GSWeb_SetScriptAlias");
pConfig=(GSWeb_Config *)ap_get_module_config(pServerRec->module_config,
&GSWeb_Module);
pConfig->pszGSWeb = p_pszArg;
GSWLog(GSW_DEBUG,pServerRec,"Stop GSWeb_SetScriptAlias");
return NULL;
};
//--------------------------------------------------------------------
// Set Param: ConfigFile
static CONST char *GSWeb_SetConfig(cmd_parms *p_pCmdParams, void *p_pUnused, char *p_pszArg)
{
server_rec* pServerRec = p_pCmdParams->server;
GSWeb_Config* pConfig = NULL;
GSWLog(GSW_DEBUG,pServerRec,"Start GSWeb_SetConfig");
pConfig=(GSWeb_Config *)ap_get_module_config(pServerRec->module_config,
&GSWeb_Module);
pConfig->pszConfigPath = p_pszArg;
GSWLog(GSW_DEBUG,pServerRec,"Stop GSWeb_SetConfig");
return NULL;
};
//--------------------------------------------------------------------
// Translate
int GSWeb_Translation(request_rec* p_pRequestRec)
{
int iRetValue=OK;
GSWeb_Config* pConfig=NULL;
GSWURLComponents stURL;
memset(&stURL,0,sizeof(stURL));
GSWLog(GSW_DEBUG,p_pRequestRec->server,"Start GSWeb_Translation");
pConfig=(GSWeb_Config *)ap_get_module_config(p_pRequestRec->server->module_config,
&GSWeb_Module);
// Is this for us ?
if (strncmp(pConfig->pszGSWeb,
p_pRequestRec->uri,
strlen(pConfig->pszGSWeb))==0)
{
GSWURLError eError=GSWParseURL(&stURL,p_pRequestRec->uri,
p_pRequestRec->server);
if (eError!=GSWURLError_OK)
{
GSWLog(GSW_ERROR,p_pRequestRec->server,"GSWeb_Translation Declined (Error %d)",(int)eError);
iRetValue=DECLINED;
}
else
{
GSWLog(GSW_DEBUG,
p_pRequestRec->server,
"GSWeb_Translation Handler p_pRequestRec->handler=%s pool=%p handler=%s pConfig->pszGSWeb=%s",
p_pRequestRec->handler,
p_pRequestRec->pool,
g_szGSWeb_Handler,
pConfig->pszGSWeb);
p_pRequestRec->handler=(char*)ap_pstrdup(p_pRequestRec->pool,g_szGSWeb_Handler);
iRetValue=OK;
};
}
else
{
GSWLog(GSW_DEBUG,p_pRequestRec->server,"GSWeb_Translation Decliend");
iRetValue=DECLINED;
};
GSWLog(GSW_DEBUG,p_pRequestRec->server,"Stop GSWeb_Translation");
return iRetValue;
};
//--------------------------------------------------------------------
static void copyHeaders(request_rec* p_pRequestRec,GSWHTTPRequest* p_pGSWHTTPRequest)
{
server_rec* pServerRec = p_pRequestRec->server;
conn_rec* pConnection = p_pRequestRec->connection;
table* pHeadersIn = p_pRequestRec->headers_in;
table_entry* pHeader=NULL;
int i;
char szPort[40]="";
CONST char* pszRemoteLogName=NULL;
GSWLog(GSW_DEBUG,pServerRec,"Start copyHeaders");
// copy p_pRequestRec headers
pHeader = (table_entry*)(&pHeadersIn->a)->elts;
for (i=0;i<(&pHeadersIn->a)->nelts;i++)
{
if (pHeader->key)
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,pHeader->key,pHeader->val);
pHeader++;
};
// Add server headers
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_ServerSoftware,
SERVER_VERSION);
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_ServerName,
pServerRec->server_hostname);
ap_snprintf(szPort,
sizeof(szPort),
"%u",
pServerRec->port);
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_ServerPort,
szPort);
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_RemoteHost,
(CONST char*)ap_get_remote_host(pConnection,p_pRequestRec->per_dir_config,REMOTE_NAME));
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_RemoteAddress,
pConnection->remote_ip);
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_DocumentRoot,
(char*)ap_document_root(p_pRequestRec));
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_ServerAdmin,
pServerRec->server_admin);
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_ScriptFileName,
p_pRequestRec->filename);
ap_snprintf(szPort,
sizeof(szPort),
"%d",
ntohs(pConnection->remote_addr.sin_port));
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_RemotePort,
szPort);
if (pConnection->user)
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_RemoteUser,
pConnection->user);
if (pConnection->ap_auth_type)
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_AuthType,//"auth_type",
pConnection->ap_auth_type);
pszRemoteLogName = (char*)ap_get_remote_logname(p_pRequestRec);
if (pszRemoteLogName)
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
g_szServerInfo_RemoteIdent,
pszRemoteLogName);
GSWLog(GSW_DEBUG,pServerRec,"Stop copyHeaders");
};
//--------------------------------------------------------------------
// callback finction to copy an header into p_pRequest
static void getHeader(GSWDictElem* p_pElem,void* p_pRequestRec)
{
request_rec* pRequestRec = (request_rec*)p_pRequestRec;
if (!pRequestRec->content_type && strcasecmp(p_pElem->pszKey,g_szHeader_ContentType)==0)
pRequestRec->content_type = (char*)ap_pstrdup(pRequestRec->pool,(char*)p_pElem->pValue);
else
ap_table_add(pRequestRec->headers_out,p_pElem->pszKey,(char*)p_pElem->pValue);
};
//--------------------------------------------------------------------
// send response
static void sendResponse(request_rec* p_pRequestRec,GSWHTTPResponse* p_pHTTPResponse)
{
char szStatusBuffer[512]="";
server_rec* pServerRec = p_pRequestRec->server;
GSWLog(GSW_DEBUG,pServerRec,"Start sendResponse");
// Process Headers
GSWDict_PerformForAllElem(p_pHTTPResponse->pHeaders,getHeader,p_pRequestRec);
ap_snprintf(szStatusBuffer,sizeof(szStatusBuffer),"%u %s",
p_pHTTPResponse->uStatus,
p_pHTTPResponse->pszStatusMessage);
p_pRequestRec->status_line = szStatusBuffer;
p_pRequestRec->status = p_pHTTPResponse->uStatus;
// Set content type if none
if (!p_pRequestRec->content_type)
p_pRequestRec->content_type = g_szContentType_TextHtml;
// Set content length
ap_set_content_length(p_pRequestRec, p_pHTTPResponse->uContentLength);
// Now Send response...
// send Headers
ap_send_http_header(p_pRequestRec);
// If not headers only
if (!p_pRequestRec->header_only)
{
ap_soft_timeout("Send GSWeb response",p_pRequestRec);
ap_rwrite(p_pHTTPResponse->pContent,p_pHTTPResponse->uContentLength,p_pRequestRec);
ap_kill_timeout(p_pRequestRec);
};
GSWLog(GSW_DEBUG,pServerRec,"Stop sendResponse");
};
//--------------------------------------------------------------------
// die/send response
static int dieSendResponse(request_rec* p_pRequestRec,GSWHTTPResponse** p_ppHTTPResponse,BOOL p_fDecline)
{
server_rec* pServerRec = p_pRequestRec->server;
void* pLogServerData=pServerRec;
GSWLog(GSW_DEBUG,pLogServerData,"Start dieSendResponse");
sendResponse(p_pRequestRec,*p_ppHTTPResponse);
GSWHTTPResponse_Free(*p_ppHTTPResponse,pLogServerData);
*p_ppHTTPResponse=NULL;
GSWLog(GSW_DEBUG,pLogServerData,"Start dieSendResponse");
return p_fDecline ? DECLINED : OK;
};
//--------------------------------------------------------------------
// die with a message
static int dieWithMessage(request_rec* p_pRequestRec,CONST char* p_pszMessage,BOOL p_fDecline)
{
int iReturn=0;
GSWHTTPResponse* pResponse=NULL;
server_rec* pServerRec = p_pRequestRec->server;
GSWLog(GSW_DEBUG,pServerRec,"Start dieWithMessage");
GSWLog(GSW_ERROR,pServerRec,"Send Error Response: %s",p_pszMessage);
pResponse = GSWHTTPResponse_BuildErrorResponse(NULL,p_pszMessage,p_pRequestRec->server);
iReturn=dieSendResponse(p_pRequestRec,&pResponse,p_fDecline);
GSWLog(GSW_DEBUG,pServerRec,"Stop dieWithMessage");
return iReturn;
};
//--------------------------------------------------------------------
// GSWeb Request Handler
static int GSWeb_Handler(request_rec* p_pRequestRec)
{
int iRetVal=OK;
GSWURLComponents stURLComponents;
GSWHTTPResponse* pResponse = NULL;
GSWURLError eError=GSWURLError_OK;
CONST char* pszURLError=NULL;
server_rec* pServerRec = p_pRequestRec->server;
void* pLogServerData=pServerRec;
memset(&stURLComponents,0,sizeof(stURLComponents));
GSWLog(GSW_DEBUG,pLogServerData,"Start GSWeb_Handler");
// Log the request
GSWLog(GSW_INFO,
pLogServerData,
"GNUstepWeb New request: %s",
p_pRequestRec->uri);
// Parse the uri
eError=GSWParseURL(&stURLComponents,p_pRequestRec->uri,
pLogServerData);
if (eError!=GSWURLError_OK)
{
pszURLError=GSWURLErrorMessage(eError,
pLogServerData);
GSWLog(GSW_INFO,pLogServerData,"URL Parsing Error: %s", pszURLError);
if (eError==GSWURLError_InvalidAppName)
{
pResponse = GSWDumpConfigFile(&stURLComponents,
p_pRequestRec->server);
iRetVal=dieSendResponse(p_pRequestRec,&pResponse,NO);
}
else
iRetVal=dieWithMessage(p_pRequestRec,pszURLError,NO);
}
else
{
iRetVal = ap_setup_client_block(p_pRequestRec,REQUEST_CHUNKED_ERROR);
if (iRetVal==0) // OK Continue
{
// Build the GSWHTTPRequest with the method
GSWHTTPRequest* pRequest=NULL;
CONST char* pszRequestError=NULL;
pRequest=GSWHTTPRequest_New(p_pRequestRec->method,NULL,pLogServerData);
// validate the method
pszRequestError=GSWHTTPRequest_ValidateMethod(pRequest,pLogServerData);
if (pszRequestError)
{
iRetVal=dieWithMessage(p_pRequestRec,pszRequestError,NO);
}
else
{
GSWeb_Config* pConfig = NULL;
CONST char* pszDocRoot=NULL;
// copy headers
copyHeaders(p_pRequestRec,pRequest);
// Get Form data if any
// POST Method
if (pRequest->eMethod==ERequestMethod_Post
&& pRequest->uContentLength>0
&& ap_should_client_block(p_pRequestRec))
{
int iReadLength=0;
int iRemainingLength = pRequest->uContentLength;
char* pszBuffer = malloc(pRequest->uContentLength);
char* pszData = pszBuffer;
while (iRemainingLength>0)
{
ap_soft_timeout("reading GSWeb request",p_pRequestRec);
iReadLength=ap_get_client_block(p_pRequestRec,pszData,iRemainingLength);
ap_kill_timeout(p_pRequestRec);
pszData += iReadLength;
iRemainingLength-=iReadLength;
};
GSWLog(GSW_INFO,pLogServerData,"pszBuffer(%p)=%.*s",
(void*)pszBuffer,
(int)pRequest->uContentLength,
pszBuffer);
pRequest->pContent = pszBuffer;
}
else if (pRequest->eMethod==ERequestMethod_Get)
{
// Get the QueryString
stURLComponents.stQueryString.pszStart = p_pRequestRec->args;
stURLComponents.stQueryString.iLength = p_pRequestRec->args ? strlen(p_pRequestRec->args) : 0;
};
// get the document root
/* pConfig=(GSWeb_Config*)ap_get_module_config(p_pRequestRec->per_dir_config,&GSWeb_Module);
if (pConfig && pConfig->pszRoot)
pszDocRoot = pConfig->pszRoot;
else*/
pszDocRoot=(char*)ap_document_root(p_pRequestRec);
// Build the response (Beware: tr_handleRequest free pRequest)
ap_soft_timeout("Call GSWeb Application",p_pRequestRec);
pRequest->pServerHandle = p_pRequestRec;
pResponse=GSWAppRequest_HandleRequest(&pRequest,
&stURLComponents,
p_pRequestRec->protocol,
pszDocRoot,
g_szGSWeb_StatusResponseAppName, //AppTest name
pLogServerData);
ap_kill_timeout(p_pRequestRec);
// Send the response (if any)
if (pResponse)
{
sendResponse(p_pRequestRec,pResponse);
GSWHTTPResponse_Free(pResponse,pLogServerData);
iRetVal = OK;
}
else
iRetVal = DECLINED;
};
};
};
GSWLog(GSW_DEBUG,pLogServerData,"Stop GSWeb_Handler");
return iRetVal;
};
//--------------------------------------------------------------------
// Module definitions
static command_rec GSWeb_Commands[20] =
{
/*NEW {
GSWEB_CONF__DOC_ROOT, // Command keyword
GSWeb_SetDocRoot, // Function
NULL, // Fixed Arg
RSRC_CONF, // Type
TAKE1, // Args Descr
"RootDirectory for GSWeb"
},
*/
{
GSWEB_CONF__ALIAS, // Command keyword
GSWeb_SetScriptAlias, // Function
NULL, // Fixed Arg
RSRC_CONF, // Type
TAKE1, // Args Descr
"ScriptAlias for GSWeb"
},
{
GSWEB_CONF__CONFIG_FILE_PATH, // Command keyword
GSWeb_SetConfig, // Function
NULL, // Fixed Arg
RSRC_CONF, // Type
TAKE1, // Args Descr
"Configuration File Path for GSWeb"
},
{
NULL
}
};
handler_rec GSWeb_Handlers[] =
{
{ GSWEB__MIME_TYPE, GSWeb_Handler },
{ GSWEB_HANDLER, GSWeb_Handler },
{ NULL }
};
module GSWeb_Module =
{
STANDARD_MODULE_STUFF,
GSWeb_Init, // Init
NULL, // Create DirectoryConfig
NULL, // Merge DirectoryConfig
GSWeb_CreateConfig, // Create ServerConfig
NULL, // Merge ServerConfig
GSWeb_Commands, // Commands List
GSWeb_Handlers, // Handlers List
GSWeb_Translation, // Fn to Translatie Filename/URI
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};