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