예제 #1
0
/* Implements the #register_hooks method of Apache's #module vtable. */
static void
register_hooks(apr_pool_t *pconf)
{
  ap_hook_pre_config(init_dso, NULL, NULL, APR_HOOK_REALLY_FIRST);
  ap_hook_post_config(init, NULL, NULL, APR_HOOK_MIDDLE);

  /* our provider */
  dav_register_provider(pconf, "svn", &provider);

  /* input filter to read MERGE bodies. */
  ap_register_input_filter("SVN-MERGE", merge_xml_in_filter, NULL,
                           AP_FTYPE_RESOURCE);
  ap_hook_insert_filter(merge_xml_filter_insert, NULL, NULL,
                        APR_HOOK_MIDDLE);

  /* general request handler for methods which mod_dav DECLINEs. */
  ap_hook_handler(dav_svn__handler, NULL, NULL, APR_HOOK_LAST);

  /* live property handling */
  dav_hook_gather_propsets(dav_svn__gather_propsets, NULL, NULL,
                           APR_HOOK_MIDDLE);
  dav_hook_find_liveprop(dav_svn__find_liveprop, NULL, NULL, APR_HOOK_MIDDLE);
  dav_hook_insert_all_liveprops(dav_svn__insert_all_liveprops, NULL, NULL,
                                APR_HOOK_MIDDLE);
  dav_register_liveprop_group(pconf, &dav_svn__liveprop_group);

  /* Proxy / mirroring filters and fixups */
  ap_register_output_filter("LocationRewrite", dav_svn__location_header_filter,
                            NULL, AP_FTYPE_CONTENT_SET);
  ap_register_output_filter("ReposRewrite", dav_svn__location_body_filter,
                            NULL, AP_FTYPE_CONTENT_SET);
  ap_register_input_filter("IncomingRewrite", dav_svn__location_in_filter,
                           NULL, AP_FTYPE_CONTENT_SET);
  ap_hook_fixups(dav_svn__proxy_request_fixup, NULL, NULL, APR_HOOK_MIDDLE);
}
예제 #2
0
void h2_task_register_hooks(void)
{
    /* This hook runs on new connections before mod_ssl has a say.
     * Its purpose is to prevent mod_ssl from touching our pseudo-connections
     * for streams.
     */
    ap_hook_pre_connection(h2_task_pre_conn,
                           NULL, mod_ssl, APR_HOOK_FIRST);
    /* When the connection processing actually starts, we might 
     * take over, if the connection is for a task.
     */
    ap_hook_process_connection(h2_task_process_conn, 
                               NULL, NULL, APR_HOOK_FIRST);

    ap_register_input_filter("H2_SLAVE_IN", h2_filter_slave_in,
                             NULL, AP_FTYPE_NETWORK);
    ap_register_output_filter("H2_SLAVE_OUT", h2_filter_slave_output,
                              NULL, AP_FTYPE_NETWORK);
    ap_register_output_filter("H2_PARSE_H1", h2_filter_parse_h1,
                              NULL, AP_FTYPE_NETWORK);

    ap_register_input_filter("H2_REQUEST", h2_filter_request_in,
                             NULL, AP_FTYPE_PROTOCOL);
    ap_register_output_filter("H2_RESPONSE", h2_filter_headers_out,
                              NULL, AP_FTYPE_PROTOCOL);
    ap_register_output_filter("H2_TRAILERS_OUT", h2_filter_trailers_out,
                              NULL, AP_FTYPE_PROTOCOL);
}
static void upload_hooks(apr_pool_t* p) {

  ap_register_input_filter("tmpfile-filter", tmpfile_filter,
		NULL, AP_FTYPE_RESOURCE) ;
  ap_register_input_filter("upload-filter", upload_filter,
		upload_filter_init, AP_FTYPE_RESOURCE) ;

} ;
예제 #4
0
파일: h2_task.c 프로젝트: AzerTyQsdF/osx
void h2_task_register_hooks(void)
{
    /* This hook runs on new connections before mod_ssl has a say.
     * Its purpose is to prevent mod_ssl from touching our pseudo-connections
     * for streams.
     */
    ap_hook_pre_connection(h2_task_pre_conn,
                           NULL, mod_ssl, APR_HOOK_FIRST);
    /* When the connection processing actually starts, we might to
     * take over, if the connection is for a task.
     */
    ap_hook_process_connection(h2_task_process_conn, 
                               NULL, NULL, APR_HOOK_FIRST);

    ap_register_output_filter("H2_RESPONSE", h2_response_output_filter,
                              NULL, AP_FTYPE_PROTOCOL);
    ap_register_input_filter("H2_TO_H1", h2_filter_stream_input,
                             NULL, AP_FTYPE_NETWORK);
    ap_register_output_filter("H1_TO_H2", h2_filter_stream_output,
                              NULL, AP_FTYPE_NETWORK);
    ap_register_output_filter("H1_TO_H2_RESP", h2_filter_read_response,
                              NULL, AP_FTYPE_PROTOCOL);
    ap_register_output_filter("H2_TRAILERS", h2_response_trailers_filter,
                              NULL, AP_FTYPE_PROTOCOL);
}
예제 #5
0
static void CaseFilterInRegisterHooks(apr_pool_t *p)
{
    ap_hook_insert_filter(CaseFilterInInsertFilter, NULL, NULL,
                          APR_HOOK_MIDDLE);
    ap_register_input_filter(s_szCaseFilterName, CaseFilterInFilter, NULL,
                             AP_FTYPE_RESOURCE);
}
예제 #6
0
static void register_hooks(apr_pool_t *p)
{
    ap_hook_post_config(http_post_config, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_process_connection(ap_process_http_connection, NULL, NULL,
                               APR_HOOK_REALLY_LAST);
    ap_hook_map_to_storage(ap_send_http_trace,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_map_to_storage(http_send_options,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_http_scheme(http_scheme,NULL,NULL,APR_HOOK_REALLY_LAST);
    ap_hook_default_port(http_port,NULL,NULL,APR_HOOK_REALLY_LAST);
    ap_hook_create_request(http_create_request, NULL, NULL, APR_HOOK_REALLY_LAST);
    ap_http_input_filter_handle =
        ap_register_input_filter("HTTP_IN", ap_http_filter,
                                 NULL, AP_FTYPE_PROTOCOL);
    ap_http_header_filter_handle =
        ap_register_output_filter("HTTP_HEADER", ap_http_header_filter,
                                  NULL, AP_FTYPE_PROTOCOL);
    ap_chunk_filter_handle =
        ap_register_output_filter("CHUNK", ap_http_chunk_filter,
                                  NULL, AP_FTYPE_TRANSCODE);
    ap_http_outerror_filter_handle =
        ap_register_output_filter("HTTP_OUTERROR", ap_http_outerror_filter,
                                  NULL, AP_FTYPE_PROTOCOL);
    ap_byterange_filter_handle =
        ap_register_output_filter("BYTERANGE", ap_byterange_filter,
                                  NULL, AP_FTYPE_PROTOCOL);
    ap_method_registry_init(p);
}
예제 #7
0
static void
 akismet_register_hooks(apr_pool_t *p)
{
    ap_hook_post_config(akismet_post_config, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_child_init(akismet_child_init, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_insert_filter(akismet_insert_filter, NULL, NULL, APR_HOOK_MIDDLE);
    ap_register_input_filter(akismet_filter_name, akismet_filter, NULL, AP_FTYPE_RESOURCE);
}
static void upload_progress_register_hooks (apr_pool_t *p)
{
  ap_hook_fixups(upload_progress_handle_request, NULL, NULL, APR_HOOK_FIRST);
  ap_hook_handler(reportuploads_handler, NULL, NULL, APR_HOOK_FIRST);
  ap_hook_post_config(upload_progress_init, NULL, NULL, APR_HOOK_MIDDLE);
  ap_hook_child_init(upload_progress_child_init, NULL, NULL, APR_HOOK_MIDDLE);
  ap_register_input_filter("UPLOAD_PROGRESS", track_upload_progress, NULL, AP_FTYPE_RESOURCE);
}
예제 #9
0
/**
 * @internal
 *
 * Register functions to handle filters and hooks.
 */
static void ironbee_register_hooks(apr_pool_t *p)
{
    /* Other modules:
     *   mod_ssl       = AP_FTYPE_CONNECTION + 5
     *   mod_expires   = AP_FTYPE_CONTENT_SET - 2
     *   mod_cache     = AP_FTYPE_CONTENT_SET - 1
     *   mod_deflate   = AP_FTYPE_CONTENT_SET - 1
     *   mod_headers   = AP_FTYPE_CONTENT_SET
     */

    ap_register_input_filter(
        "IRONBEE_IN",
        ironbee_input_filter,
        NULL,
        AP_FTYPE_CONNECTION + 1
    );

#ifdef IB_DEBUG
    ap_register_input_filter(
        "IRONBEE_DBG_IN",
        ironbee_dbg_input_filter,
        NULL,
        AP_FTYPE_CONNECTION
    );
#endif

    ap_register_output_filter(
        "IRONBEE_OUT",
        ironbee_output_filter,
        NULL,
        AP_FTYPE_CONNECTION
    );

    ap_hook_child_init(ironbee_child_init,
                       NULL, NULL,
                       APR_HOOK_FIRST);

    ap_hook_post_config(ironbee_post_config,
                        NULL, NULL,
                        APR_HOOK_MIDDLE);

    ap_hook_pre_connection(ironbee_pre_connection,
                           NULL, NULL,
                           APR_HOOK_LAST);
}
예제 #10
0
static void charset_register_hooks(apr_pool_t *p)
{
    ap_hook_fixups(find_code_page, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_insert_filter(xlate_insert_filter, NULL, NULL, APR_HOOK_REALLY_LAST);
    ap_register_output_filter(XLATEOUT_FILTER_NAME, xlate_out_filter, NULL,
                              AP_FTYPE_RESOURCE);
    ap_register_input_filter(XLATEIN_FILTER_NAME, xlate_in_filter, NULL,
                             AP_FTYPE_RESOURCE);
}
예제 #11
0
/* Implements the #register_hooks method of Apache's #module vtable. */
static void
register_hooks(apr_pool_t *pconf)
{
  ap_hook_pre_config(init_dso, NULL, NULL, APR_HOOK_REALLY_FIRST);
  ap_hook_post_config(init, NULL, NULL, APR_HOOK_MIDDLE);

  /* our provider */
  dav_register_provider(pconf, "svn", &provider);

  /* input filter to read MERGE bodies. */
  ap_register_input_filter("SVN-MERGE", merge_xml_in_filter, NULL,
                           AP_FTYPE_RESOURCE);
  ap_hook_insert_filter(merge_xml_filter_insert, NULL, NULL,
                        APR_HOOK_MIDDLE);

  /* general request handler for methods which mod_dav DECLINEs. */
  ap_hook_handler(dav_svn__handler, NULL, NULL, APR_HOOK_LAST);

  /* Handler to GET Subversion's FSFS cache stats, a bit like mod_status. */
  ap_hook_handler(dav_svn__status, NULL, NULL, APR_HOOK_MIDDLE);

  /* live property handling */
  dav_hook_gather_propsets(dav_svn__gather_propsets, NULL, NULL,
                           APR_HOOK_MIDDLE);
  dav_hook_find_liveprop(dav_svn__find_liveprop, NULL, NULL, APR_HOOK_MIDDLE);
  dav_hook_insert_all_liveprops(dav_svn__insert_all_liveprops, NULL, NULL,
                                APR_HOOK_MIDDLE);
  dav_register_liveprop_group(pconf, &dav_svn__liveprop_group);

  /* Proxy / mirroring filters and fixups */
  ap_register_output_filter("LocationRewrite", dav_svn__location_header_filter,
                            NULL, AP_FTYPE_CONTENT_SET);
  ap_register_output_filter("ReposRewrite", dav_svn__location_body_filter,
                            NULL, AP_FTYPE_CONTENT_SET);
  ap_register_input_filter("IncomingRewrite", dav_svn__location_in_filter,
                           NULL, AP_FTYPE_CONTENT_SET);
  ap_hook_fixups(dav_svn__proxy_request_fixup, NULL, NULL, APR_HOOK_MIDDLE);
  /* translate_name hook is LAST so that it doesn't interfere with modules
   * like mod_alias that are MIDDLE. */
  ap_hook_translate_name(dav_svn__translate_name, NULL, NULL, APR_HOOK_LAST);
  /* map_to_storage hook is LAST to avoid interferring with mod_http's
   * handling of OPTIONS and TRACE. */
  ap_hook_map_to_storage(dav_svn__map_to_storage, NULL, NULL, APR_HOOK_LAST);
}
예제 #12
0
파일: mod_sslhaf.c 프로젝트: Ath103/sslhaf
/**
 * Main entry point.
 */
static void mod_sslhaf_register_hooks(apr_pool_t *p) {
    static const char * const afterme[] = { "mod_security2.c", NULL };

    ap_hook_pre_connection(mod_sslhaf_pre_conn, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_post_read_request(mod_sslhaf_post_request, NULL, afterme, APR_HOOK_REALLY_FIRST);

    ap_register_input_filter(mod_sslhaf_in_filter_name, mod_sslhaf_in_filter,
        NULL, AP_FTYPE_NETWORK - 1);
    ap_register_output_filter(mod_sslhaf_out_filter_name, mod_sslhaf_out_filter,
        NULL, AP_FTYPE_NETWORK - 1);
}
예제 #13
0
파일: h2_task.c 프로젝트: ikyaqoob/mod_h2
void h2_task_register_hooks(void)
{
    ap_register_output_filter("H2_RESPONSE", h2_response_output_filter,
                              NULL, AP_FTYPE_PROTOCOL);
    ap_register_input_filter("H2_TO_H1", h2_filter_stream_input,
                             NULL, AP_FTYPE_NETWORK);
    ap_register_output_filter("H1_TO_H2", h2_filter_stream_output,
                              NULL, AP_FTYPE_NETWORK);
    ap_register_output_filter("H1_TO_H2_RESP", h2_filter_read_response,
                              NULL, AP_FTYPE_PROTOCOL);
}
예제 #14
0
파일: agent.c 프로젝트: JonathanFu/OpenAM-1
static void amagent_register_hooks(apr_pool_t *p) {
#if AP_SERVER_MAJORVERSION_NUMBER == 2 && AP_SERVER_MINORVERSION_NUMBER < 3
    ap_hook_access_checker(amagent_auth_handler, NULL, NULL, APR_HOOK_FIRST);
#else
    ap_hook_check_access_ex(amagent_auth_handler, NULL, NULL, APR_HOOK_FIRST, AP_AUTH_INTERNAL_PER_CONF);
#endif
    ap_hook_post_config(amagent_init, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_child_init(amagent_worker_init, NULL, NULL, APR_HOOK_MIDDLE);

    ap_hook_insert_filter(amagent_auth_post_insert_filter, NULL, NULL, APR_HOOK_REALLY_FIRST);
    ap_register_input_filter(amagent_post_filter_name, amagent_post_filter, NULL, AP_FTYPE_RESOURCE);
}
예제 #15
0
static void dumpio_register_hooks(apr_pool_t *p)
{
/*
 * We know that SSL is CONNECTION + 5
 */
  ap_register_output_filter("DUMPIO_OUT", dumpio_output_filter,
	NULL, AP_FTYPE_CONNECTION + 3) ;

  ap_register_input_filter("DUMPIO_IN", dumpio_input_filter,
	NULL, AP_FTYPE_CONNECTION + 3) ;

  ap_hook_pre_connection(dumpio_pre_conn, NULL, NULL, APR_HOOK_MIDDLE);
}
static void register_hooks(apr_pool_t *p)
{
    static const char *pre[] = { "mod_log_config.c", NULL };

    ap_hook_pre_connection(logio_pre_conn, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_pre_config(logio_pre_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
    ap_hook_log_transaction(logio_transaction, pre, NULL, APR_HOOK_MIDDLE);

    ap_register_input_filter(logio_filter_name, logio_in_filter, NULL,
                             AP_FTYPE_NETWORK - 1);

    APR_REGISTER_OPTIONAL_FN(ap_logio_add_bytes_out);
    APR_REGISTER_OPTIONAL_FN(ap_logio_add_bytes_in);
    APR_REGISTER_OPTIONAL_FN(ap_logio_get_last_bytes);
}
예제 #17
0
static void register_hooks (apr_pool_t *p)
{
    /* APR_HOOK_FIRST because we want other modules to be able to
     * register parsers in their post_config hook via APR_HOOK_MIDDLE.
     */
    ap_hook_post_config(apreq_pre_init, NULL, NULL, APR_HOOK_FIRST);

    /* APR_HOOK_LAST because we need to lock the default_parsers hash
     * (to prevent further modifications) before the server forks.
     */
    ap_hook_post_config(apreq_post_init, NULL, NULL, APR_HOOK_LAST);

    ap_register_input_filter(APREQ_FILTER_NAME, apreq_filter, apreq_filter_init,
                             AP_FTYPE_PROTOCOL-1);
}
예제 #18
0
/**
 * Registers the hooks for this module.
 *
 * @param p the pool to allocate from, if necessary.
 */
static void fsp_register_hooks(apr_pool_t* p)
{
   // registers the pre-connection hook to handle adding filters
   ap_hook_pre_connection(
      fsp_pre_connection, NULL, NULL, APR_HOOK_MIDDLE);

   // will parse a policy file request, to be added in pre_connection
   ap_register_input_filter(
      "fsp_request", fsp_input_filter,
      NULL, AP_FTYPE_CONNECTION);

   // will emit a cross-domain policy response to be added in pre_connection
   ap_register_output_filter(
      "fsp_response", fsp_output_filter,
      NULL, AP_FTYPE_CONNECTION);
}
예제 #19
0
static void register_hooks(apr_pool_t *p)
{
    static const char *const postread_afterme_list[] = {
        "mod_security2.c",
        NULL
    };

    /*
     * mod_ssl is AP_FTYPE_CONNECTION + 5 and mod_myfixip needs to
     * be called before mod_ssl.
     */
    ap_register_input_filter(myfixip_filter_name, helocon_filter_in, NULL, AP_FTYPE_CONNECTION + 9);
    ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_child_init(child_init, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_pre_connection(pre_connection, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_post_read_request(post_read_handler, NULL, postread_afterme_list, APR_HOOK_REALLY_FIRST);
}
예제 #20
0
/*
 * Register additional hooks.
 */
static void
but_register_hooks(apr_pool_t *p)
{
	static const char * const cfgPost[] = { "http_core.c", NULL };

	ap_hook_post_config(but_post_config, NULL, cfgPost, APR_HOOK_MIDDLE);
	ap_hook_child_init(but_child_init, NULL, NULL, APR_HOOK_MIDDLE);
	ap_hook_access_checker(but_access_checker, NULL, NULL, APR_HOOK_FIRST);

#if 0
	ap_register_input_filter("MOD_BUT_IN", mod_but_input_filter, NULL, AP_FTYPE_CONTENT_SET);
	ap_hook_insert_filter(mod_but_insert_input_filter, NULL, NULL, APR_HOOK_FIRST);
#endif

	ap_register_output_filter("MOD_BUT_OUT", but_output_filter, NULL, AP_FTYPE_CONTENT_SET);
	ap_hook_insert_filter(but_insert_output_filter, NULL, NULL, APR_HOOK_LAST);
}
예제 #21
0
파일: h2_conn.c 프로젝트: covener/mod_h2
apr_status_t h2_conn_child_init(apr_pool_t *pool, server_rec *s)
{
    apr_status_t status = APR_SUCCESS;
    int minw, maxw;
    int max_threads_per_child = 0;
    int idle_secs = 0;

    check_modules(1);
    ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads_per_child);
    
    status = ap_mpm_query(AP_MPMQ_IS_ASYNC, &async_mpm);
    if (status != APR_SUCCESS) {
        /* some MPMs do not implemnent this */
        async_mpm = 0;
        status = APR_SUCCESS;
    }

    h2_config_init(pool);
    
    h2_get_num_workers(s, &minw, &maxw);
    
    idle_secs = h2_config_sgeti(s, H2_CONF_MAX_WORKER_IDLE_SECS);
    ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s,
                 "h2_workers: min=%d max=%d, mthrpchild=%d, idle_secs=%d", 
                 minw, maxw, max_threads_per_child, idle_secs);
    workers = h2_workers_create(s, pool, minw, maxw, idle_secs);
 
    ap_register_input_filter("H2_IN", h2_filter_core_input,
                             NULL, AP_FTYPE_CONNECTION);
   
    status = h2_mplx_child_init(pool, s);

    if (status == APR_SUCCESS) {
        status = apr_socket_create(&dummy_socket, APR_INET, SOCK_STREAM,
                                   APR_PROTO_TCP, pool);
    }

    return status;
}
예제 #22
0
static void test_filter_register_hooks(apr_pool_t *p)
{
  ap_register_input_filter("TEST_FILTER", test_input_filter, NULL, AP_FTYPE_RESOURCE);
}
예제 #23
0
파일: h2_conn.c 프로젝트: Sp1l/mod_h2
apr_status_t h2_conn_child_init(apr_pool_t *pool, server_rec *s)
{
    const h2_config *config = h2_config_sget(s);
    apr_status_t status = APR_SUCCESS;
    int minw, maxw, max_tx_handles, n;
    int max_threads_per_child = 0;
    int idle_secs = 0;

    check_modules(1);
    
    ap_mpm_query(AP_MPMQ_MAX_THREADS, &max_threads_per_child);
    
    status = ap_mpm_query(AP_MPMQ_IS_ASYNC, &async_mpm);
    if (status != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_TRACE1, status, s, "querying MPM for async");
        /* some MPMs do not implemnent this */
        async_mpm = 0;
        status = APR_SUCCESS;
    }

    h2_config_init(pool);
    
    minw = h2_config_geti(config, H2_CONF_MIN_WORKERS);
    maxw = h2_config_geti(config, H2_CONF_MAX_WORKERS);    
    if (minw <= 0) {
        minw = max_threads_per_child;
    }
    if (maxw <= 0) {
        maxw = minw;
    }
    
    /* How many file handles is it safe to use for transfer
     * to the master connection to be streamed out? 
     * Is there a portable APR rlimit on NOFILES? Have not
     * found it. And if, how many of those would we set aside?
     * This leads all into a process wide handle allocation strategy
     * which ultimately would limit the number of accepted connections
     * with the assumption of implicitly reserving n handles for every 
     * connection and requiring modules with excessive needs to allocate
     * from a central pool.
     */
    n = h2_config_geti(config, H2_CONF_SESSION_FILES);
    if (n < 0) {
        max_tx_handles = maxw * 2;
    }
    else {
        max_tx_handles = maxw * n;
    }
    
    ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, s,
                 "h2_workers: min=%d max=%d, mthrpchild=%d, tx_files=%d", 
                 minw, maxw, max_threads_per_child, max_tx_handles);
    workers = h2_workers_create(s, pool, minw, maxw, max_tx_handles);
    
    idle_secs = h2_config_geti(config, H2_CONF_MAX_WORKER_IDLE_SECS);
    h2_workers_set_max_idle_secs(workers, idle_secs);
 
    ap_register_input_filter("H2_IN", h2_filter_core_input,
                             NULL, AP_FTYPE_CONNECTION);
   
    status = h2_mplx_child_init(pool, s);
    
    return status;
}
예제 #24
0
static void porter_register_hooks(apr_pool_t *p)
{
  porter_input_filter_handle = ap_register_input_filter("PORTER_INPUT_FILTER", porter_input_filter, NULL, AP_FTYPE_RESOURCE);
  ap_hook_fixups(porter_fixup, NULL, NULL, APR_HOOK_MIDDLE);
}
static const char *define_filter(cmd_parms *cmd, void *dummy, const char *args)
{
    ef_server_t *conf = ap_get_module_config(cmd->server->module_config,
                                             &ext_filter_module);
    const char *token;
    const char *name;
    char *normalized_name;
    ef_filter_t *filter;

    name = ap_getword_white(cmd->pool, &args);
    if (!name) {
        return "Filter name not found";
    }

    /* During request processing, we find information about the filter
     * by looking up the filter name provided by core server in our
     * hash table.  But the core server has normalized the filter
     * name by converting it to lower case.  Thus, when adding the
     * filter to our hash table we have to use lower case as well.
     */
    normalized_name = apr_pstrdup(cmd->pool, name);
    ap_str_tolower(normalized_name);

    if (apr_hash_get(conf->h, normalized_name, APR_HASH_KEY_STRING)) {
        return apr_psprintf(cmd->pool, "ExtFilter %s is already defined",
                            name);
    }

    filter = (ef_filter_t *)apr_pcalloc(conf->p, sizeof(ef_filter_t));
    filter->name = name;
    filter->mode = OUTPUT_FILTER;
    filter->ftype = AP_FTYPE_RESOURCE;
    apr_hash_set(conf->h, normalized_name, APR_HASH_KEY_STRING, filter);

    while (*args) {
        while (apr_isspace(*args)) {
            ++args;
        }

        /* Nasty parsing...  I wish I could simply use ap_getword_white()
         * here and then look at the token, but ap_getword_white() doesn't
         * do the right thing when we have cmd="word word word"
         */
        if (!strncasecmp(args, "preservescontentlength", 22)) {
            token = ap_getword_white(cmd->pool, &args);
            if (!strcasecmp(token, "preservescontentlength")) {
                filter->preserves_content_length = 1;
            }
            else {
                return apr_psprintf(cmd->pool,
                                    "mangled argument `%s'",
                                    token);
            }
            continue;
        }

        if (!strncasecmp(args, "mode=", 5)) {
            args += 5;
            token = ap_getword_white(cmd->pool, &args);
            if (!strcasecmp(token, "output")) {
                filter->mode = OUTPUT_FILTER;
            }
            else if (!strcasecmp(token, "input")) {
                filter->mode = INPUT_FILTER;
            }
            else {
                return apr_psprintf(cmd->pool, "Invalid mode: `%s'",
                                    token);
            }
            continue;
        }

        if (!strncasecmp(args, "ftype=", 6)) {
            args += 6;
            token = ap_getword_white(cmd->pool, &args);
            filter->ftype = atoi(token);
            continue;
        }

        if (!strncasecmp(args, "enableenv=", 10)) {
            args += 10;
            token = ap_getword_white(cmd->pool, &args);
            filter->enable_env = token;
            continue;
        }

        if (!strncasecmp(args, "disableenv=", 11)) {
            args += 11;
            token = ap_getword_white(cmd->pool, &args);
            filter->disable_env = token;
            continue;
        }

        if (!strncasecmp(args, "intype=", 7)) {
            args += 7;
            filter->intype = ap_getword_white(cmd->pool, &args);
            continue;
        }

        if (!strncasecmp(args, "outtype=", 8)) {
            args += 8;
            filter->outtype = ap_getword_white(cmd->pool, &args);
            continue;
        }

        if (!strncasecmp(args, "cmd=", 4)) {
            args += 4;
            if ((token = parse_cmd(cmd->pool, &args, filter))) {
                return token;
            }
            continue;
        }

        return apr_psprintf(cmd->pool, "Unexpected parameter: `%s'",
                            args);
    }

    /* parsing is done...  register the filter
     */
    if (filter->mode == OUTPUT_FILTER) {
        /* XXX need a way to ensure uniqueness among all filters */
        ap_register_output_filter(filter->name, ef_output_filter, NULL, filter->ftype);
    }
    else if (filter->mode == INPUT_FILTER) {
        /* XXX need a way to ensure uniqueness among all filters */
        ap_register_input_filter(filter->name, ef_input_filter, NULL, filter->ftype);
    }
    else {
        ap_assert(1 != 1); /* we set the field wrong somehow */
    }

    return NULL;
}