On Fri, Dec 02, 2022 at 03:17:05PM +0000, Joe Orton wrote:
> I think this might need to do something more complex, maybe running the
> PROPFIND in a subrequest properly and capturing (buffering) the output
> in a custom filter, rather than using the mod_dav internal API directly.
> Have you tried using ap_sub_req_method_uri()? Not sure this has been
> tried before with mod_dav so might well be something I'm missing.
I did it the way you suggested. The patch gets huge, I just send the
reelvant bits. Does it looks good to you?
In register_hooks() I have
ap_register_output_filter("DAV_MSEXT_OUT", dav_msext_output, NULL,
AP_FTYPE_RESOURCE);
Then:
static apr_status_t dav_msext_output(ap_filter_t *f,
apr_bucket_brigade *bb)
{
apr_bucket_brigade *bbsub = f->ctx;
apr_bucket *b;
b = APR_BRIGADE_FIRST(bb);
while (b != APR_BRIGADE_SENTINEL(bb)) {
apr_bucket *nb;
if (APR_BUCKET_IS_EOS(b))
break;
nb = APR_BUCKET_NEXT(b);
APR_BUCKET_REMOVE(b);
APR_BRIGADE_INSERT_TAIL(bbsub, b);
b = nb;
}
return ap_pass_brigade(f->next, bb);
}
static void dav_msdavext_combined_propfind(request_rec *r)
{
apr_bucket_brigade *bbsub;
apr_bucket_brigade *bb;
ap_filter_t *f;
apr_bucket *b;
request_rec *rr = NULL;
apr_off_t length;
bbsub = apr_brigade_create(r->pool, r->output_filters->c->bucket_alloc);
rr = ap_sub_req_method_uri("PROPFIND", r->uri, r, r->output_filters);
if (!rr || rr->status != HTTP_OK)
goto out;
f = ap_add_output_filter("DAV_MSEXT_OUT", bbsub, rr, rr->connection);
if (!f)
goto out;
if (ap_run_sub_req(rr) != OK)
goto out;
ap_remove_output_filter(f);
if (apr_brigade_length(bbsub, 1, &length) != APR_SUCCESS)
goto out;
bb = apr_brigade_create(r->pool,r->output_filters->c->bucket_alloc);
apr_brigade_printf(bb, NULL, NULL,
"%016" APR_UINT64_T_HEX_FMT, length);
APR_BRIGADE_CONCAT(bb, bbsub);
ap_destroy_sub_req(rr);
rr = NULL;
rr = ap_sub_req_lookup_uri(r->uri, r, r->output_filters);
if (!rr || rr->status != HTTP_OK || rr->filename == NULL ||
rr->finfo.filetype != APR_REG)
goto out;
apr_brigade_printf(bb, NULL, NULL,
"%016" APR_UINT64_T_HEX_FMT, rr->finfo.size);
ap_set_content_type(r, "multipart/MSDAVEXTPrefixEncoded");
ap_pass_brigade(r->output_filters, bb);
/* plain GET rocessing happens afterward */
out:
if (rr)
ap_destroy_sub_req(rr);
return;
}
--
Emmanuel Dreyfus
[email protected]