mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 23:56:57 +02:00
The current file "regex.h" define an abstraction for the regex. It provides the same struct name and the same "regexec" function for the 3 regex types supported: standard libc, basic pcre and jit pcre. The regex compilation function is not provided by this file. If the developper wants to use regex, he must write regex compilation code containing "#define *JIT*". This patch provides a unique regex compilation function according to the compilation options. In addition, the "regex.h" file checks the presence of the "#define PCRE_CONFIG_JIT" when "USE_PCRE_JIT" is enabled. If this flag is not present, the pcre lib doesn't support JIT and "#error" is emitted.
171 lines
3.5 KiB
C
171 lines
3.5 KiB
C
/*
|
|
* Regex and string management functions.
|
|
*
|
|
* Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*
|
|
*/
|
|
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <common/config.h>
|
|
#include <common/regex.h>
|
|
#include <common/standard.h>
|
|
#include <proto/log.h>
|
|
|
|
/* regex trash buffer used by various regex tests */
|
|
regmatch_t pmatch[MAX_MATCH]; /* rm_so, rm_eo for regular expressions */
|
|
|
|
|
|
int exp_replace(char *dst, char *src, const char *str, const regmatch_t *matches)
|
|
{
|
|
char *old_dst = dst;
|
|
|
|
while (*str) {
|
|
if (*str == '\\') {
|
|
str++;
|
|
if (isdigit((unsigned char)*str)) {
|
|
int len, num;
|
|
|
|
num = *str - '0';
|
|
str++;
|
|
|
|
if (matches[num].rm_eo > -1 && matches[num].rm_so > -1) {
|
|
len = matches[num].rm_eo - matches[num].rm_so;
|
|
memcpy(dst, src + matches[num].rm_so, len);
|
|
dst += len;
|
|
}
|
|
|
|
} else if (*str == 'x') {
|
|
unsigned char hex1, hex2;
|
|
str++;
|
|
|
|
hex1 = toupper(*str++) - '0';
|
|
hex2 = toupper(*str++) - '0';
|
|
|
|
if (hex1 > 9) hex1 -= 'A' - '9' - 1;
|
|
if (hex2 > 9) hex2 -= 'A' - '9' - 1;
|
|
*dst++ = (hex1<<4) + hex2;
|
|
} else {
|
|
*dst++ = *str++;
|
|
}
|
|
} else {
|
|
*dst++ = *str++;
|
|
}
|
|
}
|
|
*dst = '\0';
|
|
return dst - old_dst;
|
|
}
|
|
|
|
/* returns NULL if the replacement string <str> is valid, or the pointer to the first error */
|
|
const char *check_replace_string(const char *str)
|
|
{
|
|
const char *err = NULL;
|
|
while (*str) {
|
|
if (*str == '\\') {
|
|
err = str; /* in case of a backslash, we return the pointer to it */
|
|
str++;
|
|
if (!*str)
|
|
return err;
|
|
else if (isdigit((unsigned char)*str))
|
|
err = NULL;
|
|
else if (*str == 'x') {
|
|
str++;
|
|
if (!ishex(*str))
|
|
return err;
|
|
str++;
|
|
if (!ishex(*str))
|
|
return err;
|
|
err = NULL;
|
|
}
|
|
else {
|
|
Warning("'\\%c' : deprecated use of a backslash before something not '\\','x' or a digit.\n", *str);
|
|
err = NULL;
|
|
}
|
|
}
|
|
str++;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
|
|
/* returns the pointer to an error in the replacement string, or NULL if OK */
|
|
const char *chain_regex(struct hdr_exp **head, const regex_t *preg,
|
|
int action, const char *replace, void *cond)
|
|
{
|
|
struct hdr_exp *exp;
|
|
|
|
if (replace != NULL) {
|
|
const char *err;
|
|
err = check_replace_string(replace);
|
|
if (err)
|
|
return err;
|
|
}
|
|
|
|
while (*head != NULL)
|
|
head = &(*head)->next;
|
|
|
|
exp = calloc(1, sizeof(struct hdr_exp));
|
|
|
|
exp->preg = preg;
|
|
exp->replace = replace;
|
|
exp->action = action;
|
|
exp->cond = cond;
|
|
*head = exp;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int regex_comp(const char *str, regex *regex, int cs, int cap, char **err)
|
|
{
|
|
#ifdef USE_PCRE_JIT
|
|
int flags = 0;
|
|
const char *error;
|
|
int erroffset;
|
|
|
|
if (!cs)
|
|
flags |= PCRE_CASELESS;
|
|
if (!cap)
|
|
flags |= PCRE_NO_AUTO_CAPTURE;
|
|
|
|
regex->reg = pcre_compile(str, flags, &error, &erroffset, NULL);
|
|
if (!regex->reg) {
|
|
memprintf(err, "regex '%s' is invalid (error=%s, erroffset=%d)", str, error, erroffset);
|
|
return 0;
|
|
}
|
|
|
|
regex->extra = pcre_study(regex->reg, PCRE_STUDY_JIT_COMPILE, &error);
|
|
if (!regex->extra) {
|
|
pcre_free(regex->reg);
|
|
memprintf(err, "failed to compile regex '%s' (error=%s)", str, error);
|
|
return 0;
|
|
}
|
|
#else
|
|
int flags = REG_EXTENDED;
|
|
|
|
if (!cs)
|
|
flags |= REG_ICASE;
|
|
if (!cap)
|
|
flags |= REG_NOSUB;
|
|
|
|
if (regcomp(regex, str, flags) != 0) {
|
|
memprintf(err, "regex '%s' is invalid", str);
|
|
return 0;
|
|
}
|
|
#endif
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-indent-level: 8
|
|
* c-basic-offset: 8
|
|
* End:
|
|
*/
|