Beispiel #1
0
/**
 * Constructs fail paths on keyword trie
 */
static apr_status_t acmp_connect_fail_branches(ACMP *parser) {
    /* Already connected ? */
    acmp_node_t *child, *node, *goto_node;
    apr_array_header_t *arr, *arr2, *tmp;

    if (parser->is_failtree_done != 0) return APR_SUCCESS;

    parser->root_node->text = "";
    arr  = apr_array_make(parser->pool, 32, sizeof(acmp_node_t *));
    arr2 = apr_array_make(parser->pool, 32, sizeof(acmp_node_t *));

    parser->root_node->fail = parser->root_node;

    /* All first-level children will fail back to root node */
    for (child = parser->root_node->child; child != NULL; child = child->sibling) {
        child->fail = parser->root_node;
        *(acmp_node_t **)apr_array_push(arr) = child;
#ifdef DEBUG_ACMP
        fprintf(stderr, "fail direction: *%s* => *%s*\n", child->text, child->fail->text);
#endif
    }

    for (;;) {
        while (apr_is_empty_array(arr) == 0) {
            node = *(acmp_node_t **)apr_array_pop(arr);
            node->fail = parser->root_node;
            if (node->parent != parser->root_node) {
                goto_node = acmp_child_for_code(node->parent->fail, node->letter);
                node->fail = (goto_node != NULL) ? goto_node : parser->root_node;
            }
#ifdef DEBUG_ACMP
            fprintf(stderr, "fail direction: *%s* => *%s*\n", node->text, node->fail->text);
#endif
            child = node->child;
            while (child != NULL) {
                *(acmp_node_t **)apr_array_push(arr2) = child;
                child = child->sibling;
            }
        }
        if (apr_is_empty_array(arr2) != 0) break;

        tmp = arr;
        arr = arr2;
        arr2 = tmp;
    }
    acmp_connect_other_matches(parser, parser->root_node);
    if (parser->root_node->child != NULL) acmp_build_binary_tree(parser, parser->root_node);
    parser->is_failtree_done = 1;
    return APR_SUCCESS;
}
Beispiel #2
0
/*
 * Processes a 'else' element.
 */
static apr_status_t process_else (parser_rec *p, const char *element,
		int states, apr_table_t *attrs) {
	block_t *block;
	template_node_t *n;

	if ((states & TEMPLATE_SOPEN) != 0) {
		if (apr_is_empty_array(p->b)) {
			return parse_error(p, "no 'if' to continue");
		}
		block = ((block_t *) p->b->elts) + p->b->nelts - 1;
		if (block->type != TEMPLATE_TIF || block->if_last == -1) {
			return parse_error(p, "no 'if' to continue");
		}

		n = (template_node_t *) apr_array_push(p->t);
		n->type = TEMPLATE_TJUMP;
		n->jump_next = -1;
		block->if_cnt++;

		n = ((template_node_t *) p->t->elts) + block->if_last;
		n->if_next = p->t->nelts;
		block->if_last = -1;
	}

	return APR_SUCCESS;
} 
Params *getPostParms(request_rec *r, apr_off_t * postSize) {
    apr_array_header_t *pairs = NULL;
    apr_off_t len;
    apr_size_t size;
    int res;
    int i = 0;
    char *buffer;
    Params *params = NULL;
    
    res = ap_parse_form_data(r, NULL, &pairs, -1, HUGE_STRING_LEN);
    if (res != OK || !pairs) return NULL; 
    params = apr_pcalloc(r->pool, sizeof(Params) * (pairs->nelts + 1));
    while (pairs && !apr_is_empty_array(pairs)) {
        ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs);
        apr_brigade_length(pair->value, 1, &len);
        size = (apr_size_t) len;
        buffer = apr_palloc(r->pool, size + 1);
        apr_brigade_flatten(pair->value, buffer, &size);
        buffer[len] = 0;
        params[i].key = apr_pstrdup(r->pool, pair->name);
        params[i].val = buffer;
        params[i].length = strlen(buffer);
        //ap_rprintf(r,"key : val : len: is %s : %s : %d ===", params[i].key, params[i].val, params[i].length);
        i++;
    }
    *postSize = i;

    return params;
}
static llzr_conn* get_post_data(request_rec* r)
{
    GTable *request_post_data = g_hash_table_new(g_str_hash, g_str_equal);
    apr_array_header_t *pairs = NULL;
    apr_off_t len;
    apr_size_t size;
    int res;
    char *buffer;

    res = ap_parse_form_data(r, NULL, &pairs, -1, HUGE_STRING_LEN);
    if (res != OK || !pairs) return NULL; /* Return NULL if we failed or if there are is no POST data */

    while (pairs && !apr_is_empty_array(pairs)) {
        ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs);
        apr_brigade_length(pair->value, 1, &len);
        size = (apr_size_t) len;
        buffer = apr_palloc(r->pool, size + 1);
        apr_brigade_flatten(pair->value, buffer, &size);
        buffer[len] = 0;

        g_hash_table_insert( request_post_data, apr_pstrdup(r->pool, pair->name), buffer);
    }

    return request_post_data;
}
void parseDimensions(mapcache_context *ctx, ezxml_t node, mapcache_tileset *tileset) {
   ezxml_t dimension_node;
   apr_array_header_t *dimensions = apr_array_make(ctx->pool,1,sizeof(mapcache_dimension*));
   for(dimension_node = ezxml_child(node,"dimension"); dimension_node; dimension_node = dimension_node->next) {
      char *name = (char*)ezxml_attr(dimension_node,"name");
      char *type = (char*)ezxml_attr(dimension_node,"type");
      char *unit = (char*)ezxml_attr(dimension_node,"unit");
      char *default_value = (char*)ezxml_attr(dimension_node,"default");
      
      mapcache_dimension *dimension = NULL;
      
      if(!name || !strlen(name)) {
         ctx->set_error(ctx, 400, "mandatory attribute \"name\" not found in <dimension>");
         return;
      }

      if(type && *type) {
         if(!strcmp(type,"values")) {
            dimension = mapcache_dimension_values_create(ctx->pool);
         } else if(!strcmp(type,"regex")) {
            dimension = mapcache_dimension_regex_create(ctx->pool);
         } else if(!strcmp(type,"intervals")) {
            dimension = mapcache_dimension_intervals_create(ctx->pool);
         } else if(!strcmp(type,"time")) {
            ctx->set_error(ctx,501,"time dimension type not implemented yet");
            return;
            dimension = mapcache_dimension_time_create(ctx->pool);
         } else {
            ctx->set_error(ctx,400,"unknown dimension type \"%s\"",type);
            return;
         }
      } else {
         ctx->set_error(ctx,400, "mandatory attribute \"type\" not found in <dimensions>");
         return;
      }

      dimension->name = apr_pstrdup(ctx->pool,name);

      if(unit && *unit) {
         dimension->unit = apr_pstrdup(ctx->pool,unit);
      }

      if(default_value && *default_value) {
         dimension->default_value = apr_pstrdup(ctx->pool,default_value);
      } else {
         ctx->set_error(ctx,400,"dimension \"%s\" has no \"default\" attribute",dimension->name);
         return;
      }

      dimension->configuration_parse_xml(ctx,dimension,dimension_node);
      GC_CHECK_ERROR(ctx);

      APR_ARRAY_PUSH(dimensions,mapcache_dimension*) = dimension;
   }
   if(apr_is_empty_array(dimensions)) {
      ctx->set_error(ctx, 400, "<dimensions> for tileset \"%s\" has no dimensions defined (expecting <dimension> children)",tileset->name);
      return;
   }
   tileset->dimensions = dimensions;
}
Beispiel #6
0
apr_status_t lwt_template_parse (const char *filename, lua_State *L,
		const char *flags, apr_pool_t *pool, apr_array_header_t **t,
		const char **err) {
	parser_rec *p;
	apr_status_t status;

	p = (parser_rec *) apr_pcalloc(pool, sizeof(parser_rec));	
	p->filename = filename;
	p->L = L;
	p->flags = parse_flags(flags != NULL ? flags : TEMPLATE_DEFAULT_FLAGS);
	p->pool = pool;
	p->t = apr_array_make(pool, 32, sizeof(template_node_t));
	p->b = apr_array_make(pool, 8, sizeof(block_t));	
	status = parse_template(p);
	if (status == APR_SUCCESS) {
		if (!apr_is_empty_array(p->b)) {
			status = parse_error(p, apr_psprintf(p->pool,
					"%d open elements at end of template",
					p->b->nelts));
		}
	}
	if (status != APR_SUCCESS) {
		if (err != NULL) {
			*err = p->err;
		}
		return status;
	}

	if (t != NULL) {
		*t = p->t;
	}

	return APR_SUCCESS;
} 
APR_DECLARE(void *) apr_array_pop(apr_array_header_t *arr)
{
    if (apr_is_empty_array(arr)) {
        return NULL;
    }
   
    return arr->elts + (arr->elt_size * (--arr->nelts));
}
Beispiel #8
0
// This is the method which does all the work handling the uploads.  It's only
// triggered by the fixup filter if +porter_should_rewrite_body+ returns true.
apr_status_t porter_process_upload(request_rec *r)
{
  porter_server_conf *config = (porter_server_conf *) ap_get_module_config(r->server->module_config, &porter_module);

  // Prepare the apreq objects.
  apreq_handle_t *req = apreq_handle_apache2(r);
  const apr_table_t *request_body = apreq_params(req, r->pool);

  // Create our upload request object, this is fleshed out by the rest of this method
  porter_upload_request_t *upload_request = porter_create_request(req, r, config);

  // This happens with malformed requests.  apreq_params should never return null
  // when the content-length is > 0 and it's a multipart request.  So just assume
  // it's broken and return bad request.  Otherwise subsequent method calls will
  // cause a segfault
  if (request_body == NULL)
  {
    PORTER_LOG_REQUEST_ERROR("Invalid request body");
    return HTTP_BAD_REQUEST;
  }

  // loop over each parameter provided by the user (see porter_each_parameter)
  apr_table_do(porter_each_parameter, upload_request, request_body, NULL);

  // If any of the parameter handlers return an error, they save the error code
  // in the upload_request.  So return that same error code.
  if (upload_request->status != APR_SUCCESS)
  {
    return upload_request->status;
  }


  // Just because the content type is multipart and the content-length was > 0 doesn't
  // mean that the user actually uploaded any files.  If they didn't, just return success
  // and let the original body be passed upstream.
  if (!apr_is_empty_array(upload_request->param_names))
  {
    // Write the parameter names to the X-Uploads header (comma seperated)
    const char *upload_parameters = apr_array_pstrcat(r->pool, upload_request->param_names, ',');
    apr_off_t len;
    apr_table_setn(r->headers_in, HTTP_X_UPLOADS, upload_parameters);

    // figure out the length of the newly rewritten body and set it in the request
    // along with the right content type.
    apr_brigade_length(upload_request->bucket_brigade, 0, &len);
    apr_table_setn(r->headers_in, "Content-Length", apr_itoa(r->pool, len));
    apr_table_setn(r->headers_in, "Content-Type", "application/x-www-form-urlencoded");

    // Add our input filter to the filter chain, this allows
    // us to replace the request body with our own one, and ensure that
    // gets passed down to the handler.
    ap_add_input_filter_handle(porter_input_filter_handle, upload_request, r, r->connection);
  }
  return APR_SUCCESS;
}
Beispiel #9
0
static void bind_post(int *count, lily_parse_state *parser, request_rec *r)
{
    if (*count == -1)
        return;

    lily_var *post_var = bind_hash_str_str_var(parser->symtab, "post");
    lily_hash_val *hash_val = post_var->value.hash;

    apr_array_header_t *pairs;
    apr_off_t len;
    apr_size_t size;
    char *buffer;
    char *sipkey = parser->vm->sipkey;
    lily_class *string_cls = lily_class_by_id(parser->symtab, SYM_CLASS_STRING);
    lily_sig *string_sig = string_cls->sig;

    /* Credit: I found out how to use this by reading httpd 2.4's mod_lua
       (specifically req_parsebody of lua_request.c). */
    int res = ap_parse_form_data(r, NULL, &pairs, -1, 1024 * 8);
    if (res == OK) {
        while (pairs && !apr_is_empty_array(pairs)) {
            ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs);
            apr_brigade_length(pair->value, 1, &len);
            size = (apr_size_t) len;
            buffer = lily_malloc(size + 1);
            if (buffer == NULL) {
                *count = -1;
                return;
            }

            apr_brigade_flatten(pair->value, buffer, &size);
            buffer[len] = 0;

            lily_value *elem_key = bind_string(string_sig, pair->name);
            /* Give the buffer to the value to save memory. */
            lily_value *elem_value = bind_string_and_buffer(string_sig, buffer);
            lily_hash_elem *new_elem = bind_hash_elem_with_values(sipkey,
                    elem_key, elem_value);

            if (elem_key == NULL || elem_value == NULL || new_elem == NULL) {
                lily_free(new_elem);
                deref_destroy_value(elem_key);
                deref_destroy_value(elem_value);
                *count = -1;
                return;
            }

            new_elem->next = hash_val->elem_chain;
            hash_val->elem_chain = new_elem;
        }
    }

    (*count)++;
}
/* Called after configuration is set, to finalise it. */
static int post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
{

    /* Create the caches, if required. */
    unsigned cache_max_entries
        = parse_number(authnz_crowd_process_config.cache_max_entries_string, "CrowdCacheMaxEntries", 0, UINT_MAX, 500,
        s);
    if (cache_max_entries > 0) {
        apr_time_t cache_max_age
            = apr_time_from_sec(parse_number(authnz_crowd_process_config.cache_max_age_string, "CrowdCacheMaxAge", 1,
            APR_INT64_MAX, 60, s));
        if (!crowd_cache_create(pconf, cache_max_age, cache_max_entries)) {
            exit(1);
        }
    }

    if (dir_configs != NULL) {

        /* Iterate over each directory config */
        authnz_crowd_dir_config **dir_config;
        while ((dir_config = apr_array_pop(dir_configs)) != NULL) {

            /* If any of the configuration parameters are specified, ensure that all mandatory parameters are
               specified. */
            crowd_config *crowd_config = (*dir_config)->crowd_config;
            if ((crowd_config->crowd_app_name != NULL || crowd_config->crowd_app_password != NULL
                || crowd_config->crowd_url != NULL)
                && (crowd_config->crowd_app_name == NULL || crowd_config->crowd_app_password == NULL
                || crowd_config->crowd_url == NULL)) {
                ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
                    "Missing CrowdAppName, CrowdAppPassword or CrowdURL for a directory.");
                exit(1);
            }

            /* Parse the timeout parameter, if specified */
            crowd_config->crowd_timeout
                = parse_number((*dir_config)->crowd_timeout_string, "CrowdTimeout", 0, LONG_MAX, 0, s);

            /* If no basic auth character encodings are specified, setup ISO-8859-1. */
            if (apr_is_empty_array((*dir_config)->basic_auth_xlates)) {
                const char *error = add_basic_auth_conversion("ISO-8859-1", *dir_config, pconf, ptemp);
                if (error != NULL) {
                    ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
                        "Could not configure default Basic Authentication translation.  %s", error);
                    exit(1);
                }
            }

        }
    }
    return OK;
}
Beispiel #11
0
/* return an array of (RFC 6125 coined) DNS-IDs and CN-IDs in a certificate */
BOOL SSL_X509_getIDs(apr_pool_t *p, X509 *x509, apr_array_header_t **ids)
{
    STACK_OF(GENERAL_NAME) *names;
    BIO *bio;
    X509_NAME *subj;
    char **cpp;
    int i, n;

    if (!x509 || !(*ids = apr_array_make(p, 0, sizeof(char *)))) {
        *ids = NULL;
        return FALSE;
    }

    /* First, the DNS-IDs (dNSName entries in the subjectAltName extension) */
    if ((names = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)) &&
        (bio = BIO_new(BIO_s_mem()))) {
        GENERAL_NAME *name;

        for (i = 0; i < sk_GENERAL_NAME_num(names); i++) {
            name = sk_GENERAL_NAME_value(names, i);
            if (name->type == GEN_DNS) {
                ASN1_STRING_print_ex(bio, name->d.ia5, ASN1_STRFLGS_ESC_CTRL|
                                     ASN1_STRFLGS_UTF8_CONVERT);
                n = BIO_pending(bio);
                if (n > 0) {
                    cpp = (char **)apr_array_push(*ids);
                    *cpp = apr_palloc(p, n+1);
                    n = BIO_read(bio, *cpp, n);
                    (*cpp)[n] = NUL;
                }
            }
        }
        BIO_free(bio);
    }

    if (names)
        sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);

    /* Second, the CN-IDs (commonName attributes in the subject DN) */
    subj = X509_get_subject_name(x509);
    i = -1;
    while ((i = X509_NAME_get_index_by_NID(subj, NID_commonName, i)) != -1) {
        cpp = (char **)apr_array_push(*ids);
        *cpp = SSL_X509_NAME_ENTRY_to_string(p, X509_NAME_get_entry(subj, i));
    }

    return apr_is_empty_array(*ids) ? FALSE : TRUE;
}
Beispiel #12
0
static int allowed_port(connect_conf *conf, int port)
{
    int i;
    port_range *list = (port_range *) conf->allowed_connect_ports->elts;

    if (apr_is_empty_array(conf->allowed_connect_ports)){
        return port == APR_URI_HTTPS_DEFAULT_PORT
               || port == APR_URI_SNEWS_DEFAULT_PORT;
    }

    for (i = 0; i < conf->allowed_connect_ports->nelts; i++) {
        if (port >= list[i].first && port <= list[i].last)
            return 1;
    }
    return 0;
}
static bool is_distrusted_provider(modauthopenid_config *s_cfg, std::string url, request_rec *r) {
  if(apr_is_empty_array(s_cfg->distrusted))
    return false;
  char **distrusted_sites = (char **) s_cfg->distrusted->elts;
  std::string base_url = modauthopenid::get_queryless_url(url);
  for (int i = 0; i < s_cfg->distrusted->nelts; i++) {
    pcre * re = modauthopenid::make_regex(distrusted_sites[i]);
    if(re == NULL) {
      APERR(r, "regex compilation failed for regex: %s", distrusted_sites[i]);
    } else if(modauthopenid::regex_match(base_url, re)) {
      APWARN(r, "%s is a distrusted (on black list) identity provider", base_url.c_str());
      return true;
    }
  }
  APDEBUG(r, "%s is NOT a distrusted identity provider (not blacklisted)", base_url.c_str());
  return false;
};
Beispiel #14
0
/**
var post: Hash[String, Tainted[String]]

This contains key+value pairs that were sent to the server as POST variables.
Any pair that has a key or a value that is not valid utf-8 will not be present.
*/
static lily_value *load_var_post(lily_options *options, uint16_t *unused)
{
    lily_value *v = lily_new_empty_value();
    lily_move_hash_f(MOVE_DEREF_NO_GC, v, lily_new_hash_val());
    lily_hash_val *hash_val = v->value.hash;
    request_rec *r = (request_rec *)options->data;

    apr_array_header_t *pairs;
    apr_off_t len;
    apr_size_t size;
    char *buffer;

    /* Credit: I found out how to use this by reading httpd 2.4's mod_lua
       (specifically req_parsebody of lua_request.c). */
    int res = ap_parse_form_data(r, NULL, &pairs, -1, 1024 * 8);
    if (res == OK) {
        while (pairs && !apr_is_empty_array(pairs)) {
            ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs);
            if (lily_is_valid_utf8(pair->name) == 0)
                continue;

            apr_brigade_length(pair->value, 1, &len);
            size = (apr_size_t) len;
            buffer = lily_malloc(size + 1);

            if (lily_is_valid_utf8(buffer) == 0) {
                lily_free(buffer);
                continue;
            }

            apr_brigade_flatten(pair->value, buffer, &size);
            buffer[len] = 0;

            lily_value *elem_key = lily_new_string(pair->name);
            /* Give the buffer to the value to save memory. */
            lily_value *elem_raw_value = lily_new_string_take(buffer);
            lily_value *elem_value = bind_tainted_of(elem_raw_value);

            apache_add_unique_hash_entry(options->sipkey, hash_val, elem_key,
                    elem_value);
        }
    }

    return v;
}
/* This is a wrapper around svn_uri_condense_targets() and
 * svn_dirent_condense_targets() (the choice of which is made based on
 * the value of TARGETS_ARE_URIS) which takes care of the
 * single-target special case.
 *
 * Callers are expected to check for an empty *COMMON_PARENT (which
 * means, "there was nothing common") for themselves.
 */
static svn_error_t *
condense_targets(const char **common_parent,
                 apr_array_header_t **target_relpaths,
                 const apr_array_header_t *targets,
                 svn_boolean_t targets_are_uris,
                 svn_boolean_t remove_redundancies,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
{
  if (targets_are_uris)
    {
      SVN_ERR(svn_uri_condense_targets(common_parent, target_relpaths,
                                       targets, remove_redundancies,
                                       result_pool, scratch_pool));
    }
  else
    {
      SVN_ERR(svn_dirent_condense_targets(common_parent, target_relpaths,
                                          targets, remove_redundancies,
                                          result_pool, scratch_pool));
    }

  /* svn_*_condense_targets leaves *TARGET_RELPATHS empty if TARGETS only
     had 1 member, so we special case that. */
  if (apr_is_empty_array(*target_relpaths))
    {
      const char *base_name;

      if (targets_are_uris)
        {
          svn_uri_split(common_parent, &base_name,
                        *common_parent, result_pool);
        }
      else
        {
          svn_dirent_split(common_parent, &base_name,
                           *common_parent, result_pool);
        }
      APR_ARRAY_PUSH(*target_relpaths, const char *) = base_name;
    }

  return SVN_NO_ERROR;
}
Beispiel #16
0
apr_status_t h2_stream_submit_pushes(h2_stream *stream)
{
    apr_status_t status = APR_SUCCESS;
    apr_array_header_t *pushes;
    int i;
    
    pushes = h2_push_collect(stream->pool, stream->request, stream->response);
    if (pushes && !apr_is_empty_array(pushes)) {
        ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, stream->session->c,
                      "h2_stream(%ld-%d): found %d push candidates",
                      stream->session->id, stream->id, pushes->nelts);
        for (i = 0; i < pushes->nelts; ++i) {
            h2_push *push = APR_ARRAY_IDX(pushes, i, h2_push*);
            h2_stream *s = h2_session_push(stream->session, stream, push);
            if (!s) {
                status = APR_ECONNRESET;
                break;
            }
        }
    }
Beispiel #17
0
/*
 * Processes a 'elseif' element.
 */
static apr_status_t process_elseif (parser_rec *p, const char *element,
		int states, apr_table_t *attrs) {
	block_t *block;
	template_node_t *n;
	apr_status_t status;

	if ((states & TEMPLATE_SOPEN) != 0) {
		if (apr_is_empty_array(p->b)) {
			return parse_error(p, "no 'if' to continue");
		}
		block = ((block_t *) p->b->elts) + p->b->nelts - 1;
		if (block->type != TEMPLATE_TIF || block->if_last == -1) {
			return parse_error(p, "no 'if' to continue");
		}

		n = (template_node_t *) apr_array_push(p->t);
		n->type = TEMPLATE_TJUMP;
		n->jump_next = -1;
		block->if_cnt++;

		n = ((template_node_t *) p->t->elts) + block->if_last;
		n->if_next = p->t->nelts;
		block->if_last = p->t->nelts;

		n = (template_node_t *) apr_array_push(p->t);
		n->type = TEMPLATE_TIF;
		n->if_cond = apr_table_get(attrs, "cond");
		if (n->if_cond == NULL) {
			return parse_error(p, "missing attribute 'cond'");
		}
		if ((status = compile_exp(p, n->if_cond, &n->if_index))
				!= APR_SUCCESS) {
			return status;
		}
		n->if_next = -1;
	}

	return APR_SUCCESS;
}
Beispiel #18
0
ZEKE_API(apr_table_t*) apr_table_clone(apr_pool_t *pool, const apr_table_t *table)
{
  apr_table_t *new_table;
  const apr_array_header_t *ta = NULL;
  int nelts = 0;

  if(!apr_is_empty_table(table)) {
    ta = apr_table_elts(table);
    nelts= ta->nelts;
  }

  new_table = apr_table_make(pool,nelts);
  assert(new_table != NULL);

  if(!apr_is_empty_array(ta)) {
    int i;
    apr_table_entry_t *te = (apr_table_entry_t*)ta->elts;
    for(i = 0; i < ta->nelts; i++)
      apr_table_set(new_table,te[i].key,te[i].val);
  }

  return new_table;
}
Beispiel #19
0
void mapcache_tileset_configuration_check(mapcache_context *ctx, mapcache_tileset *tileset)
{

  /* check we have all we want */
  if(tileset->cache == NULL) {
    /* TODO: we should allow tilesets with no caches */
    ctx->set_error(ctx, 400, "tileset \"%s\" has no cache configured.", tileset->name);
    return;
  }

  if(apr_is_empty_array(tileset->grid_links)) {
    ctx->set_error(ctx, 400, "tileset \"%s\" has no grids configured", tileset->name);
    return;
  }
#ifdef USE_PROJ
  /* not implemented yet, will be used to automatically calculate wgs84bbox with proj */
  else if(tileset->wgs84bbox[0]>=tileset->wgs84bbox[2]) {
    mapcache_grid_link *sgrid = APR_ARRAY_IDX(tileset->grid_links,0,mapcache_grid_link*);
    double *extent = sgrid->grid->extent;
    if(sgrid->restricted_extent) {
      extent = sgrid->restricted_extent;
    }
  }
Beispiel #20
0
/*
 * Parses a set element.
 */
static apr_status_t process_set (parser_rec *p, const char *element,
		int states, apr_table_t *attrs) {
        template_node_t *n;
	const char *names;
        char *name, *last;
        const char *sep = ", \t";
        int status;

        if ((states & TEMPLATE_SOPEN) != 0) {
		n = (template_node_t *) apr_array_push(p->t);
		n->type = TEMPLATE_TSET;
                n->set_names = apr_array_make(p->pool, 2, sizeof(const char *));
                names = apr_table_get(attrs, "names");
                if (names == NULL) {
                        return parse_error(p, "missing attribute 'names'");
                }
                name = apr_strtok(apr_pstrdup(p->pool, names), sep, &last);
                while (name != NULL) {
                        *((char **) apr_array_push(n->set_names)) = name;
                        name = apr_strtok(NULL, sep, &last);
                }
                if (apr_is_empty_array(n->set_names)) {
                        return parse_error(p, "empty 'names'");
                }
                n->set_expressions = apr_table_get(attrs, "expressions");
                if (n->set_expressions == NULL) {
                        return parse_error(p, "missing attribute "
					"'expressions'");
                }
                if ((status = compile_exp(p, n->set_expressions, &n->set_index))
				!= APR_SUCCESS) {
                        return status;
                }
	}

	return APR_SUCCESS;
}
Beispiel #21
0
/** Determine whether factory is empty. */
MRCP_DECLARE(apt_bool_t) mrcp_sa_factory_is_empty(const mrcp_sa_factory_t *sa_factory)
{
	return apr_is_empty_array(sa_factory->agents_arr);
}
Beispiel #22
0
void parseDimensions(mapcache_context *ctx, ezxml_t node, mapcache_tileset *tileset)
{
  ezxml_t dimension_node;
  apr_array_header_t *dimensions = apr_array_make(ctx->pool,1,sizeof(mapcache_dimension*));
  for(dimension_node = ezxml_child(node,"dimension"); dimension_node; dimension_node = dimension_node->next) {
    char *name = (char*)ezxml_attr(dimension_node,"name");
    char *type = (char*)ezxml_attr(dimension_node,"type");
    char *unit = (char*)ezxml_attr(dimension_node,"unit");
    char *default_value = (char*)ezxml_attr(dimension_node,"default");

    mapcache_dimension *dimension = NULL;

    if(!name || !strlen(name)) {
      ctx->set_error(ctx, 400, "mandatory attribute \"name\" not found in <dimension>");
      return;
    }

    if(type && *type) {
      if(!strcmp(type,"values")) {
        dimension = mapcache_dimension_values_create(ctx,ctx->pool);
      } else if(!strcmp(type,"regex")) {
        dimension = mapcache_dimension_regex_create(ctx,ctx->pool);
      } else if(!strcmp(type,"sqlite")) {
        dimension = mapcache_dimension_sqlite_create(ctx,ctx->pool);
      } else if(!strcmp(type,"time")) {
        dimension = mapcache_dimension_time_create(ctx,ctx->pool);
      } else {
        ctx->set_error(ctx,400,"unknown dimension type \"%s\"",type);
        return;
      }
    } else {
      ctx->set_error(ctx,400, "mandatory attribute \"type\" not found in <dimensions>");
      return;
    }
    GC_CHECK_ERROR(ctx);

    dimension->name = apr_pstrdup(ctx->pool,name);

    if(unit && *unit) {
      dimension->unit = apr_pstrdup(ctx->pool,unit);
    }
    
    if(default_value && *default_value) {
      dimension->default_value = apr_pstrdup(ctx->pool,default_value);
    } else {
      ctx->set_error(ctx,400,"dimension \"%s\" has no \"default\" attribute",dimension->name);
      return;
    }
    

    dimension->configuration_parse_xml(ctx,dimension,dimension_node);
    GC_CHECK_ERROR(ctx);

    APR_ARRAY_PUSH(dimensions,mapcache_dimension*) = dimension;
  }
  if(apr_is_empty_array(dimensions)) {
    ctx->set_error(ctx, 400, "<dimensions> for tileset \"%s\" has no dimensions defined (expecting <dimension> children)",tileset->name);
    return;
  }
  
  tileset->dimensions = dimensions;
  dimension_node = ezxml_child(node,"store_assemblies");
  if(dimension_node && dimension_node->txt) {
    if(!strcmp(dimension_node->txt,"false")) {
      tileset->store_dimension_assemblies = 0;
    } else if(strcmp(dimension_node->txt,"true")) {
      ctx->set_error(ctx,400,"failed to parse <store_assemblies> (%s), expecting \"true\" or \"false\"",dimension_node->txt);
      return;
    }
  }
  
  dimension_node = ezxml_child(node,"assembly_type");
  if(dimension_node) {
    if(!strcmp(dimension_node->txt,"stack")) {
      tileset->dimension_assembly_type = MAPCACHE_DIMENSION_ASSEMBLY_STACK;
    } else if(!strcmp(dimension_node->txt,"animate")) {
      tileset->dimension_assembly_type = MAPCACHE_DIMENSION_ASSEMBLY_ANIMATE;
      ctx->set_error(ctx,400,"animate dimension assembly mode not implemented");
      return;
    } else if(strcmp(dimension_node->txt,"none")) {
      ctx->set_error(ctx,400,"unknown dimension assembly mode (%s). Can be one of \"stack\" or \"none\"",dimension_node->txt);
      return;
    } else {
      tileset->dimension_assembly_type = MAPCACHE_DIMENSION_ASSEMBLY_NONE;
    }
  }
  
  /* should we create subdimensions from source if not found in cache.
  e.g. if dimension=mosaic returns dimension=val1,val2,val3 should we 
  query the wms source with dimension=val1 , dimension=val2 and/or
  dimension=val3 if they are not found in cache */
  dimension_node = ezxml_child(node,"subdimensions_read_only");
  if(dimension_node) {
    if(tileset->dimension_assembly_type == MAPCACHE_DIMENSION_ASSEMBLY_NONE) {
      ctx->set_error(ctx,400,"<subdimensions_read_only> used on a tileset with no <assembly_type> set, which makes no sense");
      return;
    }
    if(dimension_node && dimension_node->txt && !strcmp(dimension_node->txt,"true")) {
      tileset->subdimension_read_only = 1;
    } else if(strcmp(dimension_node->txt,"false")) {
      ctx->set_error(ctx,400,"failed to parse <subdimensions_read_only> (%s), expecting \"true\" or \"false\"",dimension_node->txt);
      return;
    }
  }
}
Beispiel #23
0
static int rpaf_post_read_request(request_rec *r) {
    char *fwdvalue, *val, *mask, *last_val;
    int i;
    apr_port_t tmpport;
    apr_pool_t *tmppool;
    const char *header_ip = NULL, *header_host = NULL, *header_https = NULL, *header_port = NULL;
    rpaf_server_cfg *cfg = (rpaf_server_cfg *)ap_get_module_config(r->server->module_config,
                                                                   &rpaf_module);

    if (!cfg->enable)
        return DECLINED;

    /* this overcomes an issue when mod_rewrite causes this to get called again
       and the environment value is lost for HTTPS. This is the only thing that
       is lost and we do not need to process any further after restoring the
       value. Note that this check uses the *per-request* note - otherwise we
       would shortcut here for every subsequent request */
    const char *rpaf_https = apr_table_get(r->notes, "rpaf_https");
    if (rpaf_https) {
        apr_table_set(r->subprocess_env, "HTTPS", rpaf_https);
        return DECLINED;
    }

    /* check if the remote_addr is in the allowed proxy IP list */
    if (is_in_array(r->DEF_ADDR, cfg->proxy_ips) != 1) {
        if (cfg->forbid_if_not_proxy)
            return HTTP_FORBIDDEN;
        return DECLINED;
    }

    /* TODO: We should not just assume that we should fallback to
       X-Forwarded-For as this could pose a security risk, keeping
       this for now to keep our behaviour consistant */
    header_ip = cfg->headername;
    if (header_ip)
      fwdvalue = (char *)apr_table_get(r->headers_in, header_ip);
    if (!header_ip || !fwdvalue)
    {
      header_ip = "X-Forwarded-For";
      fwdvalue  = (char *)apr_table_get(r->headers_in, header_ip);
    }

    /* if there was no forwarded for header then we dont do anything */
    if (!fwdvalue)
        return DECLINED;

    /* split up the list of forwarded IPs */
    apr_array_header_t *arr = apr_array_make(r->pool, 4, sizeof(char *));
    while ((val = strsep(&fwdvalue, ",")) != NULL) {
        /* strip leading and trailing whitespace */
        while(isspace(*val))
            ++val;
        for (i = strlen(val) - 1; i > 0 && isspace(val[i]); i--)
            val[i] = '\0';
        if (rpaf_looks_like_ip(val))
            *(char **)apr_array_push(arr) = apr_pstrdup(r->pool, val);
    }

    /* if there were no IPs, then there is nothing to do */
    if (apr_is_empty_array(arr))
        return DECLINED;

    /* get the last IP and check if it is in our list of proxies */
    if ((last_val = last_not_in_array(r, arr, cfg->proxy_ips)) == NULL)
        return DECLINED;

    /* if we are cleaning up the headers then we need to correct the forwarded IP list */
    if (cfg->clean_headers)
    {
        /* pop the proxy's IP from the list */
        apr_array_pop(arr);
        if (apr_is_empty_array(arr))
            apr_table_unset(r->headers_in, header_ip);
        else {
            char *ip_list = apr_array_pstrcat(r->pool, arr, ',');
            apr_table_set(r->headers_in, header_ip, ip_list);
        }
    }

    rpaf_cleanup_rec *rcr = (rpaf_cleanup_rec *)apr_pcalloc(r->pool, sizeof(rpaf_cleanup_rec));
    rcr->old_ip = apr_pstrdup(r->DEF_POOL, r->DEF_IP);
    rcr->r = r;
    apr_pool_cleanup_register(r->pool, (void *)rcr, rpaf_cleanup, apr_pool_cleanup_null);
    r->DEF_IP = apr_pstrdup(r->DEF_POOL, last_val);
    memcpy(&rcr->old_addr, r->DEF_ADDR, sizeof(apr_sockaddr_t));

    tmppool = r->DEF_ADDR->pool;
    tmpport = r->DEF_ADDR->port;
    apr_sockaddr_t *tmpsa;
    int ret = apr_sockaddr_info_get(&tmpsa, r->DEF_IP, APR_UNSPEC, tmpport, 0, tmppool);
    if (ret == APR_SUCCESS)
        memcpy(r->DEF_ADDR, tmpsa, sizeof(apr_sockaddr_t));
    if (cfg->sethostname) {
        const char *hostvalue;
        header_host = "X-Forwarded-Host";
        hostvalue   = apr_table_get(r->headers_in, header_host);
        if (!hostvalue) {
            header_host = "X-Host";
            hostvalue   = apr_table_get(r->headers_in, header_host);
        }

        if (!hostvalue) {
            header_host = NULL;
        } else {
            apr_array_header_t *arr = apr_array_make(r->pool, 0, sizeof(char*));
            while (*hostvalue && (val = ap_get_token(r->pool, &hostvalue, 1))) {
                *(char **)apr_array_push(arr) = apr_pstrdup(r->pool, val);
                if (*hostvalue != '\0')
                  ++hostvalue;
            }

            apr_table_set(r->headers_in, "Host", apr_pstrdup(r->pool, ((char **)arr->elts)[((arr->nelts)-1)]));
            r->hostname = apr_pstrdup(r->pool, ((char **)arr->elts)[((arr->nelts)-1)]);
            ap_update_vhost_from_headers(r);
        }
    }

    if (cfg->sethttps) {
        const char *httpsvalue, *scheme;
        header_https = "X-Forwarded-HTTPS";
        httpsvalue   = apr_table_get(r->headers_in, header_https);
        if (!httpsvalue) {
            header_https = "X-HTTPS";
            httpsvalue   = apr_table_get(r->headers_in, header_https);
        }

        if (!httpsvalue) {
            header_https = "X-Forwarded-Proto";
            httpsvalue   = apr_table_get(r->headers_in, header_https);
            if (!httpsvalue) {
              header_https = "X-Forwarded-Protocol";
              httpsvalue   = apr_table_get(r->headers_in, header_https);
            }
            if (httpsvalue) {
                if (strcmp(httpsvalue, cfg->https_scheme) == 0) {
                    /* set a per-request note to get around an issue with mod_rewrite
                       (explained in an earlier comment), and a per-connection note
                       to allow our version of ssl_is_https() to work.
                     */
                    apr_table_set(r->notes, "rpaf_https", "on");
                    apr_table_set(r->connection->notes, "rpaf_https", "on");
                    apr_table_set(r->subprocess_env   , "HTTPS"     , "on");
                    scheme = cfg->https_scheme;
                } else {
                    scheme = cfg->orig_scheme;
                }
            } else {
                header_https = NULL;
                scheme       = cfg->orig_scheme;
            }
        } else {
            if(strcmp(httpsvalue, "on") == 0 || strcmp(httpsvalue, "On") == 0) {
              apr_table_set(r->notes, "rpaf_https", "on");
              apr_table_set(r->connection->notes, "rpaf_https", "on");
              apr_table_set(r->subprocess_env   , "HTTPS"     , "on");
              scheme = cfg->https_scheme;
            } else {
              scheme = cfg->orig_scheme;
            }
        }

        #if AP_SERVER_MINORVERSION_NUMBER > 1 && AP_SERVER_PATCHLEVEL_NUMBER > 2
        r->server->server_scheme = scheme;
        #endif
    }

     if (cfg->setport) {
        const char *portvalue;
        header_port = "X-Forwarded-Port";
        portvalue   = apr_table_get(r->headers_in, header_port);
        if (!portvalue) {
            header_port = "X-Port";
            portvalue   = apr_table_get(r->headers_in, header_port);
        }

        if (!portvalue) {
            header_port     = NULL;
            r->server->port = cfg->orig_port;
        } else {
            r->server->port    = atoi(portvalue);
            r->parsed_uri.port = r->server->port;
        }
    }

    if (cfg->clean_headers) {
        if (header_host ) apr_table_unset(r->headers_in, header_host );
        if (header_https) apr_table_unset(r->headers_in, header_https);
        if (header_port ) apr_table_unset(r->headers_in, header_port );
    }

    return DECLINED;
}
Beispiel #24
0
/* TOOD: rewrite drive_serf to make it async */
static int drive_serf(request_rec *r, serf_config_t *conf)
{
    apr_status_t rv = 0;
    apr_pool_t *pool;
    apr_sockaddr_t *address;
    s_baton_t *baton = apr_palloc(r->pool, sizeof(s_baton_t));
    /* XXXXX: make persistent/per-process or something.*/
    serf_context_t *serfme;
    serf_connection_t *conn;
    serf_server_config_t *ctx =
        (serf_server_config_t *)ap_get_module_config(r->server->module_config,
                                                     &serf_module);

    /* Allocate everything out of a subpool, with a shorter lifetime than
     * the main request, so that we can cleanup safely and remove our events
     * from the main serf context in the async mpm mode.
     */
    apr_pool_create(&pool, r->pool);
    if (strcmp(conf->url.scheme, "cluster") == 0) {
        int rc;
        ap_serf_cluster_provider_t *cp;
        serf_cluster_t *cluster;
        apr_array_header_t *servers = NULL;
        apr_uint32_t pick = 0;
        ap_serf_server_t *choice;

        /* TODO: could this be optimized in post-config to pre-setup the
         * pointers to the right cluster inside the conf structure?
         */
        cluster = apr_hash_get(ctx->clusters,
                               conf->url.hostname,
                               APR_HASH_KEY_STRING);
        if (!cluster) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01123)
                          "SerfCluster: unable to find cluster %s", conf->url.hostname);
            return HTTP_INTERNAL_SERVER_ERROR;
        }

        cp = ap_lookup_provider(AP_SERF_CLUSTER_PROVIDER, cluster->provider, "0");

        if (cp == NULL) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01124)
                          "SerfCluster: unable to find provider %s", cluster->provider);
            return HTTP_INTERNAL_SERVER_ERROR;
        }

        if (cp->list_servers == NULL) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01125)
                          "SerfCluster: %s is missing list servers provider.", cluster->provider);
            return HTTP_INTERNAL_SERVER_ERROR;
        }

        rc = cp->list_servers(cp->baton,
                              r,
                              cluster->params,
                              &servers);

        if (rc != OK) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, APLOGNO(01126)
                          "SerfCluster: %s list servers returned failure", cluster->provider);
            return HTTP_INTERNAL_SERVER_ERROR;
        }

        if (servers == NULL || apr_is_empty_array(servers)) {
            ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, r, APLOGNO(01127)
                          "SerfCluster: %s failed to provide a list of servers", cluster->provider);
            return HTTP_INTERNAL_SERVER_ERROR;
        }

        /* TOOD: restructure try all servers in the array !! */
        pick = ap_random_pick(0, servers->nelts-1);
        choice = APR_ARRAY_IDX(servers, pick, ap_serf_server_t *);

        rv = apr_sockaddr_info_get(&address, choice->ip,
                                   APR_UNSPEC, choice->port, 0,
                                   pool);
    }
Beispiel #25
0
svn_error_t * SVNAuthData::cleanup_callback(svn_boolean_t *delete_cred, void *cleanup_baton,
                                            const char *cred_kind, const char *realmstring,
                                            apr_hash_t * hash, apr_pool_t * scratch_pool)
{
    std::tuple<std::vector<std::tuple<CString, CString, SVNAuthDataInfo>>*, std::vector<std::tuple<CString, CString, SVNAuthDataInfo>>> * tupleBaton =
        (std::tuple<std::vector<std::tuple<CString, CString, SVNAuthDataInfo>>*, std::vector<std::tuple<CString, CString, SVNAuthDataInfo>>>*)cleanup_baton;

    auto authList = std::get<0>(*tupleBaton);
    auto delList = std::get<1>(*tupleBaton);

    CString s1, s2;
    if (cred_kind)
        s1 = CUnicodeUtils::GetUnicode(cred_kind);
    if (realmstring)
        s2 = CUnicodeUtils::GetUnicode(realmstring);

    SVNAuthDataInfo authinfodata;

    for (apr_hash_index_t *hi = apr_hash_first(scratch_pool, hash); hi; hi = apr_hash_next(hi))
    {
        const void *vkey;
        void *val;

        apr_hash_this(hi, &vkey, NULL, &val);
        const char * key = (const char*)vkey;
        svn_string_t *value = (svn_string_t *)val;
        if (strcmp(key, SVN_CONFIG_AUTHN_PASSWORD_KEY) == 0)
        {
            CStringA data(value->data, (int)value->len);
            authinfodata.password = CUnicodeUtils::GetUnicode(data);
        }
        else if (strcmp(key, SVN_CONFIG_AUTHN_PASSPHRASE_KEY) == 0)
        {
            CStringA data(value->data, (int)value->len);
            authinfodata.passphrase = CUnicodeUtils::GetUnicode(data);
        }
        else if (strcmp(key, SVN_CONFIG_AUTHN_PASSTYPE_KEY) == 0)
        {
            CStringA data(value->data, (int)value->len);
            authinfodata.passtype = CUnicodeUtils::GetUnicode(data);
        }
        else if (strcmp(key, SVN_CONFIG_AUTHN_USERNAME_KEY) == 0)
        {
            CStringA data(value->data, (int)value->len);
            authinfodata.username = CUnicodeUtils::GetUnicode(data);
        }
        else if (strcmp(key, SVN_CONFIG_AUTHN_ASCII_CERT_KEY) == 0)
        {
            const svn_string_t * der_cert = nullptr;
            svn_x509_certinfo_t * certinfo = nullptr;
            const apr_array_header_t * hostnames = nullptr;
            svn_error_t *err;

            /* Convert header-less PEM to DER by undoing base64 encoding. */
            der_cert = svn_base64_decode_string(value, scratch_pool);

            err = svn_x509_parse_cert(&certinfo, der_cert->data, der_cert->len,
                                      scratch_pool, scratch_pool);
            if (err)
                continue;
            authinfodata.subject = svn_x509_certinfo_get_subject(certinfo, scratch_pool);
            authinfodata.validfrom = svn_time_to_human_cstring(svn_x509_certinfo_get_valid_from(certinfo), scratch_pool);
            authinfodata.validuntil = svn_time_to_human_cstring(svn_x509_certinfo_get_valid_to(certinfo), scratch_pool);
            authinfodata.issuer = svn_x509_certinfo_get_issuer(certinfo, scratch_pool);
            authinfodata.fingerprint = svn_checksum_to_cstring_display(svn_x509_certinfo_get_digest(certinfo), scratch_pool);

            hostnames = svn_x509_certinfo_get_hostnames(certinfo);
            if (hostnames && !apr_is_empty_array(hostnames))
            {
                int i;
                svn_stringbuf_t *buf = svn_stringbuf_create_empty(scratch_pool);
                for (i = 0; i < hostnames->nelts; ++i)
                {
                    const char *hostname = APR_ARRAY_IDX(hostnames, i, const char*);
                    if (i > 0)
                        svn_stringbuf_appendbytes(buf, ", ", 2);
                    svn_stringbuf_appendbytes(buf, hostname, strlen(hostname));
                }
                authinfodata.hostname = buf->data;
            }
        }
        else if (strcmp(key, SVN_CONFIG_AUTHN_FAILURES_KEY) == 0)
Beispiel #26
0
static void create_service(struct service_data *j) {
    apr_pool_t *t;
    const char *n;
    char *p;
    struct runtime_data *r = j->runtime;
    char **type, **txt_record;
    AvahiStringList *strlist = NULL;


    if (!j->group)
        if (!(j->group = avahi_entry_group_new(r->client, service_callback, j))) {
            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->main_server, "avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(r->client)));
            return;
        }

    ap_assert(j->group);
    ap_assert(avahi_entry_group_is_empty(j->group));

    apr_pool_create(&t, r->pool);

/*         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->main_server, "Service <%s>, host <%s>, port <%u>, location <%s>", j->name, j->host_name, j->port, j->location); */

    if (j->chosen_name)
        n = j->chosen_name;
    else if (!j->name)
        n = avahi_client_get_host_name(r->client);
    else if (j->append_host_name)
        n = apr_pstrcat(t, j->name, avahi_client_get_host_name(r->client), NULL);
    else
        n = j->name;

    if (!j->pool)
        apr_pool_create(&j->pool, r->pool);

    if (n != j->chosen_name) {
        apr_pool_clear(j->pool);
        j->chosen_name = apr_pstrdup(j->pool, n);
    }

    p = j->location ? apr_pstrcat(t, "path=", j->location, NULL) : NULL;

/*         ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->main_server, "%s, %s", p, n); */

    txt_record = (char **) j->txt_record->elts;

    for ( ; *txt_record ; txt_record++)
       strlist =  avahi_string_list_add(strlist, *txt_record);

    if (p)
        strlist = avahi_string_list_add(strlist, p);

    if (apr_is_empty_array(j->types)) {

        if (avahi_entry_group_add_service_strlst(
                j->group,
                AVAHI_IF_UNSPEC,
                AVAHI_PROTO_UNSPEC,
                0,
                n,
                j->port == 443 ? "_https._tcp" : "_http._tcp",
                NULL,
                j->host_name,
                j->port,
                strlist) < 0) {

            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->main_server, "avahi_entry_group_add_service_strlst(\"%s\") failed: %s", n, avahi_strerror(avahi_client_errno(r->client)));
        }

        const char * cnames = {j->host_name, NULL};
        PublishAvahiCNames(cnames);

    } else {

        for (type = (char**) j->types->elts; *type; type++) {

            if (avahi_entry_group_add_service_strlst(
                    j->group,
                    AVAHI_IF_UNSPEC,
                    AVAHI_PROTO_UNSPEC,
                    0,
                    n,
                    *type,
                    NULL,
                    j->host_name,
                    j->port,
                    strlist) < 0) {

                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->main_server, "avahi_entry_group_add_service_strlst(\"%s\") failed: %s", n, avahi_strerror(avahi_client_errno(r->client)));
            }

            const char * cnames = {j->host_name, NULL};
            PublishAvahiCNames(cnames);
        }
    }

    avahi_string_list_free(strlist);

    if (avahi_entry_group_is_empty(j->group)) {
        avahi_entry_group_free(j->group);
        j->group = NULL;
    } else
        avahi_entry_group_commit(j->group);

    apr_pool_destroy(t);
}