diff options
| author | fengweihao <[email protected]> | 2022-09-09 10:44:11 +0800 |
|---|---|---|
| committer | fengweihao <[email protected]> | 2022-09-09 10:44:11 +0800 |
| commit | b321486e3fbd27d9e061c607e10c5a4bc5a32e33 (patch) | |
| tree | c5b059d2f97c7b4fc3f8936e3303a97c14cf275d /plugin/business/tsg-http/src/pattern_replace.cpp | |
| parent | e52bafad6bfd6916a1019af562b310bd8b2a8d85 (diff) | |
TSG-11849 tfe增加从环境变量中读入处理机ip
TSG-11742 IP Libraries统一使用.分隔地理层级
TSG-10722 日志中开始时间从解析层获取
Diffstat (limited to 'plugin/business/tsg-http/src/pattern_replace.cpp')
| -rw-r--r-- | plugin/business/tsg-http/src/pattern_replace.cpp | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/plugin/business/tsg-http/src/pattern_replace.cpp b/plugin/business/tsg-http/src/pattern_replace.cpp new file mode 100644 index 0000000..4b7f2ad --- /dev/null +++ b/plugin/business/tsg-http/src/pattern_replace.cpp @@ -0,0 +1,352 @@ +#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 <sys/stat.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 *__attribute__((__unused__)) +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 *__attribute__((__unused__)) +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 __attribute__((__unused__)) +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, int options) +{ + assert(strlen(zone->find) != 0); + + int error=0; + PCRE2_SIZE erroffset=0; + + const PCRE2_SPTR pattern = (PCRE2_SPTR)zone->find; + const PCRE2_SPTR subject = (PCRE2_SPTR)in; + const PCRE2_SPTR replacement = (PCRE2_SPTR)zone->replace_with; + uint32_t pcre2_options = options ? PCRE2_UTF : 0; + + pcre2_code *re = pcre2_compile(pattern, strlen(zone->find), pcre2_options, &error, &erroffset, 0); + if (!re) + return 0; + + 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, //pcre2_match_data *match_data, pcre2_match_context + replacement, strlen(zone->replace_with), + 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=0; + } + 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, int options) +{ + 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, options); + 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; + } +} + +static char *find_insert_position(char * in) +{ + char *insert_from = NULL; + char *script_local = NULL; + char *head_in = NULL; + + if (in == NULL) + { + return NULL; + } + + head_in = strstr(in, "</head>"); + insert_from = strstr(in, "jquery"); + if (insert_from != NULL && head_in != NULL && (head_in - insert_from) > 0) + { + script_local=strstr(insert_from, "</script>"); + if (script_local) + insert_from=script_local + sizeof("</script>"); + } + else + { + insert_from=head_in; + } + return insert_from; +} + +size_t insert_string(char * in, size_t in_sz, const char *insert_on, const char *script, const char *type, char** out) +{ + char *target=NULL; + size_t target_size=0; + + const char* js_style="<script type=\"text/javascript\" class=\"RQ_SCRIPT\">%s</script>"; + const char* css_style= "<style type=\"text/css\" class=\"RQ_SCRIPT\">%s</style>"; + const char* this_style=NULL; + size_t concat_len=0, concat_size=0; + char* concat_style=NULL; + char* insert_from=NULL; + size_t offset=0; + + if (script == NULL || in == NULL) + { + return 0; + } + + if (insert_on != NULL && 0==strcasecmp(insert_on, "after_page_load")) + { + insert_from=strstr(in, "</body>"); + } + else + { + insert_from=find_insert_position(in); + } + if(!insert_from) + { + return 0; + } + + if (0==strcasecmp(type, "css")) + { + this_style=css_style; + } + else if (0==strcasecmp(type, "js")) + { + this_style=js_style; + } + else + { + assert(0); + } + concat_size = strlen(script)+1+strlen(this_style); + concat_style = ALLOC(char, concat_size); + concat_len=snprintf(concat_style, concat_size, + this_style, + script); + + target_size = in_sz+concat_len; + target = ALLOC(char, target_size); + assert((unsigned int)(insert_from-in) <= target_size); + offset=0; + memcpy(target+offset, in, insert_from-in); + offset+=insert_from-in; + memcpy(target+offset, concat_style, concat_len); + offset+=concat_len; + memcpy(target+offset, insert_from, in_sz-(insert_from-in)); + offset+=in_sz-(insert_from-in); + assert(target_size==offset); + + free(concat_style); + concat_style = NULL; + *out=target; + return target_size; +} + +size_t execute_insert_rule(char * in, size_t in_sz, const struct insert_rule * rules, char** out) +{ + return insert_string(in, in_sz, rules->position, rules->script, rules->type, out); +} + +void simple_replace(const char* find, const char* replacement, const char* input, size_t in_sz, char** output, size_t *output_sz, int options) +{ + char* exec_para=NULL; + asprintf(&exec_para,"zone=http_resp_body;substitute=/%s/%s", find, replacement); + size_t n_got_rule=0, i=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, options); + for(i=0; i<n_got_rule; i++) + { + FREE(&(rules[i].find)); + FREE(&(rules[i].replace_with)); + } + free(exec_para); + return; +} + + |
