📄 mod_gsoap.c
字号:
/** Apache SOAP module for Foto Upload * @file mod_gsoap.c * @author Christian Aberger (http://www.aberger.at) */#include <stdio.h>#include <assert.h>#include <ltdl.h>#include "httpd.h"#include "http_config.h"#include "http_core.h"#include "http_log.h"#include "http_main.h"#include "http_protocol.h"#include "util_script.h"#include "stdsoap2.h" // standard header for gsoap#include "apache_gsoap.h"typedef int bool;#define false 0#define true ((int)0xffff)#define IOBUF_CHUNK_SIZE 8192#define GSOAP_ID "Apache mod_gsoap gsoap httpd extension 0.0.5"/** A shared library containing a SOAP server. */typedef struct SoapSharedLibrary_S { pool *m_pPool; void *m_hLibrary; ///< handle of the loaded libray. const char *m_pszPath; ///< the path of the library, including the name. bool m_bIsSOAPLibrary; ///< is this library a SOAP library that contains the server factory entry point?} SoapSharedLibrary;/** Table of shared libraries that are already loaded. * a singleton. */typedef struct SoapSharedLibraries_S { pool *m_pPool; SoapSharedLibrary *m_pSOAPLibrary; ///< the main SOAP library that will serve our requests array_header *m_pLibraries; ///< the array where we store our libraries. apache_init_soap_interface_fn m_pfnEntryPoint; struct apache_soap_interface *m_pIntf; bool m_bAllLibrariesLoaded; ///< have all libraries in our libraries collection been already successfully loaded?} SoapSharedLibraries;/** Environment to which record applies (directory, * server, or combination). */typedef enum enConfigurationType { ct_server = 1, ///< used for per-server configuration ct_directory = 2, ///< used for per-directory configuration ct_both = 3 ///< used for both} ConfigurationType;/** Store the configuration information set in the Apache Server configuration directives. * These are set e.g. in the file httpd.conf * It's perfectly reasonable to have two different structures for the two * different environments. The same command handlers will be called for * both, though, so the handlers need to be able to tell them apart. One * possibility is for both structures to start with an int which is zero for * one and 1 for the other. * * Note that while the per-directory and per-server configuration records are * available to most of the module handlers, they should be treated as * READ-ONLY by all except the command and merge handlers. Sometimes handlers * are handed a record that applies to the current location by implication or * inheritance, and modifying it will change the rules for other locations. */typedef struct gsoapConfiguration_S { SoapSharedLibraries *m_pLibraries; ConfigurationType m_Type; ///< the type of configuration environment} gsoapConfiguration;/** Our internal per request soap configuration */typedef struct gsoapRequestConfiguration_S { request_rec *r; ///< the current request record. char *m_pszAllHeaders; ///< all headers received as a string, this is returned to gsoap's http_parse function before we return the body. const char *m_pszCurrentHeaderReadingPosition; ///< the position where the next header read operation will start. unsigned int m_nHeaderLength; ///< total length of all headers concatenated as string char *m_pOutBuf; ///< output buffer size_t m_nOutBufLength; ///< allocated length of output buffer size_t m_nOutBufCount; ///< bytes in output buffer int headers_sent; ///< have http - headers already been sent to client us? int headers_received; ///< have the request headers already been passed to gsoap ? int (*http_parse)(struct soap *); ///< the original gsoap parsing function.} gsoapRequestConfiguration;/* * To avoid leaking memory from pools other than the per-request one, we * allocate a module-private pool. */static pool *the_gsoapPool = NULL;/** @return our pool for gsoapConfiguration */static pool *gsoapConfiguration_getModulePool() { if (NULL == the_gsoapPool) { the_gsoapPool = ap_make_sub_pool(NULL); } return the_gsoapPool;}static gsoapConfiguration *getConfiguration(request_rec *r);static gsoapRequestConfiguration *getRequestConfiguration(struct soap *);/** @param p the pool to use for memory allocations. @param pszPath the path of the library.*/static void SoapSharedLibrary_init(SoapSharedLibrary *This, pool *p, const SoapSharedLibrary *pLib) {/* fprintf(stderr, "call gsoap module \n\n");*/ This->m_pPool = p; This->m_hLibrary = NULL; This->m_pszPath = ap_pstrdup(p, pLib->m_pszPath); This->m_bIsSOAPLibrary = pLib->m_bIsSOAPLibrary;}static void SoapSharedLibrary_init2(SoapSharedLibrary *This, pool *p, const char *pszPath) { This->m_pPool = p; This->m_hLibrary = NULL; This->m_pszPath = ap_pstrdup(p, pszPath); This->m_bIsSOAPLibrary = false;}static void SoapSharedLibrary_clear(SoapSharedLibrary *This, pool *p) { This->m_pPool = p; This->m_hLibrary = NULL; This->m_pszPath = NULL; This->m_bIsSOAPLibrary = false;}static SoapSharedLibrary *SoapSharedLibrary_create(pool *p) { SoapSharedLibrary *This = (SoapSharedLibrary *)ap_pcalloc(p, sizeof(SoapSharedLibrary)); SoapSharedLibrary_clear(This, p);}/* SoapSharedLibrary_assign(SoapSharedLibrary *This, SoapSharedLibrary *pLib) { This->m_pPool = pLib->m_pPool; This->m_hLibrary = NULL; This->m_pszPath = ap_strdup(m_pPool, pLib->m_pszPath); This->m_bIsSoapLibrary = pLib->m_bIsSoapLibrary; }*//** * @param pTempPool pool to use for allocating temporary objects (e.g. error message). */static const char *SoapSharedLibrary_load(SoapSharedLibrary *This, pool *pTempPool) { const char *pszError = NULL; const int nFlags = RTLD_LAZY | RTLD_GLOBAL; This->m_hLibrary = (void *)dlopen(This->m_pszPath, nFlags); if (NULL == This->m_hLibrary) { pszError = ap_psprintf(NULL == pTempPool ? This->m_pPool : pTempPool, "mod_gsoap: %s loading library %s", dlerror(), This->m_pszPath); } return pszError;}/** * @return NULL on success or error message if an error occurred. */static const char *SoapSharedLibrary_unload(SoapSharedLibrary *This) { const char *pszError = NULL; if (NULL != This->m_hLibrary) { int nClose = dlclose(This->m_hLibrary); pszError = dlerror(); This->m_hLibrary = NULL; } return pszError;}/*-------------------------------------------------------*/static void SoapSharedLibraries_init(SoapSharedLibraries *This, pool *p) { This->m_pPool = p; This->m_pSOAPLibrary = NULL; This->m_pLibraries = ap_make_array(p, 0, sizeof(SoapSharedLibrary **)); This->m_bAllLibrariesLoaded = false; This->m_pfnEntryPoint = NULL; This->m_pIntf = (struct apache_soap_interface *)ap_pcalloc(p, sizeof(struct apache_soap_interface));}static SoapSharedLibrary *SoapSharedLibraries_getLibrary(SoapSharedLibraries *This, unsigned nIndex) { SoapSharedLibrary **ppLibs = NULL; SoapSharedLibrary *pLib = NULL; assert(NULL != This); assert(NULL != This->m_pLibraries); assert(nIndex >= 0); assert(nIndex < This->m_pLibraries->nelts); ppLibs = (SoapSharedLibrary **)This->m_pLibraries->elts; pLib = ppLibs[nIndex]; return pLib;}/** * @param pszPath the operating system name of the library. */static bool SoapSharedLibraries_contains(SoapSharedLibraries *This, const char *pszPath) { int i = 0; bool bContains = false; for (i = 0; i < This->m_pLibraries->nelts && !bContains; i++) { SoapSharedLibrary *pLib = SoapSharedLibraries_getLibrary(This, i); assert(NULL != pLib); if (0 == strcmp(pszPath, pLib->m_pszPath)) { bContains = true; } } return bContains;}static void SoapSharedLibraries_addLibrary(SoapSharedLibraries *This, SoapSharedLibrary *pLibrary) { assert(NULL != pLibrary); This->m_bAllLibrariesLoaded = false; if (!SoapSharedLibraries_contains(This, pLibrary->m_pszPath)) { SoapSharedLibrary **ppNewLib = (SoapSharedLibrary **)ap_push_array(This->m_pLibraries); *ppNewLib = pLibrary; if (pLibrary->m_bIsSOAPLibrary) { This->m_pSOAPLibrary = pLibrary; } }}static const char *SoapSharedLibraries_getEntryPoints(SoapSharedLibraries *This, SoapSharedLibrary *pLib, pool *pTempPool) { (*This->m_pfnEntryPoint)(This->m_pIntf);/* void *pfun = NULL; pfun = (void *)dlsym(pLib->m_hLibrary, "soap_init"); This->m_pIntf->fsoap_init = (apache_soap_init_fn)pfun; pfun = (void *)dlsym(pLib->m_hLibrary, "soap_serve"); This->m_pIntf->fsoap_serve = (apache_soap_serve_fn)pfun; pfun = (void *)dlsym(pLib->m_hLibrary, "soap_destroy"); This->m_pIntf->fsoap_destroy = (apache_soap_destroy_fn)pfun; pfun = (void *)dlsym(pLib->m_hLibrary, "soap_end"); This->m_pIntf->fsoap_end = (apache_soap_end_fn)pfun;*/ return NULL;}/** * @return the error message if a load failed, NULL on success. */static const char *SoapSharedLibraries_loadAllLibraries(SoapSharedLibraries *This, pool *pTempPool) { bool bAllLibrariesLoaded = false; const char *pszError = NULL; bool bRetry = false; int i = 0; int nRetry = 0; assert(NULL != This); if (This->m_bAllLibrariesLoaded) { return NULL; } for (nRetry = 0; nRetry < 5 && !bAllLibrariesLoaded; nRetry++) { do { pszError = NULL; bRetry = false; // don't try it again. bAllLibrariesLoaded = true; for (i = 0; i < This->m_pLibraries->nelts; i++) { SoapSharedLibrary *pLib = SoapSharedLibraries_getLibrary(This, i); if (NULL == pLib->m_hLibrary) { pszError = SoapSharedLibrary_load(pLib, pTempPool); if (NULL == pszError) { assert(NULL != pLib->m_hLibrary); bRetry = true; ///< we loaded one, lets retry with all others, maybe they depend on that. } else { bAllLibrariesLoaded = false; } if (NULL != pLib->m_hLibrary && pLib->m_bIsSOAPLibrary) { void *pfun = (void *)dlsym(pLib->m_hLibrary, APACHE_HTTPSERVER_ENTRY_POINT); if (NULL == pfun) { pszError = ap_psprintf(pTempPool, "gsoap: load library \"%s\" success, but failed to find the \"%s\" entry point", pLib->m_pszPath, APACHE_HTTPSERVER_ENTRY_POINT); return pszError; } else { This->m_pfnEntryPoint = (apache_init_soap_interface_fn)pfun; pszError = SoapSharedLibraries_getEntryPoints(This, pLib, pTempPool); } } } } } while(bRetry); } if (bAllLibrariesLoaded) { This->m_bAllLibrariesLoaded = true; pszError = NULL; } return pszError;}static const char *SoapSharedLibraries_unloadAllLibraries(SoapSharedLibraries *This) { const char *pszError = NULL; int i = 0; assert(NULL != This); This->m_bAllLibrariesLoaded = false; for (i = 0; i < This->m_pLibraries->nelts && NULL == pszError; i++) { SoapSharedLibrary *pLib = SoapSharedLibraries_getLibrary(This, i); if (NULL != pLib && NULL != pLib->m_hLibrary) { const char *pszErr = SoapSharedLibrary_unload(pLib); if (NULL == pszError) { pszError = pszErr; } } } return pszError;}static void SoapSharedLibraries_clear(SoapSharedLibraries *This) { int i = 0; SoapSharedLibraries_unloadAllLibraries(This); for (i = 0; i < This->m_pLibraries->nelts; i++) { SoapSharedLibrary *pLib = SoapSharedLibraries_getLibrary(This, i); SoapSharedLibrary_clear(pLib, This->m_pPool); }}static void SoapSharedLibraries_merge(SoapSharedLibraries *This, SoapSharedLibraries *pLibs) { int i = 0; assert(NULL != This); if (NULL == pLibs) { return; } This->m_bAllLibrariesLoaded = false; for (i = 0; i < pLibs->m_pLibraries->nelts; i++) { SoapSharedLibrary *pLib = SoapSharedLibraries_getLibrary(pLibs, i); if (!SoapSharedLibraries_contains(This, pLib->m_pszPath)) { SoapSharedLibrary *pNewLib = SoapSharedLibrary_create(This->m_pPool); SoapSharedLibrary_init(pNewLib, This->m_pPool, pLib); SoapSharedLibraries_addLibrary(This, pNewLib); } }}static void SoapSharedLibraries_merge3(SoapSharedLibraries *This, SoapSharedLibraries *libraries1, SoapSharedLibraries *libraries2) { SoapSharedLibraries_merge(This, libraries1); SoapSharedLibraries_merge(This, libraries2);}static void gsoapConfiguration_merge(gsoapConfiguration *This, gsoapConfiguration *pParentConfig, gsoapConfiguration *pNewConfig) { assert(NULL != This); SoapSharedLibraries_merge3(This->m_pLibraries, pParentConfig->m_pLibraries, pNewConfig->m_pLibraries); This->m_Type = ct_both;}static void gsoapConfiguration_init(gsoapConfiguration *This, pool *p) { This->m_pLibraries = (SoapSharedLibraries *)ap_pcalloc(p, sizeof(SoapSharedLibraries)); SoapSharedLibraries_init(This->m_pLibraries, p); This->m_Type = ct_directory;}static gsoapConfiguration *gsoapConfiguration_create(pool *p) { gsoapConfiguration *pConfig = (gsoapConfiguration *)ap_pcalloc(p, sizeof(gsoapConfiguration)); gsoapConfiguration_init(pConfig, p); return pConfig;}/*--------------------------------------------------------------------------*//* forward declarations *//*--------------------------------------------------------------------------*/static int gsoap_handler(request_rec *r);static void gsoap_init(server_rec *s, pool *p);static void gsoap_child_init(server_rec *s, pool *p);static void gsoap_child_exit(server_rec *s, pool *p);static void *gsoap_create_dir_config(pool *p, char *dirspec);static void *gsoap_merge_dir_config(pool *p, void *parent_conf, void *newloc_conf);static void *gsoap_create_server_config(pool *p, server_rec *s);static void *gsoap_merge_server_config(pool *p, void *server1_conf, void *server2_conf);static int gsoap_post_read_request(request_rec *r);static int gsoap_translate_handler(request_rec *r);static int gsoap_check_user_id(request_rec *r);static int gsoap_auth_checker(request_rec *r);static int gsoap_access_checker(request_rec *r);static int gsoap_type_checker(request_rec *r);static int gsoap_fixer_upper(request_rec *r);static int gsoap_logger(request_rec *r);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -