blob: eccfd1c249785c183d4e221f717faa20d7dbfb87 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <httpfilt.h>
#include <httpext.h>
#include "axis2_iis_constants.h"
#include "axis2_iis_worker.h"
/* Axis headers */
#include <axutil_error_default.h>
#include <axutil_log_default.h>
#include <axutil_thread_pool.h>
#include <axiom_xml_reader.h>
#include <axutil_log.h>
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif
#define AXIS2_IIS_LOG_FILE_TAG "log_file"
#define AXIS2_IIS_LOG_LEVEL_TAG "log_level"
#define AXIS2_IIS_REPO_PATH_TAG "axis2c_home"
#define AXIS2_IIS_EXTENSION_URI_TAG "extension_uri"
#define AXIS2_IIS_REDIRECT_WORD_TAG "redirect_uri"
#define AXIS2_IIS_AXIS2_LOCATION "axis2_location"
#define AXIS2_IIS_SERVICE_URL_PREFIX "services_url_prefix"
#define AXIS2_IIS_LOG_TRACE_VERB "trace"
#define AXIS2_IIS_LOG_ERROR_VERB "error"
#define AXIS2_IIS_LOG_INFO_VERB "info"
#define AXIS2_IIS_LOG_USER_VERB "user"
#define AXIS2_IIS_LOG_CRITICAL_VERB "critical"
#define AXIS2_IIS_LOG_WARN_VERB "warning"
#define AXIS2_IIS_LOG_DEBUG_VERB "debug"
#define MAX_FILE_PATH 256
#define REGISTRY_LOCATION "Software\\Apache Axis2c\\IIS ISAPI Redirector"
static int is_inited = FALSE;
static axis2_iis_worker_t *axis2_worker = NULL;
static const axutil_env_t *axutil_env = NULL;
/* Configuration parameters */
axis2_char_t *axis2_location = "/axis2";
static axis2_char_t *axis2_service_url_prefix= "/services";
static axis2_char_t repo_path[MAX_FILE_PATH];
static axis2_char_t log_file[MAX_FILE_PATH];
static axutil_log_levels_t log_level = AXIS2_LOG_LEVEL_CRITICAL;
/* Path variables */
static char szOriginalPath[_MAX_PATH + 1];
static char szPath[_MAX_PATH + 1];
axis2_char_t general_error[] = "<html>\r\n"
"<head><title> An IIS server error occurred. </title></head>\r\n"
"<h1> An IIS server error occurred </h1>\r\n"
"<hr>\r\n"
"An error occurred in IIS while processing this request.</hr></html>";
axis2_char_t initializing_error[] = "<html>\r\n"
"<head><title> An IIS server error occurred. </title></head>\r\n"
"<h1> An IIS server error occurred </h1>\r\n"
"<hr>\r\n"
"An error occurred while initilizing Axis2/C.</hr></html>";
/*
* This is a utility functipn for reading configuration data from the registery.
*/
static axis2_status_t AXIS2_CALL
read_registery_init_data();
/*
* Utility function for reading
*/
static axis2_status_t AXIS2_CALL get_registry_config_parameter(
HKEY hkey,
const char *tag,
char *b,
DWORD sz);
/*
* Parse the given string and return the corresponding log_level
*/
axutil_log_levels_t AXIS2_CALL axis2_iis_parse_log_level(char level[]);
/*
* Initialize axis. This function is called in the begining of the module loading.
* It initializes the axis by reading values from the configuration and creating the
* required structures for the axis2c
*/
axis2_status_t AXIS2_CALL init_axis2();
/*
* This is the function to be called after the processing
* is over for non Axis2 requets
*/
VOID
WINAPI
ExecUrlCompletion (
EXTENSION_CONTROL_BLOCK * pecb,
PVOID pContext,
DWORD cbIO,
DWORD dwError
);
/*
* If somethign went wrong in the IIS server when
* we are proccessing we send this
*/
BOOL
send_error(
EXTENSION_CONTROL_BLOCK * pecb,
CHAR error[]);
axis2_status_t AXIS2_CALL init_axis2();
BOOL
WINAPI
GetExtensionVersion(HSE_VERSION_INFO * pVer)
{
pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR,
HSE_VERSION_MAJOR);
strncpy( pVer->lpszExtensionDesc,
"WildCardMap Sample ISAPI Extension", HSE_MAX_EXT_DLL_NAME_LEN );
pVer->lpszExtensionDesc[HSE_MAX_EXT_DLL_NAME_LEN-1] = '\0';
server_version = 5;
return TRUE;
}
DWORD
WINAPI
HttpExtensionProc(EXTENSION_CONTROL_BLOCK * pecb)
{
HSE_EXEC_URL_INFO ExecUrlInfo;
DWORD cbData = INTERNET_MAX_URL_LENGTH;
char url[INTERNET_MAX_URL_LENGTH];
axis2_bool_t is_for_us = AXIS2_TRUE;
/* Get the URL */
if ( pecb->GetServerVariable( pecb->ConnID,
"URL",
url,
&cbData ) == FALSE )
{
return HSE_STATUS_ERROR;
}
if (!is_inited)
{
DWORD dwBufferSize = 0;
axis2_char_t server_software[256];
axis2_char_t *version = NULL;
ZeroMemory(szOriginalPath, sizeof szOriginalPath);
dwBufferSize = sizeof szOriginalPath;
#if _WIN32_WINNT >= 0x0502
GetDllDirectory( dwBufferSize, szOriginalPath );
#else
GetCurrentDirectory( dwBufferSize, szOriginalPath );
#endif
ZeroMemory(szPath, sizeof szPath);
dwBufferSize = sizeof szPath;
/* Get the current physical paht */
if (pecb->GetServerVariable(pecb->ConnID, "APPL_PHYSICAL_PATH", szPath, &dwBufferSize) == FALSE)
{
send_error(pecb, initializing_error);
return HSE_STATUS_ERROR;
}
/* Retrieve the server version */
dwBufferSize = 32;
if (pecb->GetServerVariable(pecb->ConnID, "SERVER_SOFTWARE", server_software, &dwBufferSize) == FALSE)
{
send_error(pecb, initializing_error);
return HSE_STATUS_ERROR;
}
version = axutil_strchr(server_software, '/');
if (version)
{
server_version = atoi(version + 1);
}
#if _WIN32_WINNT >= 0x0502
SetDllDirectory( szPath );
#else
SetCurrentDirectory( szPath );
#endif
/* If we haven't initialized axis2/c before initialization failed */
if (AXIS2_FAILURE == init_axis2())
{
send_error(pecb, initializing_error);
return HSE_STATUS_ERROR;
}
#if _WIN32_WINNT >= 0x0502
SetDllDirectory( szOriginalPath );
#else
SetCurrentDirectory( szOriginalPath );
#endif
}
/* Check weather we have a request for Axis2/C */
if (server_version >= 6 && strlen(url) >= strlen(axis2_location))
{
int i = 0;
is_for_us = AXIS2_TRUE;
while (axis2_location[i] != '\0')
{
if (axis2_location[i] != (url)[i]) {
is_for_us = AXIS2_FALSE;
break;
}
i++;
}
if (url[i] != '/' && url[i] != '\0')
{
is_for_us = AXIS2_FALSE;
}
}
if (is_for_us)
{
/* Windows cannot find the correct dlls unless the path is set*/
#if _WIN32_WINNT >= 0x0502
SetDllDirectory( szPath );
#else
SetCurrentDirectory( szPath );
#endif
pecb->dwHttpStatusCode = HTTP_INTERNAL_SERVER_ERROR;
/* We are sure that worker is not NULL since it is NULL init_axis2 would have failed */
axis2_iis_worker_process_request(axis2_worker, axutil_env, pecb);
/* Windows cannot find the correct dlls unless the dir is set
but we want to reset to previous dir after the load */
#if _WIN32_WINNT >= 0x0502
SetDllDirectory( szOriginalPath );
#else
SetCurrentDirectory( szOriginalPath );
#endif
return HSE_STATUS_SUCCESS;
}
else if (server_version >= 6)
{
/* For IIS 5.1 or earlier this code is never executed. Since the URL is
redirected to Axis2/C by the Filter */
/* If not for Axis2/C let the request go to who ever wants it */
ExecUrlInfo.pszUrl = NULL; /* Use original request URL */
ExecUrlInfo.pszMethod = NULL; /* Use original request method */
ExecUrlInfo.pszChildHeaders = NULL; /* Use original request headers */
ExecUrlInfo.pUserInfo = NULL; /* Use original request user info */
ExecUrlInfo.pEntity = NULL; /* Use original request entity */
/* Provent recursion */
ExecUrlInfo.dwExecUrlFlags = HSE_EXEC_URL_IGNORE_CURRENT_INTERCEPTOR;
/* Associate the completion routine and the current URL with this request. */
if ( pecb->ServerSupportFunction( pecb->ConnID,
HSE_REQ_IO_COMPLETION,
ExecUrlCompletion,
NULL,
NULL) == FALSE )
{
return HSE_STATUS_ERROR;
}
/* Ok, now that everything is set up, let's call the child request */
if ( pecb->ServerSupportFunction( pecb->ConnID,
HSE_REQ_EXEC_URL,
&ExecUrlInfo,
NULL,
NULL ) == FALSE )
{
return HSE_STATUS_ERROR;
}
/* Return pending and let the completion clean up */
return HSE_STATUS_PENDING;
}
return HSE_STATUS_ERROR;
}
VOID
WINAPI
ExecUrlCompletion (
EXTENSION_CONTROL_BLOCK * pecb,
PVOID pContext,
DWORD cbIO,
DWORD dwError
)
{
/* We are done so notify */
pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_DONE_WITH_SESSION,
NULL,
NULL,
NULL);
}
BOOL
send_error(
EXTENSION_CONTROL_BLOCK * pecb,
axis2_char_t error[])
{
DWORD cbData;
pecb->dwHttpStatusCode = 500;
/* Send headers and response */
pecb->ServerSupportFunction( pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
"500 Server Error",
NULL,
(LPDWORD)"Content-Type: text/html\r\n\r\n" );
cbData = axutil_strlen( error );
return pecb->WriteClient( pecb->ConnID,
error,
&cbData,
HSE_IO_SYNC );
}
axis2_status_t AXIS2_CALL read_registery_init_data()
{
long rc = 0;
axis2_status_t ok = TRUE;
char tmpbuf[INTERNET_MAX_URL_LENGTH];
HKEY hkey;
AXIS2_IMPORT extern axis2_char_t *axis2_request_url_prefix;
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGISTRY_LOCATION, (DWORD) 0, KEY_READ, &hkey);
if (ERROR_SUCCESS != rc)
{
return AXIS2_FAILURE;
}
if (get_registry_config_parameter(hkey, AXIS2_IIS_REPO_PATH_TAG, tmpbuf, sizeof(repo_path)))
{
strcpy(repo_path, tmpbuf);
}
else
{
return AXIS2_FAILURE;
}
if (get_registry_config_parameter(hkey, AXIS2_IIS_LOG_FILE_TAG, tmpbuf, sizeof(log_file)))
{
strcpy(log_file, tmpbuf);
}
else
{
return AXIS2_FAILURE;
}
if (get_registry_config_parameter(hkey, AXIS2_IIS_LOG_LEVEL_TAG, tmpbuf, sizeof(tmpbuf)))
{
log_level = axis2_iis_parse_log_level(tmpbuf);
}
else
{
return AXIS2_FAILURE;
}
if (get_registry_config_parameter(hkey, AXIS2_IIS_SERVICE_URL_PREFIX, tmpbuf, sizeof(tmpbuf)))
{
axis2_request_url_prefix = _strdup(tmpbuf);
}
if (get_registry_config_parameter(hkey, AXIS2_IIS_AXIS2_LOCATION, tmpbuf, sizeof(tmpbuf)))
{
axis2_location = _strdup(tmpbuf);
}
RegCloseKey(hkey);
return ok;
}
axutil_log_levels_t AXIS2_CALL
axis2_iis_parse_log_level(char level[])
{
if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_TRACE_VERB))
{
return AXIS2_LOG_LEVEL_TRACE;
}
if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_DEBUG_VERB))
{
return AXIS2_LOG_LEVEL_DEBUG;
}
if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_INFO_VERB))
{
return AXIS2_LOG_LEVEL_INFO;
}
if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_USER_VERB))
{
return AXIS2_LOG_LEVEL_USER;
}
if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_WARN_VERB))
{
return AXIS2_LOG_LEVEL_WARNING;
}
if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_ERROR_VERB))
{
return AXIS2_LOG_LEVEL_ERROR;
}
if (0 == AXIS2_STRICMP(level, AXIS2_IIS_LOG_CRITICAL_VERB))
{
return AXIS2_LOG_LEVEL_CRITICAL;
}
return AXIS2_LOG_LEVEL_DEBUG;
}
axis2_status_t AXIS2_CALL
get_registry_config_parameter(HKEY hkey, const char *tag, char *b, DWORD sz)
{
DWORD type = 0;
LONG lrc;
lrc = RegQueryValueEx(hkey, tag, (LPDWORD) 0, &type, (LPBYTE) b, &sz);
if ((ERROR_SUCCESS != lrc) || (type != REG_SZ))
{
return FALSE;
}
b[sz] = '\0';
return TRUE;
}
/**
* This method initializes the axis2 engine. All the required variables are set to
* their initial values in this method.
*/
axis2_status_t AXIS2_CALL init_axis2()
{
/*
* These are the varibles required to initialize axis.
*/
axis2_status_t status = FALSE;
/* We need to init xml readers before we go into threaded env */
if (!is_inited)
{
axiom_xml_reader_init();
status = read_registery_init_data();
if (status == AXIS2_FAILURE)
{
return AXIS2_FAILURE;
}
axutil_error_init();
/* Initialize the environement */
axutil_env = axutil_env_create_all(log_file, log_level);
if (!axutil_env)
{
return AXIS2_FAILURE;
}
axis2_worker = axis2_iis_worker_create(axutil_env, repo_path);
if (!axis2_worker)
{
return AXIS2_FAILURE;
}
is_inited = AXIS2_TRUE;
return AXIS2_SUCCESS;
}
return AXIS2_FAILURE;
}