Exemplo n.º 1
0
boolean nx_config_cache_get_string(const char *module, const char *key, const char **result)
{
    nx_ctx_t *ctx;
    nx_cc_item_t *item;
    char ckey[NX_CONFIG_CACHE_MAX_KEYLEN];

    ASSERT(module != NULL);
    ASSERT(key != NULL);

    ctx = nx_ctx_get();

    if ( apr_snprintf(ckey, sizeof(ckey), "%s/%s", module, key) == sizeof(ckey) )
    {
	nx_panic("config cache key too long, limit is %d bytes", NX_CONFIG_CACHE_MAX_KEYLEN);
    }

    CHECKERR(apr_thread_mutex_lock(ctx->config_cache_mutex));
    item = (nx_cc_item_t *) apr_hash_get(ctx->config_cache, ckey, APR_HASH_KEY_STRING);
    CHECKERR(apr_thread_mutex_unlock(ctx->config_cache_mutex));

    if ( item == NULL )
    {
	return ( FALSE );
    }

    if ( (strcmp(item->key, ckey) == 0) && (item->value->type == NX_VALUE_TYPE_STRING) )
    {
	ASSERT(item->value->string != NULL);
	*result = item->value->string->buf;
	item->used = TRUE;
	return ( TRUE );
    }

    return ( FALSE );
}
Exemplo n.º 2
0
static void im_ssl_event(nx_module_t *module, nx_event_t *event)
{
    nx_module_input_t *input = NULL;

    ASSERT(event != NULL);

    switch ( event->type )
    {
	case NX_EVENT_READ:
	    im_ssl_read(module, event);
	    break;
	case NX_EVENT_WRITE:
	    im_ssl_write(module, event);
	    break;
	case NX_EVENT_DISCONNECT:
	    CHECKERR_MSG(apr_socket_data_get((void **) &input, "input",
					     (apr_socket_t *) event->data),
			 "couldn't get input data from socket");
	    im_ssl_disconnect(input);
	    break;
	case NX_EVENT_POLL:
	    if ( nx_module_get_status(module) == NX_MODULE_STATUS_RUNNING )
	    {
		nx_module_pollset_poll(module, TRUE);
	    }
	    break;
	default:
	    nx_panic("invalid event type: %d", event->type);
    }
}
Exemplo n.º 3
0
static void im_exec_event(nx_module_t *module, nx_event_t *event)
{
    nx_im_exec_conf_t *imconf;
    nx_exception_t e;

    ASSERT(event != NULL);

    imconf = (nx_im_exec_conf_t *) module->config;

    switch ( event->type )
    {
	case NX_EVENT_DISCONNECT:
	    // FIXME: restart if imconf->restart == TRUE
	    log_warn("im_exec process %s exited", imconf->cmd);
	    imconf->running = FALSE;
	    im_exec_add_restart_event(module);
	    break;
	case NX_EVENT_READ:
	    try
	    {
		im_exec_read(module);
	    }
	    catch(e)
	    {
		log_exception(e);
		im_exec_add_restart_event(module);
	    }
	    break;
	case NX_EVENT_POLL:
#ifdef WIN32
	    nx_panic("pollset based im_exec implementation doesn't work on windows");
#else
	    if ( nx_module_get_status(module) == NX_MODULE_STATUS_RUNNING )
	    {
		nx_module_pollset_poll(module, TRUE);
	    }
	    break;
#endif
	default:
	    nx_panic("invalid event type: %d", event->type);
    }
}
Exemplo n.º 4
0
static void xm_exec_event(nx_module_t *module, nx_event_t *event)
{
    ASSERT(event != NULL);

    switch ( event->type )
    {
	case NX_EVENT_MODULE_SPECIFIC:
	    xm_exec_reap(module);
	    break;
	default:
	    nx_panic("invalid event type: %d", event->type);
    }
}
Exemplo n.º 5
0
static void pm_norepeat_event(nx_module_t *module, nx_event_t *event)
{
    ASSERT(event != NULL);

    switch ( event->type )
    {
	case NX_EVENT_DATA_AVAILABLE:
	    pm_norepeat_data_available(module);
	    break;
	case NX_EVENT_WRITE:
	    pm_norepeat_write(module);
	    break;
	default:
	    nx_panic("invalid event type: %d", event->type);
    }
}
Exemplo n.º 6
0
void nx_config_cache_set_string(const char *module, const char *key, const char *value)
{
    nx_ctx_t *ctx;
    nx_cc_item_t *item;
    char ckey[NX_CONFIG_CACHE_MAX_KEYLEN];

    ASSERT(module != NULL);
    ASSERT(key != NULL);
    ASSERT(value != NULL);

    ctx = nx_ctx_get();

    if ( apr_snprintf(ckey, sizeof(ckey), "%s/%s", module, key) == sizeof(ckey) )
    {
	nx_panic("config cache key too long, limit is %d bytes", NX_CONFIG_CACHE_MAX_KEYLEN);
    }

    CHECKERR(apr_thread_mutex_lock(ctx->config_cache_mutex));
    item = (nx_cc_item_t *) apr_hash_get(ctx->config_cache, ckey, APR_HASH_KEY_STRING);
    CHECKERR(apr_thread_mutex_unlock(ctx->config_cache_mutex));

    if ( item != NULL )
    {
	ASSERT(item->value->type == NX_VALUE_TYPE_STRING);
	nx_value_free(item->value);
	item->value = nx_value_new_string(value);
	item->used = TRUE;
	item->needflush = TRUE;
    }
    else
    {
	item = malloc(sizeof(nx_cc_item_t));
	memset(item, 0, sizeof(nx_cc_item_t));
	item->key = strdup(ckey);
	item->value = nx_value_new_string(value);
	item->used = TRUE;
	item->needflush = TRUE;
	CHECKERR(apr_thread_mutex_lock(ctx->config_cache_mutex));
	apr_hash_set(ctx->config_cache, item->key, APR_HASH_KEY_STRING, (void *) item);
	CHECKERR(apr_thread_mutex_unlock(ctx->config_cache_mutex));
    }
}
Exemplo n.º 7
0
static void im_tcp_event(nx_module_t *module, nx_event_t *event)
{
    ASSERT(event != NULL);

    switch ( event->type )
    {
	case NX_EVENT_READ:
	    im_tcp_read(module, event);
	    break;
	case NX_EVENT_DISCONNECT:
	    im_tcp_got_disconnect(module, event);
	    break;
	case NX_EVENT_POLL:
	    if ( nx_module_get_status(module) == NX_MODULE_STATUS_RUNNING )
	    {
		nx_module_pollset_poll(module, TRUE);
	    }
	    break;
	default:
	    nx_panic("invalid event type: %d", event->type);
    }
}
static void om_kafka_event(nx_module_t *module, nx_event_t *event) {
	log_debug("Kafka module event entrypoint");
	nx_exception_t e;
	ASSERT(module != NULL);
	ASSERT(event != NULL);

	nx_om_kafka_conf_t* modconf;
	modconf = (nx_om_kafka_conf_t*) module->config;
	switch (event->type) {
		case NX_EVENT_DATA_AVAILABLE:
			log_debug("Output buflen: %d, bufstart: %d", (int) module->output.buflen, (int) module->output.bufstart);
			try {
				om_kafka_write(module);
			} catch (e) {
				io_err_handler(module, &e);
			}
			break;
		case NX_EVENT_READ:
			break;
		case NX_EVENT_WRITE:
			break;
		case NX_EVENT_RECONNECT:
			break;
		case NX_EVENT_DISCONNECT:
			break;
		case NX_EVENT_TIMEOUT:
			break;
		case NX_EVENT_POLL:
			if (nx_module_get_status(module) == NX_MODULE_STATUS_RUNNING) {
				nx_module_pollset_poll(module, FALSE);
			} 
			break;
		default:
		nx_panic("invalid event type: %d", event->type);
	}
}
Exemplo n.º 9
0
static void parse_kvp(nx_logdata_t *logdata,
		      nx_kvp_ctx_t *ctx,
		      const char *src,
		      size_t len)
{
    nx_string_t *valuestr = NULL;
    nx_exception_t e;
    nx_kvp_state_t state = NX_KVP_STATE_KEY_START;
    char keyname[256];
    int keylen = 0;
    volatile boolean got_keyquote = FALSE;

    try
    {
	int pos = 0;
	boolean got_valquote = FALSE;

	for ( pos = 0; pos < (int) len; pos++ )
	{
//	    log_info("parse [%c] state: %d", src[pos], state);
	    
	    switch ( state )
	    {
		case NX_KVP_STATE_KEY:
		    if ( src[pos] == ctx->keyquotechar )
		    {
			if ( got_keyquote == TRUE )
			{
			    state = NX_KVP_STATE_KV_DELIMITER;
			}
			else
			{
			    throw_msg("invalid key quotation in key-value pair");
			}
		    }
		    else if ( (ctx->kvdelimiter == '\0') &&
			      IS_KVDELIMITERCHAR(src[pos]) )
		    {
			ctx->kvdelimiter = src[pos];
			state = NX_KVP_STATE_VALUE_START;
		    }
		    else if ( src[pos] == ctx->kvdelimiter )
		    {
			state = NX_KVP_STATE_VALUE_START;
		    }
		    else if ( src[pos] == ctx->escapechar )
		    {
			state = NX_KVP_STATE_KEY_ESCAPE;
		    }
/* Unquoted keys containing space don't work with this, so instead we trim the space at the end
		    else if ( (src[pos] == ' ') && (got_keyquote != TRUE) )
		    {
			state = NX_KVP_STATE_KV_DELIMITER;
		    }
*/
		    else
		    {
			if ( keylen < (int) sizeof(keyname) - 1 )
			{
			    keyname[keylen] = src[pos];
			    keylen++;
			}
		    }
		    break;

		case NX_KVP_STATE_VALUE_START:
		    if ( src[pos] == ' ' )
		    { // skip leading space
			break;
		    }
		    got_valquote = FALSE;
		    ASSERT(valuestr == NULL);
		    valuestr = nx_string_new();

		    if ( (ctx->valquotechar == '\0') && 
			 IS_QUOTECHAR(src[pos]) )
		    { // auto-detected quotechar
			ctx->valquotechar = src[pos];
			got_valquote = TRUE;
		    }		    
		    else if ( src[pos] == ctx->valquotechar )
		    {
			got_valquote = TRUE;
		    }
		    else
		    {
			pos--; // handle character in STATE_VALUE
		    }
		    state = NX_KVP_STATE_VALUE;
		    break;

		case NX_KVP_STATE_VALUE:
		    if ( src[pos] == ctx->valquotechar )
		    {
			state = NX_KVP_STATE_KVP_DELIMITER;
			if ( got_valquote == TRUE )
			{
			}
			else
			{
			    if ( valuestr->len > 0)
			    {
				throw_msg("invalid value quotation in key-value pair: %s", valuestr->buf);
			    }
			}
		    }
		    else if ( (ctx->kvpdelimiter == '\0') &&
			      IS_KVPDELIMITERCHAR(src[pos]) &&
			      (got_valquote == FALSE) )
		    {
			ctx->kvpdelimiter = src[pos];
			// add field-value
			add_logdata_field(logdata, keyname, keylen, got_keyquote, valuestr);
			valuestr = NULL;
			state = NX_KVP_STATE_KEY_START;
		    }
		    else if ( (src[pos] == ctx->kvpdelimiter) && (got_valquote == FALSE) )
		    {
			// add field-value
			add_logdata_field(logdata, keyname, keylen, got_keyquote, valuestr);
			valuestr = NULL;
			state = NX_KVP_STATE_KEY_START;
		    }
		    else if ( src[pos] == ctx->escapechar )
		    {
			state = NX_KVP_STATE_VALUE_ESCAPE;
		    }
		    else
		    { // append character to value
			nx_string_append(valuestr, src + pos, 1);
		    }
		    break;

		case NX_KVP_STATE_VALUE_ESCAPE:
		    unescape_value(ctx, src[pos], valuestr, got_valquote);
		    state = NX_KVP_STATE_VALUE;
		    break;

		case NX_KVP_STATE_KV_DELIMITER:
		    if ( src[pos] == ' ' ) 
		    { // skip space
			break;
		    }

		    if ( (ctx->kvdelimiter == '\0') &&
			 IS_KVDELIMITERCHAR(src[pos]) )
		    {
			ctx->kvdelimiter = src[pos];
			state = NX_KVP_STATE_VALUE_START;
		    }
		    else if ( src[pos] == ctx->kvdelimiter )
		    {
			state = NX_KVP_STATE_VALUE_START;
		    }
		    break;
		    
		case NX_KVP_STATE_KVP_DELIMITER:
		    if ( (ctx->kvpdelimiter == '\0') &&
			 IS_KVPDELIMITERCHAR(src[pos]) )
		    {
			ctx->kvpdelimiter = src[pos];
			state = NX_KVP_STATE_KEY_START;
			add_logdata_field(logdata, keyname, keylen, got_keyquote, valuestr);
			valuestr = NULL;
		    }
		    else if ( src[pos] == ctx->kvpdelimiter )
		    {
			state = NX_KVP_STATE_KEY_START;
			add_logdata_field(logdata, keyname, keylen, got_keyquote, valuestr);
			valuestr = NULL;
		    }
		    break;
		    
		case NX_KVP_STATE_KEY_START:
		    keylen = 0;
		    got_keyquote = FALSE;
		    if ( src[pos] == ' ' )
		    { // skip space
			break;
		    }
		    else if ( (ctx->keyquotechar == '\0') && 
			      IS_QUOTECHAR(src[pos]) )
		    { // auto-detected quotechar
			ctx->keyquotechar = src[pos];
			got_keyquote = TRUE;
			state = NX_KVP_STATE_KEY;
		    }
		    else if ( src[pos] == ctx->keyquotechar )
		    {
			got_keyquote = TRUE;
			state = NX_KVP_STATE_KEY;
		    }
		    else if ( src[pos] == ctx->escapechar )
		    {
			state = NX_KVP_STATE_KEY_ESCAPE;
		    }
		    else if ( src[pos] == ctx->kvpdelimiter )
		    { // double delimiter, no value for kvp, skip
		    }
		    else
		    { // first character of unquoted key
			state = NX_KVP_STATE_KEY;
			if ( keylen < (int) sizeof(keyname) - 1 )
			{
			    keyname[keylen] = src[pos];
			    keylen++;
			}
		    }
		    break;
		case NX_KVP_STATE_KEY_ESCAPE:
		    if ( (src[pos] == ctx->escapechar) ||
			 (src[pos] == ctx->keyquotechar) )
		    {
			if ( keylen < (int) sizeof(keyname) - 1 )
			{
			    keyname[keylen] = src[pos];
			    keylen++;
			}
		    }
		    else
		    {
			if ( keylen < (int) sizeof(keyname) - 2 )
			{
			    keyname[keylen] = ctx->escapechar;
			    keylen++;

			    keyname[keylen] = src[pos];
			    keylen++;
			}
		    }
		    state = NX_KVP_STATE_KEY;
		    break;
		default:
		    nx_panic("invalid state %d", state);
	    }
	}
    }
    catch(e)
    {
	if ( valuestr != NULL )
	{
	    nx_string_free(valuestr);
	}
	rethrow(e);
    }

    switch ( state )
    {
	case NX_KVP_STATE_VALUE:
	case NX_KVP_STATE_KVP_DELIMITER:
	    add_logdata_field(logdata, keyname, keylen, got_keyquote, valuestr);
	    break;
	case NX_KVP_STATE_KEY_START:
	    ASSERT(valuestr == NULL);
	    break;
	case NX_KVP_STATE_KV_DELIMITER:
	case NX_KVP_STATE_KEY:
	case NX_KVP_STATE_KEY_ESCAPE:
	case NX_KVP_STATE_VALUE_START:
	case NX_KVP_STATE_VALUE_ESCAPE:
	    if ( valuestr != NULL )
	    {
		nx_string_free(valuestr);
	    }
	    throw_msg("invalid KVP input: '%s' [state: %d]", src, state);
	    break;
	default:
	    nx_panic("invalid state %d", state);
    }
}
Exemplo n.º 10
0
static boolean match_line(nx_value_t *pattern, const char *subject, size_t len)
{
    int pcre_result;

    if ( pattern->type == NX_VALUE_TYPE_STRING )
    {
	if ( len < pattern->string->len )
	{
	    len = pattern->string->len;
	}
	if ( strncmp(subject, pattern->string->buf, len) == 0 )
	{
	    return ( TRUE );
	}
    }
    else // REGEXP
    {
	int ovector[NX_EXPR_MAX_CAPTURED_FIELDS * 3];

	ASSERT(pattern->type == NX_VALUE_TYPE_REGEXP);
	pcre_result = pcre_exec(pattern->regexp.pcre, NULL, 
				subject, 
				(int) len, 0, 0,
				ovector, NX_EXPR_MAX_CAPTURED_FIELDS * 3);

	if ( pcre_result >= 0 )
	{ // got match
	    return ( TRUE );
	}
	else
	{
	    switch ( pcre_result )
	    {
		case PCRE_ERROR_NOMATCH:
		    log_debug("regexp [%s] doesn't match subject string [%s]",
			      pattern->regexp.str, subject);
		    break;
		case PCRE_ERROR_NULL:
		    nx_panic("invalid arguments (code, ovector or ovecsize are invalid)");
		case PCRE_ERROR_BADOPTION:
		    nx_panic("invalid option in options parameter");
		case PCRE_ERROR_BADMAGIC:
		    nx_panic("invalid pcre magic value");
		case PCRE_ERROR_UNKNOWN_NODE:
		case PCRE_ERROR_INTERNAL:
		    nx_panic("pcre bug or buffer overflow error");
		case PCRE_ERROR_NOMEMORY:
		    nx_panic("pcre_malloc() failed");
		case PCRE_ERROR_MATCHLIMIT:
		    log_error("pcre match_limit reached");
		    break;
		case PCRE_ERROR_BADUTF8:
		    log_error("invalid pcre utf-8 byte sequence");
		    break;
		case PCRE_ERROR_BADUTF8_OFFSET:
		    log_error("invalid pcre utf-8 byte sequence offset");
		    break;
		case PCRE_ERROR_PARTIAL:
		    break;
		case PCRE_ERROR_BADPARTIAL:
		    nx_panic("PCRE_ERROR_BADPARTIAL");
		case PCRE_ERROR_BADCOUNT:
		    nx_panic("negative ovecsize");
		default:
		    log_error("unknown pcre error in pcre_exec(): %d", pcre_result);
		    break;
	    }
	}
    }

    return ( FALSE );
}
Exemplo n.º 11
0
static boolean nx_patterndb_match_matchfields(nx_logdata_t *logdata,
					      nx_pattern_matchfields_t *matchfields,
					      nx_logdata_field_list_t *addfields,
					      boolean isgroup,
					      const char *name)
{
    nx_pattern_matchfield_t *matchfield;
    nx_logdata_field_t *logfield;
    nx_exception_t e;

    ASSERT(matchfields != NULL);

    for ( matchfield = NX_DLIST_FIRST(matchfields);
	  matchfield != NULL;
	  matchfield = NX_DLIST_NEXT(matchfield, link) )
    {
	logfield = nx_logdata_get_field(logdata, matchfield->name);
	if ( logfield == NULL )
	{ // logdata does not have field
	    //log_debug("logdata does not have '%s' field", matchfield->name);
	    return ( FALSE );
	}

	if ( logfield->value->defined == FALSE )
	{ // undef does not match
	    return ( FALSE );
	}

	if ( logfield->value->type == NX_VALUE_TYPE_STRING )
	{ 
	    switch ( matchfield->type )
	    {
		case NX_PATTERN_MATCH_TYPE_EXACT:
		    //log_debug("exact match for '%s' against '%s'", matchfield->value, logfield->value->string->buf);
		    if ( strcmp(matchfield->value, logfield->value->string->buf) != 0 )
		    {
			return ( FALSE );
		    }
		    break;
		case NX_PATTERN_MATCH_TYPE_REGEXP:
		    if ( patterndb_regexp_match(logfield->value->string->buf, matchfield,
						addfields, isgroup, name) == FALSE )
		    {
			//log_debug("logdata field didn't match regexp");
			return ( FALSE );
		    }
		    break;
		default:
		    nx_panic("invalid match type: %d", matchfield->type);
	    }
	}
	else if ( logfield->value->type == NX_VALUE_TYPE_INTEGER )
	{ 
	    char intstr[32];
	    char *strval;
	    volatile boolean retval = FALSE;

	    switch ( matchfield->type )
	    {
		case NX_PATTERN_MATCH_TYPE_EXACT:
		    //log_debug("exact match for '%s' against '%ld'", matchfield->value, logfield->value->integer);
		    apr_snprintf(intstr, sizeof(intstr), "%"APR_INT64_T_FMT, logfield->value->integer);
		    if ( strcmp(matchfield->value, intstr) != 0 )
		    {
			return ( FALSE );
		    }
		    break;
		case NX_PATTERN_MATCH_TYPE_REGEXP:
		    strval = nx_value_to_string(logfield->value);
		    try
		    {
			if ( patterndb_regexp_match(strval, matchfield,
						    addfields, isgroup, name) == TRUE )
			{
			    retval = TRUE;
			}
		    }
		    catch(e)
		    {
			free(strval);
			rethrow(e);
		    }
		    free(strval);
		    return ( retval );
		default:
		    nx_panic("invalid match type: %d", matchfield->type);
	    }
	}
	else if ( logfield->value->type == NX_VALUE_TYPE_BOOLEAN )
	{ 
	    switch ( matchfield->type )
	    {
		case NX_PATTERN_MATCH_TYPE_EXACT:
		    if ( (strcasecmp(matchfield->value, "true") == 0) &&
			 (logfield->value->boolean == FALSE) )
		    {
			return ( FALSE );
		    }
		    else if ( (strcasecmp(matchfield->value, "false") == 0) &&
			 (logfield->value->boolean == TRUE) )
		    {
			return ( FALSE );
		    }
		    break;
		case NX_PATTERN_MATCH_TYPE_REGEXP:
		    log_error("invalid use of REGEXP match with BOOLEAN type %s", logfield->key);
		    return ( FALSE );
		default:
		    nx_panic("invalid match type: %d", matchfield->type);
	    }
	}
	else 
	{ // other logdata field type
	    char *strval;
	    boolean retval = FALSE;

	    strval = nx_value_to_string(logfield->value);
	    try
	    {
		switch ( matchfield->type )
		{
		    case NX_PATTERN_MATCH_TYPE_EXACT:
			if ( strcmp(matchfield->value, strval) == 0 )
			{
			    retval = TRUE;
			}
			break;
		    case NX_PATTERN_MATCH_TYPE_REGEXP:
			if ( patterndb_regexp_match(strval, matchfield,
						    addfields, isgroup, name) == TRUE )
			{
			    retval = TRUE;
			}
			break;
		    default:
			nx_panic("invalid match type: %d", matchfield->type);
		}
	    }
	    catch(e)
	    {
		free(strval);
		rethrow(e);
	    }
	    free(strval);

	    return ( retval );
	}
    }
    return ( TRUE );
}
Exemplo n.º 12
0
static boolean patterndb_regexp_match(const char *subject,
				      nx_pattern_matchfield_t *matchfield,
				      nx_logdata_field_list_t *addfields,
				      boolean isgroup,
				      const char *name)
{
    int result;
    nx_pattern_capturedfield_t * volatile capturedfield;
    int ovector[NX_PATTERNDB_MAX_CAPTURED_FIELDS * 3];
    volatile int i;
    nx_value_t *value;
    nx_logdata_field_t *setfield;
    nx_exception_t e;

    result = pcre_exec(matchfield->regexp, NULL, subject, (int) strlen(subject), 0, 0,
		       ovector, NX_PATTERNDB_MAX_CAPTURED_FIELDS * 3);

    if ( result < 0 )
    {
	switch ( result )
	{
	    case PCRE_ERROR_NOMATCH:
		break;
	    case PCRE_ERROR_PARTIAL:
		// The subject string did not match, but it did match partially.
		// Treat the same as NOMATCH
		break;
	    case PCRE_ERROR_NULL:
		nx_panic("invalid arguments (code, ovector or ovecsize are invalid)");
	    case PCRE_ERROR_BADOPTION:
		nx_panic("invalid option in options parameter");
	    case PCRE_ERROR_BADMAGIC:
		nx_panic("invalid pcre magic value");
	    case PCRE_ERROR_UNKNOWN_NODE:
	    case PCRE_ERROR_INTERNAL:
		nx_panic("pcre bug or buffer overflow error");
	    case PCRE_ERROR_NOMEMORY:
		nx_panic("pcre_malloc() failed");
	    case PCRE_ERROR_MATCHLIMIT:
		log_error("pcre match_limit reached in pattern '%s' for regexp '%s'",
			  name, matchfield->value);
		break;
	    case PCRE_ERROR_BADUTF8:
		log_error("invalid pcre utf-8 byte sequence in pattern '%s' for regexp '%s'",
			  name, matchfield->value);
		break;
	    case PCRE_ERROR_BADUTF8_OFFSET:
		log_error("invalid pcre utf-8 byte sequence offset in pattern '%s' for regexp '%s'",
			  name, matchfield->value);
		break;
	    case PCRE_ERROR_BADPARTIAL:
		nx_panic("PCRE_ERROR_BADPARTIAL");
	    case PCRE_ERROR_BADCOUNT:
		nx_panic("negative ovecsize");
	    default:
		log_error("unknown pcre error in pcre_exec(): %d", result);
		break;
	}
	log_debug("regexp '%s' did not match against '%s'", matchfield->value, subject);
	return ( FALSE );
    }

    log_debug("regexp '%s' matched on '%s'", matchfield->value, subject);

    if ( matchfield->capturedfield_cnt > 0 )
    {
	if ( result != matchfield->capturedfield_cnt + 1 )
	{
	    throw_msg("regexp match returned %d captured substrings, matchfield in pattern has %d defined",
		      result - 1, matchfield->capturedfield_cnt);
	}
	// add captured fields into setfields variable, these will be added to the
	// logdata if all matchfields match (=the pattern matches)
	for ( capturedfield = NX_DLIST_FIRST(matchfield->capturedfields), i = 2;
	      capturedfield != NULL;
	      capturedfield = NX_DLIST_NEXT(capturedfield, link), i += 2 )
	{
	    ASSERT(matchfield->capturedfield_cnt * 2 >= i);

	    try
	    {
		size_t len = (size_t) (ovector[i + 1] - ovector[i]);
		if ( capturedfield->type == NX_VALUE_TYPE_STRING )
		{
		    value = nx_value_new(NX_VALUE_TYPE_STRING);
		    value->string = nx_string_create(subject + ovector[i], (int) len);
		}
		else
		{
		    char tmpstr[len + 1];
		    
		    memcpy(tmpstr, subject + ovector[i], len);
		    tmpstr[len] = '\0';
		    value = nx_value_from_string(tmpstr, capturedfield->type);
		}
		setfield = malloc(sizeof(nx_logdata_field_t));
		setfield->value = value;
		setfield->key = strdup(capturedfield->name);
		ASSERT(addfields != NULL);
		NX_DLIST_INSERT_TAIL(addfields, setfield, link);
		//log_debug("added %s to logdata", capturedfield->name);
	    }
	    catch(e)
	    {
		log_exception_msg(e, "error setting field '%s' in %s '%s'",		  
				  capturedfield->name,
				  isgroup == TRUE ? "pattern group" : "pattern",
				  name);
	    }
	}
    }

    return ( TRUE );
}