将配置文件纳入版本管理。
This commit is contained in:
242
plugin/business/pangu-http/src/pattern_replace.cpp
Normal file
242
plugin/business/pangu-http/src/pattern_replace.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
#include "pattern_replace.h"
|
||||
|
||||
#include <tfe_utils.h>
|
||||
|
||||
#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
#include <pcre2.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define MAX_EDIT_MATCHES 16
|
||||
|
||||
enum replace_zone zone_name_to_id(const char * name)
|
||||
{
|
||||
const char * std_name[] = {"http_req_uri",
|
||||
"http_req_header",
|
||||
"http_req_body",
|
||||
"http_resp_header",
|
||||
"http_resp_body",
|
||||
"http_resp_body"};
|
||||
size_t i = 0;
|
||||
for (i = 0; i < sizeof(std_name) / sizeof(const char *); i++)
|
||||
{
|
||||
if (0 == strcasecmp(name, std_name[i]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (enum replace_zone) i;
|
||||
}
|
||||
static char * strchr_esc(char * s, const char delim)
|
||||
{
|
||||
char * token;
|
||||
if (s == NULL)
|
||||
return NULL;
|
||||
for (token = s; *token != '\0'; token++)
|
||||
{
|
||||
if (*token == '\\')
|
||||
{
|
||||
token++;
|
||||
continue;
|
||||
}
|
||||
if (*token == delim)
|
||||
break;
|
||||
}
|
||||
if (*token == '\0')
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return token;
|
||||
}
|
||||
}
|
||||
static char * strtok_r_esc(char * s, const char delim, char ** save_ptr)
|
||||
{
|
||||
char * token;
|
||||
|
||||
if (s == NULL) s = *save_ptr;
|
||||
|
||||
/* Scan leading delimiters. */
|
||||
token = strchr_esc(s, delim);
|
||||
if (token == NULL)
|
||||
{
|
||||
*save_ptr = token;
|
||||
return s;
|
||||
}
|
||||
/* Find the end of the token. */
|
||||
*token = '\0';
|
||||
token++;
|
||||
*save_ptr = token;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
size_t format_replace_rule(const char * exec_para, struct replace_rule * replace, size_t n_replace)
|
||||
{
|
||||
char * tmp = ALLOC(char, strlen(exec_para) + 1);
|
||||
char * token = NULL, * sub_token = NULL, * saveptr = NULL, * saveptr2 = NULL;
|
||||
size_t idx = 0;
|
||||
|
||||
const char * str_zone = "zone=";
|
||||
const char * str_subs = "substitute=";
|
||||
memcpy(tmp, exec_para, strlen(exec_para));
|
||||
|
||||
for (token = tmp;; token = NULL)
|
||||
{
|
||||
sub_token = strtok_r(token, ";", &saveptr);
|
||||
if (sub_token == NULL) break;
|
||||
|
||||
if (0 == strncasecmp(sub_token, str_zone, strlen(str_zone)))
|
||||
{
|
||||
replace[idx].zone = zone_name_to_id(sub_token + strlen(str_zone));
|
||||
if (replace[idx].zone == kZoneMax)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sub_token = strtok_r(NULL, ";", &saveptr);
|
||||
if (0 == strncasecmp(sub_token, str_subs, strlen(str_subs)))
|
||||
{
|
||||
sub_token += strlen(str_subs) + 1;
|
||||
replace[idx].find = tfe_strdup(strtok_r_esc(sub_token, '/', &saveptr2));
|
||||
replace[idx].replace_with = tfe_strdup(strtok_r_esc(NULL, '/', &saveptr2));
|
||||
|
||||
idx++;
|
||||
if (idx == n_replace)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(tmp);
|
||||
tmp = NULL;
|
||||
return idx;
|
||||
}
|
||||
|
||||
size_t select_replace_rule(enum replace_zone zone, const struct replace_rule * replace, size_t n_replace,
|
||||
const struct replace_rule ** selected, size_t n_selected)
|
||||
{
|
||||
size_t i = 0, j = 0;
|
||||
for (i = 0; i < n_replace && j < n_selected; i++)
|
||||
{
|
||||
if (replace[i].zone == zone)
|
||||
{
|
||||
selected[j] = replace + i;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
size_t replace_string(const char * in, size_t in_sz, const struct replace_rule * zone, char** out)
|
||||
{
|
||||
size_t replace_len = strlen(zone->replace_with);
|
||||
|
||||
assert(strlen(zone->find) != 0);
|
||||
|
||||
int error;
|
||||
PCRE2_SIZE erroffset;
|
||||
|
||||
const PCRE2_SPTR pattern = (PCRE2_SPTR)zone->find;
|
||||
const PCRE2_SPTR subject = (PCRE2_SPTR)in;
|
||||
const PCRE2_SPTR replacement = (PCRE2_SPTR)zone->replace_with;
|
||||
|
||||
pcre2_code *re = pcre2_compile(pattern, PCRE2_ZERO_TERMINATED, 0, &error, &erroffset, 0);
|
||||
if (re == 0)
|
||||
return -1;
|
||||
|
||||
pcre2_jit_compile(re, PCRE2_JIT_COMPLETE);
|
||||
|
||||
PCRE2_SIZE outbuff_size = in_sz+sizeof(replacement)*MAX_EDIT_MATCHES;
|
||||
PCRE2_SIZE outlen = 0;
|
||||
PCRE2_UCHAR* out_buffer = NULL;
|
||||
not_enough_mem_retry:
|
||||
out_buffer = (PCRE2_UCHAR*)malloc(sizeof(PCRE2_UCHAR)*outbuff_size);
|
||||
outlen = outbuff_size;
|
||||
int rc = pcre2_substitute(re, subject, in_sz, 0, PCRE2_SUBSTITUTE_GLOBAL | PCRE2_SUBSTITUTE_EXTENDED | PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, 0, 0, replacement, PCRE2_ZERO_TERMINATED, out_buffer, &outlen);
|
||||
if(outlen>outbuff_size)
|
||||
{
|
||||
outbuff_size=outlen;
|
||||
free(out_buffer);
|
||||
out_buffer=NULL;
|
||||
goto not_enough_mem_retry;
|
||||
}
|
||||
if(rc<=0)
|
||||
{
|
||||
free(out_buffer);
|
||||
outlen=rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out=(char*)out_buffer;
|
||||
}
|
||||
pcre2_code_free(re);
|
||||
return outlen;
|
||||
}
|
||||
|
||||
size_t execute_replace_rule(const char * in, size_t in_sz,
|
||||
enum replace_zone zone, const struct replace_rule * rules, size_t n_rule, char** out)
|
||||
{
|
||||
const struct replace_rule * todo[n_rule];
|
||||
size_t n_todo = 0, i = 0, interator_sz=0, pre_out_sz=0;
|
||||
const char * interator = NULL;
|
||||
char* new_out = NULL, * pre_out = NULL;
|
||||
size_t output_size=0;
|
||||
if (in_sz == 0 || in==NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
n_todo = select_replace_rule(zone, rules, n_rule, todo, n_rule);
|
||||
interator = in;
|
||||
interator_sz = in_sz;
|
||||
for (i = 0; i < n_todo; i++)
|
||||
{
|
||||
output_size = replace_string(interator, interator_sz, todo[i], &new_out);
|
||||
if (output_size == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pre_out != NULL)
|
||||
{
|
||||
free(pre_out);
|
||||
pre_out = NULL;
|
||||
}
|
||||
pre_out = new_out;
|
||||
pre_out_sz = output_size;
|
||||
|
||||
interator = new_out;
|
||||
interator_sz = output_size;
|
||||
|
||||
new_out=NULL;
|
||||
output_size=0;
|
||||
}
|
||||
if(pre_out_sz>0)
|
||||
{
|
||||
*out=pre_out;
|
||||
return pre_out_sz;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
void simple_replace(const char* find, const char* replacement, const char* input, size_t in_sz, char** output, size_t *output_sz)
|
||||
{
|
||||
char* exec_para=NULL;
|
||||
asprintf(&exec_para,"zone=http_resp_body;substitute=/%s/%s", find, replacement);
|
||||
size_t n_got_rule=0;
|
||||
struct replace_rule rules[16];
|
||||
n_got_rule=format_replace_rule(exec_para, rules, sizeof(rules)/sizeof(rules[0]));
|
||||
*output_sz=execute_replace_rule(input, strlen(input), kZoneResponseBody, rules, n_got_rule, output);
|
||||
free(exec_para);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user