summaryrefslogtreecommitdiffstats
path: root/src/core/transport/http/server/IIS/axis2_isapi_plugin.c
blob: eccfd1c249785c183d4e221f717faa20d7dbfb87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
/*
 * 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;
}