mirror of
https://github.com/gnustep/libs-gsweb.git
synced 2025-02-23 11:41:20 +00:00
o added g_szHeader_GSWeb_ApplicationName * GSWAdaptors/Apache/mod_gsweb.c: o added application name header git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@17017 72102866-910b-0410-8b05-ffd578937521
924 lines
30 KiB
C
924 lines
30 KiB
C
/* mod_gsweb.c - GSWeb: Apache Module
|
|
Copyright (C) 1999 Free Software Foundation, Inc.
|
|
|
|
Written by: Manuel Guesdon <mguesdon@sbuilders.com>
|
|
Date: July 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.
|
|
*/
|
|
|
|
#define moduleRevision "$Revision$"
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <sys/param.h>
|
|
|
|
#include "../common/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>
|
|
|
|
#include <http_protocol.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;
|
|
|
|
|
|
#ifdef Apache2
|
|
/*
|
|
* Declare ourselves so the configuration routines can find and know us.
|
|
* We'll fill it in at the end of the module.
|
|
*/
|
|
module AP_MODULE_DECLARE_DATA GSWeb_Module;
|
|
|
|
#include <ap_compat.h>
|
|
#include <apr_pools.h>
|
|
#include <apr_strings.h>
|
|
#include <apr_tables.h>
|
|
|
|
#define ap_soft_timeout(s, r) ;
|
|
#define ap_hard_timeout(s, r) ;
|
|
#define ap_kill_timeout(r) ;
|
|
|
|
typedef apr_pool_t pool;
|
|
typedef apr_array_header_t array_header;
|
|
typedef apr_table_t table;
|
|
typedef apr_table_entry_t table_entry;
|
|
#else
|
|
//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
|
|
};
|
|
#endif
|
|
|
|
// 1.x/2.x Compatibility
|
|
#ifdef Apache2
|
|
#define APR_PSPRINTF apr_psprintf
|
|
#else
|
|
#define APR_PSPRINTF ap_psprintf
|
|
#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);
|
|
|
|
/*
|
|
* Locate our server configuration record for the current request.
|
|
*/
|
|
static GSWeb_Config *
|
|
GSWeb_GetServerConfig(server_rec *p_pServerRec)
|
|
{
|
|
return (GSWeb_Config *)ap_get_module_config(p_pServerRec->module_config,
|
|
&GSWeb_Module);
|
|
}
|
|
|
|
|
|
#ifdef Apache2
|
|
static int GSWeb_PostConfig(apr_pool_t *p, apr_pool_t *plog,
|
|
apr_pool_t *ptemp, server_rec *s)
|
|
{
|
|
char buffer[256]="mod_gsweb/"
|
|
GSWEB_SERVER_ADAPTOR_VERSION_MAJOR_STRING
|
|
"." GSWEB_SERVER_ADAPTOR_VERSION_MINOR_STRING
|
|
"rev";
|
|
RevisionStringToRevisionValue(buffer+strlen(buffer),moduleRevision);
|
|
ap_add_version_component(p, buffer);
|
|
return OK;
|
|
}
|
|
#endif
|
|
//--------------------------------------------------------------------
|
|
// Init
|
|
#ifdef Apache2
|
|
static void
|
|
GSWeb_ChildInit(apr_pool_t *p,
|
|
server_rec *p_pServerRec)
|
|
#else
|
|
static void
|
|
GSWeb_Init(server_rec *p_pServerRec,
|
|
pool *p)
|
|
#endif
|
|
{
|
|
GSWDict *pDict=GSWDict_New(0);
|
|
GSWeb_Config *pConfig=NULL;
|
|
|
|
pConfig=GSWeb_GetServerConfig(p_pServerRec);
|
|
GSWLog_Init(NULL,GSW_INFO);
|
|
GSWLog(GSW_INFO,p_pServerRec,
|
|
"GSWeb Init Start Config. Handler: " GSWEB_HANDLER);
|
|
GSWLog(GSW_DEBUG,p_pServerRec,
|
|
"GSWeb_Init: pConfig->pszGSWeb=%s",
|
|
pConfig->pszGSWeb);
|
|
|
|
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. Handler: " GSWEB_HANDLER);
|
|
GSWConfig_Init(pDict,p_pServerRec);
|
|
|
|
GSWLog(GSW_INFO,p_pServerRec,
|
|
"GSWeb Init. Handler: " GSWEB_HANDLER);
|
|
GSWDict_Free(pDict);
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// Create Config
|
|
static void *
|
|
GSWeb_CreateServerConfig(pool *p_pPool,
|
|
server_rec *p_pServerRec)
|
|
{
|
|
GSWeb_Config *pConfig = (GSWeb_Config *)ap_palloc(p_pPool,
|
|
sizeof(GSWeb_Config));
|
|
|
|
pConfig->pszGSWeb = g_szGSWeb_Prefix;
|
|
GSWLog(GSW_DEBUG,p_pServerRec,
|
|
"GSWeb_CreateServerConfig: pConfig->pszGSWeb=%s",
|
|
pConfig->pszGSWeb);
|
|
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_GetServerConfig(pServerRec);
|
|
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_GetServerConfig(pServerRec);
|
|
GSWLog(GSW_DEBUG,pServerRec,"pConfig=%p",pConfig);
|
|
GSWLog(GSW_DEBUG,pServerRec,"p_pszArg=%s",p_pszArg);
|
|
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_GetServerConfig(p_pRequestRec->server);
|
|
|
|
// 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 Declined");
|
|
iRetValue=DECLINED;
|
|
};
|
|
GSWLog(GSW_DEBUG,p_pRequestRec->server,
|
|
"Stop GSWeb_Translation return %d",
|
|
iRetValue);
|
|
return iRetValue;
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// Copy p_pRequestRec in headers into p_pGSWHTTPRequest
|
|
// Also add some environment variable headers
|
|
static void
|
|
copyHeaders(request_rec *p_pRequestRec,
|
|
GSWHTTPRequest *p_pGSWHTTPRequest)
|
|
{
|
|
server_rec *pServerRec = p_pRequestRec->server;
|
|
conn_rec *pConnection = p_pRequestRec->connection;
|
|
const array_header *headers_arr=ap_table_elts(p_pRequestRec->headers_in);
|
|
table_entry *headers=NULL;
|
|
int i=0;
|
|
char *pszPort=NULL;
|
|
CONST char *pszRemoteLogName=NULL;
|
|
GSWLog(GSW_DEBUG,pServerRec,"Start copyHeaders");
|
|
|
|
// copy p_pRequestRec headers
|
|
headers = (table_entry *) headers_arr->elts;
|
|
for (i=0;i<headers_arr->nelts;i++)
|
|
{
|
|
if (headers[i].key)
|
|
{
|
|
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
|
|
headers[i].key,headers[i].val);
|
|
#ifdef DEBUG
|
|
GSWLog(GSW_DEBUG,pServerRec,"key=%s value=%s",
|
|
headers[i].key,headers[i].val);
|
|
#endif
|
|
};
|
|
};
|
|
|
|
// Add server headers
|
|
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
|
|
g_szServerInfo_ServerSoftware,
|
|
#ifdef Apache2
|
|
ap_get_server_version()
|
|
#else
|
|
SERVER_VERSION
|
|
#endif
|
|
);
|
|
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
|
|
g_szServerInfo_RequestScheme,
|
|
ap_http_method(p_pRequestRec));
|
|
|
|
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
|
|
g_szServerInfo_Protocol,
|
|
p_pRequestRec->protocol);
|
|
|
|
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
|
|
g_szServerInfo_ProtocolNum,
|
|
APR_PSPRINTF(p_pRequestRec->pool,
|
|
"%u",
|
|
p_pRequestRec->proto_num));
|
|
|
|
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
|
|
g_szServerInfo_ServerName,
|
|
pServerRec->server_hostname);
|
|
|
|
{
|
|
unsigned int serverPort=(unsigned)ap_get_server_port(p_pRequestRec);
|
|
if (serverPort==0)
|
|
{
|
|
if (p_pRequestRec->parsed_uri.port_str && p_pRequestRec->parsed_uri.port!=0)
|
|
serverPort=(unsigned)p_pRequestRec->parsed_uri.port;
|
|
else
|
|
serverPort=(unsigned)pServerRec->port;
|
|
};
|
|
pszPort = APR_PSPRINTF(p_pRequestRec->pool,
|
|
"%u",
|
|
(unsigned int)serverPort);
|
|
};
|
|
|
|
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
|
|
g_szServerInfo_ServerPort,
|
|
pszPort);
|
|
#ifdef Apache2
|
|
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
|
|
g_szServerInfo_RemoteHost,
|
|
(CONST char *)ap_get_remote_host(pConnection,
|
|
p_pRequestRec->per_dir_config,
|
|
REMOTE_NAME,NULL));
|
|
#else /* Apache 1.x */
|
|
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
|
|
g_szServerInfo_RemoteHost,
|
|
(CONST char *)ap_get_remote_host(pConnection,
|
|
p_pRequestRec->per_dir_config,
|
|
REMOTE_NAME));
|
|
#endif
|
|
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);
|
|
pszPort = APR_PSPRINTF(p_pRequestRec->pool,
|
|
"%u",
|
|
#ifdef Apache2
|
|
pConnection->remote_addr->port
|
|
#else
|
|
ntohs(pConnection->remote_addr.sin_port)
|
|
#endif
|
|
);
|
|
GSWHTTPRequest_AddHeader(p_pGSWHTTPRequest,
|
|
g_szServerInfo_RemotePort,
|
|
pszPort);
|
|
|
|
#ifdef Apache2
|
|
//TODO
|
|
#else
|
|
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);
|
|
#endif
|
|
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 fonction to copy an header into p_pRequest
|
|
static void
|
|
getHeader(GSWDictElem *p_pElem,
|
|
void *p_pRequestRec)
|
|
{
|
|
request_rec *pRequestRec = (request_rec *)p_pRequestRec;
|
|
server_rec *pServerRec = pRequestRec->server;
|
|
#ifdef DEBUG
|
|
GSWLog(GSW_DEBUG,pServerRec,"Start getHeader key=%s value=%s headers_out=%p",
|
|
p_pElem->pszKey,(char *)p_pElem->pValue,pRequestRec->headers_out);
|
|
#endif
|
|
if (!pRequestRec->content_type &&
|
|
strcasecmp(p_pElem->pszKey,g_szHeader_ContentType)==0)
|
|
{
|
|
pRequestRec->content_type = (char *)ap_pstrdup(pRequestRec->pool,
|
|
(char *)p_pElem->pValue);//TODOVERIFY: strdup or not ?
|
|
#ifdef Apache2
|
|
ap_set_content_type(pRequestRec, (char *)p_pElem->pValue);
|
|
#endif
|
|
}
|
|
else
|
|
ap_table_add(pRequestRec->headers_out,p_pElem->pszKey,
|
|
(char *)p_pElem->pValue);
|
|
#ifdef DEBUG
|
|
GSWLog(GSW_DEBUG,pServerRec,"Stop getHeader");
|
|
#endif
|
|
};
|
|
|
|
//--------------------------------------------------------------------
|
|
// send response
|
|
|
|
static void
|
|
sendResponse(request_rec *p_pRequestRec,
|
|
GSWHTTPResponse *p_pHTTPResponse)
|
|
{
|
|
server_rec *pServerRec = p_pRequestRec->server;
|
|
GSWLog(GSW_DEBUG,pServerRec,"Start sendResponse");
|
|
|
|
// Add Headers for processing time information
|
|
#ifdef Apache2
|
|
if (GSWConfig_AddTimeHeaders())
|
|
{
|
|
char *pszBuffer= malloc(100);
|
|
apr_time_t tnow=apr_time_now();
|
|
apr_time_t duration=apr_time_as_msec(tnow-p_pRequestRec->request_time); // ms
|
|
strcpy(pszBuffer,"gswadaptor-requestdate: ");
|
|
FormatAPRTime(pszBuffer+strlen(pszBuffer),p_pRequestRec->request_time);
|
|
GSWHTTPResponse_AddHeader(p_pHTTPResponse,
|
|
pszBuffer);
|
|
strcpy(pszBuffer,"gswadaptor-sendresponsedate: ");
|
|
FormatAPRTime(pszBuffer+strlen(pszBuffer),tnow);
|
|
GSWHTTPResponse_AddHeader(p_pHTTPResponse,
|
|
pszBuffer);
|
|
sprintf(pszBuffer,"gswadaptor-processduration: %d.%d s",
|
|
(int)(duration/1000),(int)(duration%1000));
|
|
GSWHTTPResponse_AddHeader(p_pHTTPResponse,
|
|
pszBuffer);
|
|
free(pszBuffer);
|
|
pszBuffer=NULL;
|
|
};
|
|
#endif
|
|
// Process Headers
|
|
GSWDict_PerformForAllElem(p_pHTTPResponse->pHeaders,getHeader,p_pRequestRec);
|
|
|
|
GSWLog(GSW_DEBUG,pServerRec,"status message=[%s]",p_pHTTPResponse->pszStatusMessage);
|
|
p_pRequestRec->status_line = APR_PSPRINTF(p_pRequestRec->pool,"%u %s",
|
|
p_pHTTPResponse->uStatus,
|
|
p_pHTTPResponse->pszStatusMessage);
|
|
|
|
p_pRequestRec->status = p_pHTTPResponse->uStatus;
|
|
GSWLog(GSW_DEBUG,pServerRec,"p_pRequestRec->status_line=[%s]",p_pRequestRec->status_line);
|
|
|
|
// Set content type if none
|
|
if (!p_pRequestRec->content_type)
|
|
{
|
|
p_pRequestRec->content_type = g_szContentType_TextHtml;
|
|
#ifdef Apache2
|
|
ap_set_content_type(p_pRequestRec, g_szContentType_TextHtml);
|
|
#endif
|
|
};
|
|
GSWLog(GSW_DEBUG,pServerRec,"p_pRequestRec->content_type=%s",p_pRequestRec->content_type);
|
|
|
|
// Set content length
|
|
ap_set_content_length(p_pRequestRec, p_pHTTPResponse->uContentLength);
|
|
|
|
// Now Send response...
|
|
|
|
// send Headers
|
|
#ifndef Apache2 // No more needed in Apache2 (?)
|
|
ap_send_http_header(p_pRequestRec);
|
|
#endif
|
|
|
|
// 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;
|
|
GSWeb_Config *pConfig=NULL;
|
|
|
|
memset(&stURLComponents,0,sizeof(stURLComponents));
|
|
GSWLog(GSW_DEBUG,pLogServerData,"Start GSWeb_Handler");
|
|
|
|
pConfig=GSWeb_GetServerConfig(p_pRequestRec->server);
|
|
|
|
// Log the request
|
|
GSWLog(GSW_INFO,
|
|
pLogServerData,
|
|
"GNUstepWeb New request: %s",
|
|
p_pRequestRec->uri);
|
|
|
|
// Is this for us ?
|
|
if (strncmp(pConfig->pszGSWeb,
|
|
p_pRequestRec->uri,
|
|
strlen(pConfig->pszGSWeb))==0)
|
|
{
|
|
// 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
|
|
{
|
|
CONST char *pszDocRoot=NULL;
|
|
char* applicationName=NULL;
|
|
if (stURLComponents.stAppName.pszStart)
|
|
applicationName=strndup(stURLComponents.stAppName.pszStart,
|
|
stURLComponents.stAppName.iLength);//We'll need to release it
|
|
|
|
// copy headers
|
|
copyHeaders(p_pRequestRec,pRequest);
|
|
|
|
if (applicationName)
|
|
GSWHTTPRequest_AddHeader(pRequest,
|
|
g_szHeader_GSWeb_ApplicationName,
|
|
applicationName);
|
|
// 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
|
|
/* 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;
|
|
if (applicationName)
|
|
free(applicationName);
|
|
};
|
|
};
|
|
};
|
|
}
|
|
else
|
|
iRetVal = DECLINED;
|
|
GSWLog(GSW_DEBUG,pLogServerData,"Stop GSWeb_Handler");
|
|
return iRetVal;
|
|
};
|
|
|
|
|
|
|
|
#ifdef Apache2
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Which functions are responsible for which hooks in the server. */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
/*
|
|
* Each function our module provides to handle a particular hook is
|
|
* specified here. The functions are registered using
|
|
* ap_hook_foo(name, predecessors, successors, position)
|
|
* where foo is the name of the hook.
|
|
*
|
|
* The args are as follows:
|
|
* name -> the name of the function to call.
|
|
* predecessors -> a list of modules whose calls to this hook must be
|
|
* invoked before this module.
|
|
* successors -> a list of modules whose calls to this hook must be
|
|
* invoked after this module.
|
|
* position -> The relative position of this module. One of
|
|
* APR_HOOK_FIRST, APR_HOOK_MIDDLE, or APR_HOOK_LAST.
|
|
* Most modules will use APR_HOOK_MIDDLE. If multiple
|
|
* modules use the same relative position, Apache will
|
|
* determine which to call first.
|
|
* If your module relies on another module to run first,
|
|
* or another module running after yours, use the
|
|
* predecessors and/or successors.
|
|
*
|
|
* The number in brackets indicates the order in which the routine is called
|
|
* during request processing. Note that not all routines are necessarily
|
|
* called (such as if a resource doesn't have access restrictions).
|
|
* The actual delivery of content to the browser [9] is not handled by
|
|
* a hook; see the handler declarations below.
|
|
*/
|
|
static void
|
|
GSWeb_register_hooks(apr_pool_t *p)
|
|
{
|
|
/* ap_hook_pre_config(GSWeb_PreConfig, NULL, NULL, APR_HOOK_MIDDLE);
|
|
*/
|
|
ap_hook_post_config(GSWeb_PostConfig, NULL, NULL, APR_HOOK_MIDDLE);
|
|
/*
|
|
ap_hook_open_logs(GSWeb_OpenLogs, NULL, NULL, APR_HOOK_MIDDLE);
|
|
*/
|
|
ap_hook_child_init(GSWeb_ChildInit, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_handler(GSWeb_Handler, NULL, NULL, APR_HOOK_MIDDLE);
|
|
/* ap_hook_quick_handler(GSWeb_QuickHandler, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_pre_connection(GSWeb_PreConnection, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_process_connection(GSWeb_ProcessConnection, NULL, NULL, APR_HOOK_MIDDLE);
|
|
// [1] post read_request handling
|
|
ap_hook_post_read_request(GSWeb_PostReadRequest, NULL, NULL,APR_HOOK_MIDDLE);
|
|
ap_hook_log_transaction(GSWeb_Logger, NULL, NULL, APR_HOOK_MIDDLE);
|
|
#if 0
|
|
ap_hook_http_method(GSWeb_HttpMethod, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_default_port(GSWeb_DefaultPort, NULL, NULL, APR_HOOK_MIDDLE);
|
|
#endif
|
|
ap_hook_translate_name(GSWeb_Translation, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_header_parser(GSWeb_header_ParserHandler, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_check_user_id(GSWeb_CheckUserId, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_fixups(GSWeb_FixerUpper, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_type_checker(GSWeb_TypeChecker, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_access_checker(GSWeb_AccessChecker, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_auth_checker(GSWeb_AuthChecker, NULL, NULL, APR_HOOK_MIDDLE);
|
|
ap_hook_insert_filter(GSWeb_InsertFilter, NULL, NULL, APR_HOOK_MIDDLE);
|
|
*/
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* All of the routines have been declared now. Here's the list of */
|
|
/* directives specific to our module, and information about where they */
|
|
/* may appear and how the command parser should pass them to us for */
|
|
/* processing. Note that care must be taken to ensure that there are NO */
|
|
/* collisions of directive names between modules. */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
/*
|
|
* List of directives specific to our module.
|
|
*/
|
|
static const command_rec GSWeb_Commands[] =
|
|
{
|
|
AP_INIT_TAKE1
|
|
(
|
|
GSWEB_CONF__ALIAS, /* directive name */
|
|
GSWeb_SetScriptAlias, /* config action routine */
|
|
NULL, /* argument to include in call */
|
|
RSRC_CONF, /* where available */
|
|
"ScriptAlias for GSWeb" /* directive description */
|
|
),
|
|
AP_INIT_TAKE1
|
|
(
|
|
GSWEB_CONF__CONFIG_FILE_PATH, /* directive name */
|
|
GSWeb_SetConfig, /* config action routine */
|
|
NULL, /* argument to include in call */
|
|
RSRC_CONF, /* where available */
|
|
"Configuration File Path for GSWeb" /* directive description */
|
|
),
|
|
{NULL}
|
|
};
|
|
|
|
module AP_MODULE_DECLARE_DATA GSWeb_Module =
|
|
{
|
|
STANDARD20_MODULE_STUFF,
|
|
NULL,//x_create_dir_config, /* per-directory config creator */
|
|
NULL,//x_merge_dir_config, /* dir config merger */
|
|
GSWeb_CreateServerConfig, /* server config creator */
|
|
NULL,//x_merge_server_config, /* server config merger */
|
|
GSWeb_Commands, /* command table */
|
|
GSWeb_register_hooks, /* set up other request processing hooks */
|
|
};
|
|
|
|
#else
|
|
|
|
//--------------------------------------------------------------------
|
|
// Module definitions
|
|
|
|
|
|
static command_rec GSWeb_Commands[] =
|
|
{
|
|
{
|
|
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 }
|
|
};
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* */
|
|
/* Finally, the list of callback routines and data structures that provide */
|
|
/* the static hooks into our module from the other parts of the server. */
|
|
/* */
|
|
/*--------------------------------------------------------------------------*/
|
|
/*
|
|
* Module definition for configuration. If a particular callback is not
|
|
* needed, replace its routine name below with the word NULL.
|
|
*/
|
|
module GSWeb_Module =
|
|
{
|
|
STANDARD_MODULE_STUFF,
|
|
GSWeb_Init, // Init
|
|
NULL, // Create DirectoryConfig
|
|
NULL, // Merge DirectoryConfig
|
|
GSWeb_CreateServerConfig, // 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
|
|
};
|
|
|
|
#endif
|