| |
| /* |
| * 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; |
| } |