Commit c9706ffb authored by otmar's avatar otmar
Browse files

Version 1.10.

* Bugfix:
        - the xmlcgi input filter would potentially return more data
          than the downstream filter asked for. This seems to be
          fine for some backends, but php5 croaks on this.

          Fixed by using a temporary bucket-brigade.

The debugging for version 1.10 was sponsored by CentralNic.
parent 8e14629b
# gdb macros which may be useful for folks using gdb to debug
# apache. Delete it if it bothers you.
set history filename ~/.gdb_history
set history save
define dump_table
set $t = (apr_table_entry_t *)((apr_array_header_t *)$arg0)->elts
set $n = ((apr_array_header_t *)$arg0)->nelts
set $i = 0
while $i < $n
if $t[$i].val == (void *)0L
printf "[%u] '%s'=>NULL\n", $i, $t[$i].key
else
printf "[%u] '%s'='%s'\n", $i, $t[$i].key, $t[$i].val
end
set $i = $i + 1
end
end
document dump_table
Print the key/value pairs in a table.
end
define rh
run -X -e debug
end
define ro
run -DONE_PROCESS
end
define dump_string_array
set $a = (char **)((apr_array_header_t *)$arg0)->elts
set $n = (int)((apr_array_header_t *)$arg0)->nelts
set $i = 0
while $i < $n
printf "[%u] '%s'\n", $i, $a[$i]
set $i = $i + 1
end
end
document dump_string_array
Print all of the elements in an array of strings.
end
define printmemn
set $i = 0
while $i < $arg1
if $arg0[$i] < 0x20 || $arg0[$i] > 0x7e
printf "~"
else
printf "%c", $arg0[$i]
end
set $i = $i + 1
end
end
define print_bkt_datacol
# arg0 == column name
# arg1 == format
# arg2 == value
# arg3 == suppress header?
set $suppressheader = $arg3
if !$suppressheader
printf " "
printf $arg0
printf "="
else
printf " | "
end
printf $arg1, $arg2
end
define dump_bucket_ex
# arg0 == bucket
# arg1 == suppress header?
set $bucket = (struct apr_bucket *)$arg0
set $sh = $arg1
set $refcount = -1
print_bkt_datacol "bucket" "%-9s" $bucket->type->name $sh
printf "(0x%08lx)", (unsigned long)$bucket
print_bkt_datacol "length" "%-6ld" (long)($bucket->length) $sh
print_bkt_datacol "data" "0x%08lx" $bucket->data $sh
if !$sh
printf "\n "
end
if (($bucket->type == &apr_bucket_type_eos) || \
($bucket->type == &apr_bucket_type_flush))
# metadata buckets, no content
print_bkt_datacol "contents" "%c" ' ' $sh
printf " "
print_bkt_datacol "rc" "n/%c" 'a' $sh
else
if ($bucket->type == &ap_bucket_type_error)
# metadata bucket, no content but it does have an error code in it
print_bkt_datacol "contents" "%c" ' ' $sh
set $status = ((ap_bucket_error *)$bucket->data)->status
printf " (status=%3d) ", $status
print_bkt_datacol "rc" "n/%c" 'a' $sh
else
if (($bucket->type == &apr_bucket_type_file) || \
($bucket->type == &apr_bucket_type_pipe) || \
($bucket->type == &apr_bucket_type_socket))
# buckets that contain data not in memory (ie not printable)
print_bkt_datacol "contents" "[**unprintable**%c" ']' $sh
printf " "
if $bucket->type == &apr_bucket_type_file
set $refcount = ((apr_bucket_refcount *)$bucket->data)->refcount
print_bkt_datacol "rc" "%d" $refcount $sh
end
else
if (($bucket->type == &apr_bucket_type_heap) || \
($bucket->type == &apr_bucket_type_pool) || \
($bucket->type == &apr_bucket_type_mmap) || \
($bucket->type == &apr_bucket_type_transient) || \
($bucket->type == &apr_bucket_type_immortal))
# in-memory buckets
if $bucket->type == &apr_bucket_type_heap
set $refcount = ((apr_bucket_refcount *)$bucket->data)->refcount
set $p = (apr_bucket_heap *)$bucket->data
set $data = $p->base+$bucket->start
else
if $bucket->type == &apr_bucket_type_pool
set $refcount = ((apr_bucket_refcount *)$bucket->data)->refcount
set $p = (apr_bucket_pool *)$bucket->data
if !$p->pool
set $p = (apr_bucket_heap *)$bucket->data
end
set $data = $p->base+$bucket->start
else
if $bucket->type == &apr_bucket_type_mmap
# is this safe if not APR_HAS_MMAP?
set $refcount = ((apr_bucket_refcount *)$bucket->data)->refcount
set $p = (apr_bucket_mmap *)$bucket->data
set $data = ((char *)$p->mmap->mm)+$bucket->start
else
if (($bucket->type == &apr_bucket_type_transient) || \
($bucket->type == &apr_bucket_type_immortal))
set $data = ((char *)$bucket->data)+$bucket->start
end
end
end
end
if $sh
printf " | ["
else
printf " contents=["
end
set $datalen = $bucket->length
if $datalen > 17
printmem $data 17
printf "..."
set $datalen = 20
else
printmemn $data $datalen
end
printf "]"
while $datalen < 20
printf " "
set $datalen = $datalen + 1
end
if $refcount != -1
print_bkt_datacol "rc" "%d" $refcount $sh
else
print_bkt_datacol "rc" "n/%c" 'a' $sh
end
else
# 3rd-party bucket type
print_bkt_datacol "contents" "[**unknown**%c" ']' $sh
printf " "
print_bkt_datacol "rc" "n/%c" 'a' $sh
end
end
end
end
printf "\n"
end
define dump_bucket
dump_bucket_ex $arg0 0
end
document dump_bucket
Print bucket info
end
define dump_brigade
set $bb = (apr_bucket_brigade *)$arg0
set $bucket = $bb->list.next
set $sentinel = ((char *)((&($bb->list)) \
- ((size_t) &((struct apr_bucket *)0)->link)))
printf "dump of brigade 0x%lx\n", (unsigned long)$bb
printf " | type (address) | length | "
printf "data addr | contents | rc\n"
printf "----------------------------------------"
printf "----------------------------------------\n"
if $bucket == $sentinel
printf "brigade is empty\n"
end
set $j = 0
while $bucket != $sentinel
printf "%2d", $j
dump_bucket_ex $bucket 1
set $j = $j + 1
set $bucket = $bucket->link.next
end
printf "end of brigade\n"
end
document dump_brigade
Print bucket brigade info
end
define dump_filters
set $f = $arg0
while $f
printf "%s(0x%lx): ctx=0x%lx, r=0x%lx, c=0x%lx\n", \
$f->frec->name, (unsigned long)$f, (unsigned long)$f->ctx, \
$f->r, $f->c
set $f = $f->next
end
end
document dump_filters
Print filter chain info
end
define dump_process_rec
set $p = $arg0
printf "process_rec=0x%lx:\n", (unsigned long)$p
printf " pool=0x%lx, pconf=0x%lx\n", \
(unsigned long)$p->pool, (unsigned long)$p->pconf
end
document dump_process_rec
Print process_rec info
end
define dump_server_rec
set $s = $arg0
printf "name=%s:%d\n", \
$s->server_hostname, $s->port
dump_process_rec($s->process)
end
document dump_server_rec
Print server_rec info
end
define dump_servers
set $s = $arg0
while $s
dump_server_rec($s)
printf "\n"
set $s = $s->next
end
end
document dump_servers
Print server_rec list info
end
1.10 (November 2013)
* Bugfix:
- the xmlcgi input filter would potentially return more data
than the downstream filter asked for. This seems to be
fine for some backends, but php5 croaks on this.
Fixed by using a temporary bucket-brigade.
The debugging for version 1.10 was sponsored by CentralNic.
1.9: (August 2012)
* Bugfix:
......
......@@ -13,8 +13,8 @@ This is *not* a full implementation of EPP, this module just makes it
possible to write an EPP server as a set of CGI scripts.
The homepage of this software is https://sourceforge.net/projects/aepps/
where you can find the latest version. This is version 1.9, released
in August 2012.
where you can find the latest version. This is version 1.10, released
in November 2013.
RATIONALE
......@@ -70,7 +70,7 @@ header files!).
Unpack the distribution and run:
apxs -a -c -i mod_epp.c
apxs2 -a -c -i mod_epp.c
The -a should put something like
......@@ -78,7 +78,7 @@ LoadModule epp_module modules/mod_epp.so
into your httpd.conf file to load the module.
See the man page of apxs (part of the Apache 2.x httpd distribution)
See the man page of apxs2 (part of the Apache 2.x httpd distribution)
or http://www.onlamp.com/topics/apache/apache_modules for further
information on compiling and installing Apache modules.
......@@ -109,6 +109,9 @@ Apache 2.2.15. Version 1.9 made mod_epp compatible with Apache 2.2.22.
don't start the connection handler until the first bytes are received
from the client. That's fine for HTTP, but not EPP. See below.)
As all versions since 1.7 were developed for Apache 2.2.x, support for
Apache 2.0.x might have been broken.
CONFIGURATION
-------------
......@@ -452,13 +455,21 @@ mod_epp is doing, run apache like this:
httpd -e debug -X
When using gdb, make sure that you use the .gdbinit file that comes with the
apache 2.x source code. The "dump_bucket" and "dump_brigade" macros defined in
there are *really* helpful.
apache 2.x source code and mod_epp. The "dump_bucket" and "dump_brigade"
macros defined in there are *really* helpful.
To build a httpd with debugging symbols, use
CFLAGS='-g' ./configure --with-included-apr --enable-proxy-http --enable-proxy
in the httpd source tree.
For debugging under Debian use
export DEB_BUILD_OPTIONS="debug nostrip noopt"
dpkg-buildpackage -us -uc
to build the Apache packages. The debugging options might not be picked up
by apxs2, so you might want to use "apxs2 -c -i -Wc,-O0 -Wc,-g mod_epp.c"
to force this.
AUTHOR
------
......@@ -469,6 +480,7 @@ Version 1.6 was sponsored by SIDN.
Version 1.7 was sponsored by CentralNic.
Version 1.8 was sponsored by SIDN.
Version 1.9 was sponsored by CentralNic.
Version 1.10 was sponsored by CentralNic.
LICENCE
-------
......
......@@ -713,6 +713,40 @@ apr_xml_to_text(r->pool,doc->root,APR_XML_X2T_FULL_NS_LANG, doc->namespaces ,NUL
er->serialised_xml_size = strlen(er->serialised_xml);
ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, NULL,
"XML: serialized xml size = %lu.", (unsigned long) er->serialised_xml_size);
/*
* Create the multipart/formdata MIME structure for the request
* as the downstream filter might not want to get all of it at once,
* we put it in a temporary bucket-brigade. The input filter will then
* hand off data in the desired chunks.
*/
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0 , NULL,
"epp_process_frame: creating the multipart/form-data (framesize: %lu)", er->serialised_xml_size);
er->bb_formdata = apr_brigade_create(r->pool, r->connection->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(er->bb_formdata, apr_bucket_immortal_create(EPP_CONTENT_FRAME_CGI,
strlen(EPP_CONTENT_FRAME_CGI), r->connection->bucket_alloc));
APR_BRIGADE_INSERT_TAIL(er->bb_formdata, apr_bucket_pool_create(er->serialised_xml,er->serialised_xml_size,
r->pool,r->connection->bucket_alloc));
if (conf->raw_frame) {
APR_BRIGADE_INSERT_TAIL(er->bb_formdata, apr_bucket_immortal_create(conf->raw_frame,
strlen(conf->raw_frame), r->connection->bucket_alloc));
APR_BRIGADE_INSERT_TAIL(er->bb_formdata, apr_bucket_pool_create(er->orig_xml,er->orig_xml_size,
r->pool,r->connection->bucket_alloc));
}
APR_BRIGADE_INSERT_TAIL(er->bb_formdata, apr_bucket_immortal_create(EPP_CONTENT_CLTRID_CGI,
strlen(EPP_CONTENT_CLTRID_CGI), r->connection->bucket_alloc));
APR_BRIGADE_INSERT_TAIL(er->bb_formdata, apr_bucket_pool_create(er->cltrid,strlen(er->cltrid),
r->pool,r->connection->bucket_alloc));
APR_BRIGADE_INSERT_TAIL(er->bb_formdata, apr_bucket_immortal_create(EPP_CONTENT_POSTFIX_CGI,
strlen(EPP_CONTENT_POSTFIX_CGI), r->connection->bucket_alloc));
APR_BRIGADE_INSERT_TAIL(er->bb_formdata, apr_bucket_eos_create(r->connection->bucket_alloc));
/* fixme, perhap use apr_brigade_length */
sprintf(content_length, "%lu", strlen(EPP_CONTENT_FRAME_CGI)
+ strlen(EPP_CONTENT_CLTRID_CGI)
+ strlen(er->cltrid)
......@@ -1279,30 +1313,48 @@ static apr_status_t epp_xmlcgi_filter(ap_filter_t *f, apr_bucket_brigade *bb,
{
epp_rec *er = f->ctx;
epp_conn_rec *conf = er->ur->conf;
apr_off_t bytes_left;
apr_status_t rv;
apr_bucket *e_keepthis, *e;
if (er->serialised_xml_size > 0)
{
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create(EPP_CONTENT_FRAME_CGI,
strlen(EPP_CONTENT_FRAME_CGI), f->r->connection->bucket_alloc));
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(er->serialised_xml,er->serialised_xml_size,
f->r->pool,f->r->connection->bucket_alloc));
if (conf->raw_frame) {
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create(conf->raw_frame,
strlen(conf->raw_frame), f->r->connection->bucket_alloc));
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(er->orig_xml,er->orig_xml_size,
f->r->pool,f->r->connection->bucket_alloc));
}
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create(EPP_CONTENT_CLTRID_CGI,
strlen(EPP_CONTENT_CLTRID_CGI), f->r->connection->bucket_alloc));
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_pool_create(er->cltrid,strlen(er->cltrid),
f->r->pool,f->r->connection->bucket_alloc));
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_immortal_create(EPP_CONTENT_POSTFIX_CGI,
strlen(EPP_CONTENT_POSTFIX_CGI), f->r->connection->bucket_alloc));
er->serialised_xml_size = 0; /* don't send content twice if called twice. */
}
APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(f->r->connection->bucket_alloc));
return APR_SUCCESS;
/*
* how much data do we have left in the bb_formdata brigade?
*/
apr_brigade_length(er->bb_formdata,1,&bytes_left);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0 , NULL,
"epp_xmlcgi_filter: %lu bytes left in bb_formdata", bytes_left);
/*
* simple case: we have data, but no more that requested
*/
if ((bytes_left <= readbytes) && (bytes_left > 0)) {
APR_BRIGADE_PREPEND(bb,er->bb_formdata);
return(APR_SUCCESS);
}
/*
* next easy case: no more data left
*/
if (bytes_left == 0) {
/* APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(f->r->connection->bucket_alloc)); */
return(AP_NOBODY_READ);
/* FIXME: not sure about the error-code */
}
/*
* now the tricky case: we cannot hand over the full brigade. Perhaps we even
* need to split individual buckets.
*/
rv = apr_brigade_partition(er->bb_formdata, readbytes, &e_keepthis);
while((e = APR_BRIGADE_FIRST(er->bb_formdata)) != e_keepthis) {
APR_BUCKET_REMOVE(e);
APR_BRIGADE_INSERT_TAIL(bb, e);
}
return APR_SUCCESS;
}
......
......@@ -116,7 +116,7 @@ module AP_MODULE_DECLARE_DATA epp_module;
/*
* Use the following as HTTP User-agent
*/
#define EPP_USER_AGENT "mod_epp/1.8 +https://sourceforge.net/projects/aepps/"
#define EPP_USER_AGENT "mod_epp/1.10 +https://sourceforge.net/projects/aepps/"
/*
......@@ -173,6 +173,7 @@ typedef struct epp_rec {
request_rec *r;
apr_bucket_brigade *bb_out;
apr_bucket_brigade *bb_tmp;
apr_bucket_brigade *bb_formdata;
const char *serialised_xml;
apr_size_t serialised_xml_size;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment