File: mod_xmlrpc.c

package info (click to toggle)
libapache2-mod-xmlrpc2 2.2.1-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 176 kB
  • ctags: 72
  • sloc: ansic: 747; sh: 43; makefile: 14
file content (144 lines) | stat: -rw-r--r-- 3,685 bytes parent folder | download
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
/*
 * Include the core server components.
 */
#include "httpd.h"
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
#include "apr_strings.h"
#include "mod_xmlrpc_server.h"
#include "mod_xmlrpc.h"

#ifdef SUPPORT_C
#include "mod_xmlrpc_c.h"
#endif

#ifdef SUPPORT_RUBY
#include "mod_xmlrpc_rb.h"
#endif

module AP_MODULE_DECLARE_DATA xmlrpc_module;
int mod_xmlrpc_debug_lvl = DEBUG_NONE;

static void *create_xmlrpc_config(apr_pool_t *p, server_rec *s)
{
	return (void *) mod_xmlrpc_server_new();
}

static const char *mod_xmlrpc_debug(cmd_parms *parms, void *ign, char *nr)
{
	int level;

	level = atoi(nr);
	if (!level)
		return "Invalid argument supplied to XMLRPCDebug!";
	mod_xmlrpc_debug_lvl = level;

	return NULL;
}

static void xmlrpc_client_response(request_rec *r, size_t sz, const char *data)
{
	char len[10];
	int i;

	ap_set_content_type(r, "text/xml");
	apr_snprintf(len, sizeof(len), "%lu", (unsigned long) sz); /* apr doesn't support %zd?? ARGH!#$!$% */
	apr_table_setn(r->headers_out, "Content-Length", len);

	// This interface sucks.  ap_rwrite() takes a *signed* int?  What
	// genius decided to go w/ that?
	i = (int) sz;
	if (i < 0)
		i = 0;
	//ap_soft_timeout("Sending data", r);
	//ap_send_http_header(r);
	ap_rwrite(data, i, r);
	//ap_kill_timeout(r);
}

static int xmlrpc_handler(request_rec *r)
{
	void *registry;
	char buf[HUGE_STRING_LEN];
	char *input;
	struct mod_xmlrpc_result output;
	long got = 0;
	long total = 0;

	if (strcmp(r->handler, "xml-rpc") != 0)
		return DECLINED;
	if (r->method_number != M_POST)
		return HTTP_METHOD_NOT_ALLOWED;
//	if (strcmp(r->content_type, "text/xml") != 0)
//		return HTTP_BAD_REQUEST;
	if (ap_setup_client_block(r, REQUEST_CHUNKED_ERROR) != OK)
		return HTTP_BAD_REQUEST;

	if (r->remaining < 1)
		return HTTP_BAD_REQUEST;
//	if (r->remaining > xmlrpc_limit_get(XMLRPC_XML_SIZE_LIMIT_ID))
//		return HTTP_INTERNAL_SERVER_ERROR;

	if (r->remaining > sizeof(buf)-1) {
		input = apr_palloc(r->pool, 1);
		input[0] = '\0';
	}
	else
		input = buf;

	registry = ap_get_module_config(r->server->module_config, &xmlrpc_module);
	total = r->remaining;

	while ((got = ap_get_client_block(r, buf, sizeof(buf)-1)) > 0) {
		buf[got] = '\0';
		if (input != buf)
			input = apr_pstrcat(r->pool, input, buf, NULL);
 	}

	DPRINTF(DEBUG_INFO, "got %ld bytes: %s\n", total, input);
	if (!mod_xmlrpc_server_parse(registry, input, total, &output))
		return HTTP_INTERNAL_SERVER_ERROR;

	xmlrpc_client_response(r, mod_xmlrpc_result_size(&output),
			mod_xmlrpc_result_contents(&output));
	DPRINTF(DEBUG_INFO, "sent %zd bytes: ", mod_xmlrpc_result_size(&output));
	DWRITE(DEBUG_INFO, mod_xmlrpc_result_contents(&output),
			mod_xmlrpc_result_size(&output));
	DPRINTF(DEBUG_INFO, "\n");

	mod_xmlrpc_result_free(&output);

	return OK;
}

static const command_rec mod_xmlrpc_cmds[] =
{
	AP_INIT_TAKE1("XMLRPCDebug", mod_xmlrpc_debug, NULL, RSRC_CONF,
			"Usage: XMLRPCDebug <number>"),
#ifdef SUPPORT_C
	AP_INIT_TAKE1("XMLRPCServerPath", c_set_xmlrpc_dir, NULL, RSRC_CONF,
			"Usage: XMLRPCServerPath <Directory>"),
#endif
#ifdef SUPPORT_RUBY
	AP_INIT_TAKE1("XMLRPCServerPathRuby", rb_set_xmlrpc_dir, NULL,
			RSRC_CONF, "Usage: XMLRPCServerPathRuby <Directory>"),
#endif
	{NULL}
};

static void xmlrpc_register_hooks(apr_pool_t *p)
{
	ap_hook_handler(xmlrpc_handler, NULL, NULL, APR_HOOK_MIDDLE);
}

module AP_MODULE_DECLARE_DATA xmlrpc_module =
{
	STANDARD20_MODULE_STUFF,
	NULL,			/* create dir config */
	NULL,			/* merge dir config */
	create_xmlrpc_config,	/* create server config */
	NULL,			/* merge server config */
	mod_xmlrpc_cmds,	/* command handler */
	xmlrpc_register_hooks,	/* registering hooks */
};