apr_byte_t oidc_util_regexp_first_match(apr_pool_t *pool, const char *input,
		const char *regexp, char **output, char **error_str) {
	const char *errorptr = NULL;
	int erroffset;
	int rc = 0;
	int subStr[OIDC_UTIL_REGEXP_MATCH_SIZE];
	const char *psubStrMatchStr = NULL;
	apr_byte_t rv = FALSE;

	pcre *preg = pcre_compile(regexp, 0, &errorptr, &erroffset, NULL);
	if (preg == NULL) {
		*error_str = apr_psprintf(pool,
				"pattern [%s] is not a valid regular expression", regexp);
		goto out;
	}

	if ((rc = pcre_exec(preg, NULL, input, (int) strlen(input), 0, 0, subStr,
			OIDC_UTIL_REGEXP_MATCH_SIZE)) < 0) {
		switch (rc) {
		case PCRE_ERROR_NOMATCH:
			*error_str = apr_pstrdup(pool, "string did not match the pattern");
			break;
		case PCRE_ERROR_NULL:
			*error_str = apr_pstrdup(pool, "something was null");
			break;
		case PCRE_ERROR_BADOPTION:
			*error_str = apr_pstrdup(pool, "a bad option was passed");
			break;
		case PCRE_ERROR_BADMAGIC:
			*error_str = apr_pstrdup(pool,
					"magic number bad (compiled re corrupt?)");
			break;
		case PCRE_ERROR_UNKNOWN_NODE:
			*error_str = apr_pstrdup(pool,
					"something kooky in the compiled re");
			break;
		case PCRE_ERROR_NOMEMORY:
			*error_str = apr_pstrdup(pool, "ran out of memory");
			break;
		default:
			*error_str = apr_psprintf(pool, "unknown error: %d", rc);
			break;
		}
		goto out;
	}

	if (output) {

		if (pcre_get_substring(input, subStr, rc, OIDC_UTIL_REGEXP_MATCH_NR,
				&(psubStrMatchStr)) <= 0) {
			*error_str = apr_psprintf(pool, "pcre_get_substring failed (rc=%d)",
					rc);
			goto out;
		}

		*output = apr_pstrdup(pool, psubStrMatchStr);
	}

	rv = TRUE;

out:

	if (psubStrMatchStr)
		pcre_free_substring(psubStrMatchStr);
	if (preg)
		pcre_free(preg);

	return rv;
}
apr_byte_t oidc_util_regexp_first_match(apr_pool_t *pool, const char *input,
		const char *regexp, char **output, char **error_str) {
	const char *errorptr = NULL;
	int erroffset;
	int rc = 0;
	int subStr[OIDC_UTIL_REGEXP_MATCH_SIZE];
	const char *psubStrMatchStr = NULL;
	apr_byte_t rv = FALSE;

	pcre *preg = pcre_compile(regexp, 0, &errorptr, &erroffset, NULL);
	if (preg == NULL) {
		*error_str = apr_psprintf(pool,
				"pattern [%s] is not a valid regular expression", regexp);
		goto out;
	}

	if ((rc = pcre_exec(preg, NULL, input, (int) strlen(input), 0, 0, subStr,
			OIDC_UTIL_REGEXP_MATCH_SIZE)) < 0) {
		switch (rc) {
		case PCRE_ERROR_NOMATCH:
			*error_str = apr_pstrdup(pool, "string did not match the pattern");
			break;
		case PCRE_ERROR_NULL:
			*error_str = apr_pstrdup(pool, "something was null");
			break;
		case PCRE_ERROR_BADOPTION:
			*error_str = apr_pstrdup(pool, "a bad option was passed");
			break;
		case PCRE_ERROR_BADMAGIC:
			*error_str = apr_pstrdup(pool,
					"magic number bad (compiled re corrupt?)");
			break;
		case PCRE_ERROR_UNKNOWN_NODE:
			*error_str = apr_pstrdup(pool,
					"something kooky in the compiled re");
			break;
		case PCRE_ERROR_NOMEMORY:
			*error_str = apr_pstrdup(pool, "ran out of memory");
			break;
		default:
			*error_str = apr_psprintf(pool, "unknown error: %d", rc);
			break;
		}
		goto out;
	}

	if (output) {

		if (pcre_get_substring(input, subStr, rc, OIDC_UTIL_REGEXP_MATCH_NR,
				&(psubStrMatchStr)) <= 0) {
			*error_str = apr_psprintf(pool, "pcre_get_substring failed (rc=%d)",
					rc);
			goto out;
		}

		*output = apr_pstrdup(pool, psubStrMatchStr);
	}

	rv = TRUE;

out:

	if (psubStrMatchStr)
		pcre_free_substring(psubStrMatchStr);
	if (preg)
		pcre_free(preg);

	return rv;
}