ACIL FM
Dark
Refresh
Current DIR:
/opt/imunify360-webshield/lualib/resty/core
/
opt
imunify360-webshield
lualib
resty
core
Upload
Zip Selected
Delete Selected
Pilih semua
Nama
Ukuran
Permission
Aksi
base.lua
5.4 MB
chmod
View
DL
Edit
Rename
Delete
base64.lua
3.06 MB
chmod
View
DL
Edit
Rename
Delete
coroutine.lua
769 B
chmod
View
DL
Edit
Rename
Delete
ctx.lua
3.71 MB
chmod
View
DL
Edit
Rename
Delete
exit.lua
1.41 MB
chmod
View
DL
Edit
Rename
Delete
hash.lua
3.92 MB
chmod
View
DL
Edit
Rename
Delete
misc.lua
5.7 MB
chmod
View
DL
Edit
Rename
Delete
ndk.lua
2.13 MB
chmod
View
DL
Edit
Rename
Delete
param.lua
2.35 MB
chmod
View
DL
Edit
Rename
Delete
phase.lua
1.48 MB
chmod
View
DL
Edit
Rename
Delete
regex.lua
34.61 MB
chmod
View
DL
Edit
Rename
Delete
request.lua
11.14 MB
chmod
View
DL
Edit
Rename
Delete
response.lua
6.21 MB
chmod
View
DL
Edit
Rename
Delete
shdict.lua
26.56 MB
chmod
View
DL
Edit
Rename
Delete
socket.lua
7.22 MB
chmod
View
DL
Edit
Rename
Delete
time.lua
4.64 MB
chmod
View
DL
Edit
Rename
Delete
uri.lua
3.03 MB
chmod
View
DL
Edit
Rename
Delete
utils.lua
972 B
chmod
View
DL
Edit
Rename
Delete
var.lua
3.82 MB
chmod
View
DL
Edit
Rename
Delete
worker.lua
3.41 MB
chmod
View
DL
Edit
Rename
Delete
Edit file: /opt/imunify360-webshield/lualib/resty/core/regex.lua
-- Copyright (C) Yichun Zhang (agentzh) local ffi = require 'ffi' local base = require "resty.core.base" local bit = require "bit" local subsystem = ngx.config.subsystem require "resty.core.time" -- for ngx.now used by resty.lrucache if subsystem == 'http' then require "resty.core.phase" -- for ngx.get_phase end local lrucache = require "resty.lrucache" local lrucache_get = lrucache.get local lrucache_set = lrucache.set local ffi_string = ffi.string local ffi_gc = ffi.gc local ffi_copy = ffi.copy local ffi_cast = ffi.cast local C = ffi.C local bor = bit.bor local band = bit.band local lshift = bit.lshift local sub = string.sub local fmt = string.format local byte = string.byte local ngx = ngx local type = type local tostring = tostring local error = error local setmetatable = setmetatable local tonumber = tonumber local get_string_buf = base.get_string_buf local get_string_buf_size = base.get_string_buf_size local new_tab = base.new_tab local ngx_phase = ngx.get_phase local ngx_log = ngx.log local ngx_NOTICE = ngx.NOTICE local _M = { version = base.version } ngx.re = new_tab(0, 5) local pcre_ver_fn if subsystem == 'http' then ffi.cdef[[ const char *ngx_http_lua_ffi_pcre_version(void); ]] pcre_ver_fn = C.ngx_http_lua_ffi_pcre_version elseif subsystem == 'stream' then ffi.cdef[[ const char *ngx_stream_lua_ffi_pcre_version(void); ]] pcre_ver_fn = C.ngx_stream_lua_ffi_pcre_version else error("unsupported subsystem: " .. tostring(subsystem)) end local pcre_ver if not pcall(function() pcre_ver = ffi_string(pcre_ver_fn()) end) then setmetatable(ngx.re, { __index = function(_, key) error("no support for 'ngx.re." .. key .. "': OpenResty was " .. "compiled without PCRE support", 2) end }) _M.no_pcre = true return _M end local MAX_ERR_MSG_LEN = 256 local FLAG_COMPILE_ONCE = 0x01 local FLAG_DFA = 0x02 local FLAG_JIT = 0x04 local FLAG_DUPNAMES = 0x08 local FLAG_NO_UTF8_CHECK = 0x10 local PCRE_CASELESS = 0x0000001 local PCRE_MULTILINE = 0x0000002 local PCRE_DOTALL = 0x0000004 local PCRE_EXTENDED = 0x0000008 local PCRE_ANCHORED = 0x0000010 local PCRE_UTF8 = 0x0000800 local PCRE_DUPNAMES = 0x0080000 local PCRE_JAVASCRIPT_COMPAT = 0x2000000 -- PCRE2_ERROR_NOMATCH uses the same value local PCRE_ERROR_NOMATCH = -1 local regex_match_cache local regex_sub_func_cache = new_tab(0, 4) local regex_sub_str_cache = new_tab(0, 4) local max_regex_cache_size local regex_cache_size = 0 local script_engine local ngx_lua_ffi_max_regex_cache_size local ngx_lua_ffi_destroy_regex local ngx_lua_ffi_compile_regex local ngx_lua_ffi_exec_regex local ngx_lua_ffi_create_script_engine local ngx_lua_ffi_destroy_script_engine local ngx_lua_ffi_init_script_engine local ngx_lua_ffi_compile_replace_template local ngx_lua_ffi_script_eval_len local ngx_lua_ffi_script_eval_data -- PCRE 8.43 on macOS introduced the MAP_JIT option when creating the memory -- region used to store JIT compiled code, which does not survive across -- `fork()`, causing further usage of PCRE JIT compiler to segfault in worker -- processes. -- -- This flag prevents any regex used in the init phase to be JIT compiled or -- cached when running under macOS, even if the user requests so. Caching is -- thus disabled to prevent further calls of same regex in worker to have poor -- performance. -- -- TODO: improve this workaround when PCRE allows for unspecifying the MAP_JIT -- option. local no_jit_in_init local pcre_ver_num local maj, min = string.match(pcre_ver, "^(%d+)%.(%d+)") if maj and min then pcre_ver_num = tonumber(maj .. min) end if jit.os == "OSX" then if pcre_ver_num == nil then -- assume this version is faulty as well no_jit_in_init = true -- PCRE2 is also subject to this issue on macOS elseif pcre_ver_num >= 843 then no_jit_in_init = true end end -- pcre2 if pcre_ver_num > 845 then -- option PCRE_CASELESS = 0x00000008 PCRE_MULTILINE = 0x00000400 PCRE_DOTALL = 0x00000020 PCRE_EXTENDED = 0x00000080 PCRE_ANCHORED = 0x80000000 PCRE_UTF8 = 0x00080000 PCRE_DUPNAMES = 0x00000040 -- In the pcre2, The PCRE_JAVASCRIPT_COMPAT option has been split into -- independent functional options PCRE2_ALT_BSUX, PCRE2_ALLOW_EMPTY_CLASS, -- and PCRE2_MATCH_UNSET_BACKREF. local PCRE2_ALT_BSUX = 0x00000002 local PCRE2_ALLOW_EMPTY_CLASS = 0x00000001 local PCRE2_MATCH_UNSET_BACKREF = 0x00000200 PCRE_JAVASCRIPT_COMPAT = bor(PCRE2_ALT_BSUX, PCRE2_ALLOW_EMPTY_CLASS) PCRE_JAVASCRIPT_COMPAT = bor(PCRE2_MATCH_UNSET_BACKREF, PCRE_JAVASCRIPT_COMPAT) end if subsystem == 'http' then ffi.cdef[[ typedef struct { ngx_str_t value; void *lengths; void *values; } ngx_http_lua_complex_value_t; typedef struct { void *pool; unsigned char *name_table; int name_count; int name_entry_size; int ncaptures; int *captures; void *regex; void *regex_sd; ngx_http_lua_complex_value_t *replace; const char *pattern; } ngx_http_lua_regex_t; ngx_http_lua_regex_t * ngx_http_lua_ffi_compile_regex(const unsigned char *pat, size_t pat_len, int flags, int pcre_opts, unsigned char *errstr, size_t errstr_size); int ngx_http_lua_ffi_exec_regex(ngx_http_lua_regex_t *re, int flags, const unsigned char *s, size_t len, int pos); void ngx_http_lua_ffi_destroy_regex(ngx_http_lua_regex_t *re); int ngx_http_lua_ffi_compile_replace_template(ngx_http_lua_regex_t *re, const unsigned char *replace_data, size_t replace_len); struct ngx_http_lua_script_engine_s; typedef struct ngx_http_lua_script_engine_s *ngx_http_lua_script_engine_t; ngx_http_lua_script_engine_t *ngx_http_lua_ffi_create_script_engine(void); void ngx_http_lua_ffi_init_script_engine(ngx_http_lua_script_engine_t *e, const unsigned char *subj, ngx_http_lua_regex_t *compiled, int count); void ngx_http_lua_ffi_destroy_script_engine( ngx_http_lua_script_engine_t *e); size_t ngx_http_lua_ffi_script_eval_len(ngx_http_lua_script_engine_t *e, ngx_http_lua_complex_value_t *cv); size_t ngx_http_lua_ffi_script_eval_data(ngx_http_lua_script_engine_t *e, ngx_http_lua_complex_value_t *cv, unsigned char *dst); uint32_t ngx_http_lua_ffi_max_regex_cache_size(void); ]] ngx_lua_ffi_max_regex_cache_size = C.ngx_http_lua_ffi_max_regex_cache_size ngx_lua_ffi_destroy_regex = C.ngx_http_lua_ffi_destroy_regex ngx_lua_ffi_compile_regex = C.ngx_http_lua_ffi_compile_regex ngx_lua_ffi_exec_regex = C.ngx_http_lua_ffi_exec_regex ngx_lua_ffi_create_script_engine = C.ngx_http_lua_ffi_create_script_engine ngx_lua_ffi_init_script_engine = C.ngx_http_lua_ffi_init_script_engine ngx_lua_ffi_destroy_script_engine = C.ngx_http_lua_ffi_destroy_script_engine ngx_lua_ffi_compile_replace_template = C.ngx_http_lua_ffi_compile_replace_template ngx_lua_ffi_script_eval_len = C.ngx_http_lua_ffi_script_eval_len ngx_lua_ffi_script_eval_data = C.ngx_http_lua_ffi_script_eval_data elseif subsystem == 'stream' then ffi.cdef[[ typedef struct { ngx_str_t value; void *lengths; void *values; } ngx_stream_lua_complex_value_t; typedef struct { void *pool; unsigned char *name_table; int name_count; int name_entry_size; int ncaptures; int *captures; void *regex; void *regex_sd; ngx_stream_lua_complex_value_t *replace; const char *pattern; } ngx_stream_lua_regex_t; ngx_stream_lua_regex_t * ngx_stream_lua_ffi_compile_regex(const unsigned char *pat, size_t pat_len, int flags, int pcre_opts, unsigned char *errstr, size_t errstr_size); int ngx_stream_lua_ffi_exec_regex(ngx_stream_lua_regex_t *re, int flags, const unsigned char *s, size_t len, int pos); void ngx_stream_lua_ffi_destroy_regex(ngx_stream_lua_regex_t *re); int ngx_stream_lua_ffi_compile_replace_template(ngx_stream_lua_regex_t *re, const unsigned char *replace_data, size_t replace_len); struct ngx_stream_lua_script_engine_s; typedef struct ngx_stream_lua_script_engine_s *ngx_stream_lua_script_engine_t; ngx_stream_lua_script_engine_t * ngx_stream_lua_ffi_create_script_engine(void); void ngx_stream_lua_ffi_init_script_engine( ngx_stream_lua_script_engine_t *e, const unsigned char *subj, ngx_stream_lua_regex_t *compiled, int count); void ngx_stream_lua_ffi_destroy_script_engine( ngx_stream_lua_script_engine_t *e); size_t ngx_stream_lua_ffi_script_eval_len( ngx_stream_lua_script_engine_t *e, ngx_stream_lua_complex_value_t *cv); size_t ngx_stream_lua_ffi_script_eval_data( ngx_stream_lua_script_engine_t *e, ngx_stream_lua_complex_value_t *cv, unsigned char *dst); uint32_t ngx_stream_lua_ffi_max_regex_cache_size(void); ]] ngx_lua_ffi_max_regex_cache_size = C.ngx_stream_lua_ffi_max_regex_cache_size ngx_lua_ffi_destroy_regex = C.ngx_stream_lua_ffi_destroy_regex ngx_lua_ffi_compile_regex = C.ngx_stream_lua_ffi_compile_regex ngx_lua_ffi_exec_regex = C.ngx_stream_lua_ffi_exec_regex ngx_lua_ffi_create_script_engine = C.ngx_stream_lua_ffi_create_script_engine ngx_lua_ffi_init_script_engine = C.ngx_stream_lua_ffi_init_script_engine ngx_lua_ffi_destroy_script_engine = C.ngx_stream_lua_ffi_destroy_script_engine ngx_lua_ffi_compile_replace_template = C.ngx_stream_lua_ffi_compile_replace_template ngx_lua_ffi_script_eval_len = C.ngx_stream_lua_ffi_script_eval_len ngx_lua_ffi_script_eval_data = C.ngx_stream_lua_ffi_script_eval_data end local c_str_type = ffi.typeof("const char *") local cached_re_opts = new_tab(0, 4) local buf_grow_ratio = 2 function _M.set_buf_grow_ratio(ratio) buf_grow_ratio = ratio end local function get_max_regex_cache_size() if max_regex_cache_size then return max_regex_cache_size end max_regex_cache_size = ngx_lua_ffi_max_regex_cache_size() return max_regex_cache_size end local regex_cache_is_empty = true function _M.is_regex_cache_empty() return regex_cache_is_empty end local function lrucache_set_wrapper(...) regex_cache_is_empty = false lrucache_set(...) end local parse_regex_opts = function (opts) local t = cached_re_opts[opts] if t then return t[1], t[2] end local flags = 0 local pcre_opts = 0 local len = #opts for i = 1, len do local opt = byte(opts, i) if opt == byte("o") then flags = bor(flags, FLAG_COMPILE_ONCE) elseif opt == byte("j") then flags = bor(flags, FLAG_JIT) elseif opt == byte("i") then pcre_opts = bor(pcre_opts, PCRE_CASELESS) elseif opt == byte("s") then pcre_opts = bor(pcre_opts, PCRE_DOTALL) elseif opt == byte("m") then pcre_opts = bor(pcre_opts, PCRE_MULTILINE) elseif opt == byte("u") then pcre_opts = bor(pcre_opts, PCRE_UTF8) elseif opt == byte("U") then pcre_opts = bor(pcre_opts, PCRE_UTF8) flags = bor(flags, FLAG_NO_UTF8_CHECK) elseif opt == byte("x") then pcre_opts = bor(pcre_opts, PCRE_EXTENDED) elseif opt == byte("d") then flags = bor(flags, FLAG_DFA) elseif opt == byte("a") then pcre_opts = bor(pcre_opts, PCRE_ANCHORED) elseif opt == byte("D") then pcre_opts = bor(pcre_opts, PCRE_DUPNAMES) flags = bor(flags, FLAG_DUPNAMES) elseif opt == byte("J") then pcre_opts = bor(pcre_opts, PCRE_JAVASCRIPT_COMPAT) else error(fmt('unknown flag "%s" (flags "%s")', sub(opts, i, i), opts), 3) end end cached_re_opts[opts] = {flags, pcre_opts} return flags, pcre_opts end if no_jit_in_init then local parse_regex_opts_ = parse_regex_opts parse_regex_opts = function (opts) if ngx_phase() ~= "init" then -- past init_by_lua* phase now parse_regex_opts = parse_regex_opts_ return parse_regex_opts(opts) end local t = cached_re_opts[opts] if t then return t[1], t[2] end local flags = 0 local pcre_opts = 0 local len = #opts for i = 1, len do local opt = byte(opts, i) if opt == byte("o") then ngx_log(ngx_NOTICE, "regex compilation cache disabled in init ", "phase under macOS") elseif opt == byte("j") then ngx_log(ngx_NOTICE, "regex compilation disabled in init ", "phase under macOS") elseif opt == byte("i") then pcre_opts = bor(pcre_opts, PCRE_CASELESS) elseif opt == byte("s") then pcre_opts = bor(pcre_opts, PCRE_DOTALL) elseif opt == byte("m") then pcre_opts = bor(pcre_opts, PCRE_MULTILINE) elseif opt == byte("u") then pcre_opts = bor(pcre_opts, PCRE_UTF8) elseif opt == byte("U") then pcre_opts = bor(pcre_opts, PCRE_UTF8) flags = bor(flags, FLAG_NO_UTF8_CHECK) elseif opt == byte("x") then pcre_opts = bor(pcre_opts, PCRE_EXTENDED) elseif opt == byte("d") then flags = bor(flags, FLAG_DFA) elseif opt == byte("a") then pcre_opts = bor(pcre_opts, PCRE_ANCHORED) elseif opt == byte("D") then pcre_opts = bor(pcre_opts, PCRE_DUPNAMES) flags = bor(flags, FLAG_DUPNAMES) elseif opt == byte("J") then pcre_opts = bor(pcre_opts, PCRE_JAVASCRIPT_COMPAT) else error(fmt('unknown flag "%s" (flags "%s")', sub(opts, i, i), opts), 3) end end cached_re_opts[opts] = {flags, pcre_opts} return flags, pcre_opts end end local function collect_named_captures(compiled, flags, res) local name_count = compiled.name_count local name_table = compiled.name_table local entry_size = compiled.name_entry_size local ind = 0 local dup_names = (band(flags, FLAG_DUPNAMES) ~= 0) for i = 1, name_count do local n = bor(lshift(name_table[ind], 8), name_table[ind + 1]) -- ngx.say("n = ", n) local name = ffi_string(name_table + ind + 2) local cap = res[n] if dup_names then -- unmatched captures (false) are not collected if cap then local old = res[name] if old then old[#old + 1] = cap else res[name] = {cap} end end else res[name] = cap end ind = ind + entry_size end end local function collect_captures(compiled, rc, subj, flags, res) local cap = compiled.captures local ncap = compiled.ncaptures local name_count = compiled.name_count if not res then res = new_tab(ncap, name_count) end local i = 0 local n = 0 while i <= ncap do if i > rc then res[i] = false else local from = cap[n] if from >= 0 then local to = cap[n + 1] res[i] = sub(subj, from + 1, to) else res[i] = false end end i = i + 1 n = n + 2 end if name_count > 0 then collect_named_captures(compiled, flags, res) end return res end _M.collect_captures = collect_captures local function destroy_compiled_regex(compiled) ngx_lua_ffi_destroy_regex(ffi_gc(compiled, nil)) end _M.destroy_compiled_regex = destroy_compiled_regex local function re_match_compile(regex, opts) local flags = 0 local pcre_opts = 0 if opts then flags, pcre_opts = parse_regex_opts(opts) else opts = "" end local compiled, key local compile_once = (band(flags, FLAG_COMPILE_ONCE) == 1) -- FIXME: better put this in the outer scope when fixing the ngx.re API's -- compatibility in the init_by_lua* context. if not regex_match_cache then local sz = get_max_regex_cache_size() if sz <= 0 then compile_once = false else regex_match_cache = lrucache.new(sz) end end if compile_once then key = regex .. '\0' .. opts compiled = lrucache_get(regex_match_cache, key) end -- compile the regex if compiled == nil then -- print("compiled regex not found, compiling regex...") local errbuf = get_string_buf(MAX_ERR_MSG_LEN) compiled = ngx_lua_ffi_compile_regex(regex, #regex, flags, pcre_opts, errbuf, MAX_ERR_MSG_LEN) if compiled == nil then return nil, ffi_string(errbuf) end ffi_gc(compiled, ngx_lua_ffi_destroy_regex) -- print("ncaptures: ", compiled.ncaptures) if compile_once then -- print("inserting compiled regex into cache") lrucache_set_wrapper(regex_match_cache, key, compiled) end end return compiled, compile_once, flags end _M.re_match_compile = re_match_compile local function re_match_helper(subj, regex, opts, ctx, want_caps, res, nth) -- we need to cast this to strings to avoid exceptions when they are -- something else. subj = tostring(subj) local compiled, compile_once, flags = re_match_compile(regex, opts) if compiled == nil then -- compiled_once holds the error string if not want_caps then return nil, nil, compile_once end return nil, compile_once end -- exec the compiled regex local rc do local pos if ctx then pos = ctx.pos if not pos or pos <= 0 then pos = 0 else pos = pos - 1 end else pos = 0 end rc = ngx_lua_ffi_exec_regex(compiled, flags, subj, #subj, pos) end if rc == PCRE_ERROR_NOMATCH then if not compile_once then destroy_compiled_regex(compiled) end return nil end if rc < 0 then if not compile_once then destroy_compiled_regex(compiled) end if not want_caps then return nil, nil, "pcre_exec() failed: " .. rc end return nil, "pcre_exec() failed: " .. rc end if rc == 0 then if band(flags, FLAG_DFA) == 0 then if not want_caps then return nil, nil, "capture size too small" end return nil, "capture size too small" end rc = 1 end -- print("cap 0: ", compiled.captures[0]) -- print("cap 1: ", compiled.captures[1]) if ctx then ctx.pos = compiled.captures[1] + 1 end if not want_caps then if not nth or nth < 0 then nth = 0 end if nth > compiled.ncaptures then return nil, nil, "nth out of bound" end if nth >= rc then return nil, nil end local from = compiled.captures[nth * 2] + 1 local to = compiled.captures[nth * 2 + 1] if from < 0 or to < 0 then return nil, nil end return from, to end res = collect_captures(compiled, rc, subj, flags, res) if not compile_once then destroy_compiled_regex(compiled) end return res end function ngx.re.match(subj, regex, opts, ctx, res) return re_match_helper(subj, regex, opts, ctx, true, res) end function ngx.re.find(subj, regex, opts, ctx, nth) return re_match_helper(subj, regex, opts, ctx, false, nil, nth) end do local function destroy_re_gmatch_iterator(iterator) if not iterator._compile_once then destroy_compiled_regex(iterator._compiled) end iterator._compiled = nil iterator._pos = nil iterator._subj = nil end local function iterate_re_gmatch(self) local compiled = self._compiled local subj = self._subj local subj_len = self._subj_len local flags = self._flags local pos = self._pos if not pos then -- The iterator is exhausted. return nil end local rc = ngx_lua_ffi_exec_regex(compiled, flags, subj, subj_len, pos) if rc == PCRE_ERROR_NOMATCH then destroy_re_gmatch_iterator(self) return nil end if rc < 0 then destroy_re_gmatch_iterator(self) return nil, "pcre_exec() failed: " .. rc end if rc == 0 then if band(flags, FLAG_DFA) == 0 then destroy_re_gmatch_iterator(self) return nil, "capture size too small" end rc = 1 end local cp_pos = tonumber(compiled.captures[1]) if cp_pos == compiled.captures[0] then cp_pos = cp_pos + 1 if cp_pos > subj_len then local res = collect_captures(compiled, rc, subj, flags) destroy_re_gmatch_iterator(self) return res end end self._pos = cp_pos return collect_captures(compiled, rc, subj, flags) end local re_gmatch_iterator_mt = { __call = iterate_re_gmatch } function ngx.re.gmatch(subj, regex, opts) subj = tostring(subj) local compiled, compile_once, flags = re_match_compile(regex, opts) if compiled == nil then -- compiled_once holds the error string return nil, compile_once end local re_gmatch_iterator = { _compiled = compiled, _compile_once = compile_once, _subj = subj, _subj_len = #subj, _flags = flags, _pos = 0, } return setmetatable(re_gmatch_iterator, re_gmatch_iterator_mt) end end -- do local function new_script_engine(subj, compiled, count) if not script_engine then script_engine = ngx_lua_ffi_create_script_engine() if script_engine == nil then return nil end ffi_gc(script_engine, ngx_lua_ffi_destroy_script_engine) end ngx_lua_ffi_init_script_engine(script_engine, subj, compiled, count) return script_engine end local function check_buf_size(buf, buf_size, pos, len, new_len, must_alloc) if new_len > buf_size then buf_size = buf_size * buf_grow_ratio if buf_size < new_len then buf_size = new_len end local new_buf = get_string_buf(buf_size, must_alloc) ffi_copy(new_buf, buf, len) buf = new_buf pos = buf + len end return buf, buf_size, pos, new_len end _M.check_buf_size = check_buf_size local function re_sub_compile(regex, opts, replace, func) local flags = 0 local pcre_opts = 0 if opts then flags, pcre_opts = parse_regex_opts(opts) else opts = "" end local compiled local compile_once = (band(flags, FLAG_COMPILE_ONCE) == 1) if compile_once then if func then local subcache = regex_sub_func_cache[opts] if subcache then -- print("cache hit!") compiled = subcache[regex] end else local subcache = regex_sub_str_cache[opts] if subcache then local subsubcache = subcache[regex] if subsubcache then -- print("cache hit!") compiled = subsubcache[replace] end end end end -- compile the regex if compiled == nil then -- print("compiled regex not found, compiling regex...") local errbuf = get_string_buf(MAX_ERR_MSG_LEN) compiled = ngx_lua_ffi_compile_regex(regex, #regex, flags, pcre_opts, errbuf, MAX_ERR_MSG_LEN) if compiled == nil then return nil, ffi_string(errbuf) end ffi_gc(compiled, ngx_lua_ffi_destroy_regex) if func == nil then local rc = ngx_lua_ffi_compile_replace_template(compiled, replace, #replace) if rc ~= 0 then if not compile_once then destroy_compiled_regex(compiled) end return nil, "failed to compile the replacement template" end end -- print("ncaptures: ", compiled.ncaptures) if compile_once then if regex_cache_size < get_max_regex_cache_size() then -- print("inserting compiled regex into cache") if func then local subcache = regex_sub_func_cache[opts] if not subcache then regex_sub_func_cache[opts] = {[regex] = compiled} else subcache[regex] = compiled end else local subcache = regex_sub_str_cache[opts] if not subcache then regex_sub_str_cache[opts] = {[regex] = {[replace] = compiled}} else local subsubcache = subcache[regex] if not subsubcache then subcache[regex] = {[replace] = compiled} else subsubcache[replace] = compiled end end end regex_cache_size = regex_cache_size + 1 else compile_once = false end end end return compiled, compile_once, flags end _M.re_sub_compile = re_sub_compile local function re_sub_func_helper(subj, regex, replace, opts, global) local compiled, compile_once, flags = re_sub_compile(regex, opts, nil, replace) if not compiled then -- error string is in compile_once return nil, nil, compile_once end -- exec the compiled regex subj = tostring(subj) local subj_len = #subj local count = 0 local pos = 0 local cp_pos = 0 local dst_buf_size = get_string_buf_size() -- Note: we have to always allocate the string buffer because -- the user might call whatever resty.core's API functions recursively -- in the user callback function. local dst_buf = get_string_buf(dst_buf_size, true) local dst_pos = dst_buf local dst_len = 0 while true do local rc = ngx_lua_ffi_exec_regex(compiled, flags, subj, subj_len, pos) if rc == PCRE_ERROR_NOMATCH then break end if rc < 0 then if not compile_once then destroy_compiled_regex(compiled) end return nil, nil, "pcre_exec() failed: " .. rc end if rc == 0 then if band(flags, FLAG_DFA) == 0 then if not compile_once then destroy_compiled_regex(compiled) end return nil, nil, "capture size too small" end rc = 1 end count = count + 1 local prefix_len = compiled.captures[0] - cp_pos local res = collect_captures(compiled, rc, subj, flags) local piece = tostring(replace(res)) local piece_len = #piece local new_dst_len = dst_len + prefix_len + piece_len dst_buf, dst_buf_size, dst_pos, dst_len = check_buf_size(dst_buf, dst_buf_size, dst_pos, dst_len, new_dst_len, true) if prefix_len > 0 then ffi_copy(dst_pos, ffi_cast(c_str_type, subj) + cp_pos, prefix_len) dst_pos = dst_pos + prefix_len end if piece_len > 0 then ffi_copy(dst_pos, piece, piece_len) dst_pos = dst_pos + piece_len end cp_pos = compiled.captures[1] pos = cp_pos if pos == compiled.captures[0] then pos = pos + 1 if pos > subj_len then break end end if not global then break end end if not compile_once then destroy_compiled_regex(compiled) end if count > 0 then if cp_pos < subj_len then local suffix_len = subj_len - cp_pos local new_dst_len = dst_len + suffix_len local _ dst_buf, _, dst_pos, dst_len = check_buf_size(dst_buf, dst_buf_size, dst_pos, dst_len, new_dst_len, true) ffi_copy(dst_pos, ffi_cast(c_str_type, subj) + cp_pos, suffix_len) end return ffi_string(dst_buf, dst_len), count end return subj, 0 end local function re_sub_str_helper(subj, regex, replace, opts, global) local compiled, compile_once, flags = re_sub_compile(regex, opts, replace, nil) if not compiled then -- error string is in compile_once return nil, nil, compile_once end -- exec the compiled regex subj = tostring(subj) local subj_len = #subj local count = 0 local pos = 0 local cp_pos = 0 local dst_buf_size = get_string_buf_size() local dst_buf = get_string_buf(dst_buf_size) local dst_pos = dst_buf local dst_len = 0 while true do local rc = ngx_lua_ffi_exec_regex(compiled, flags, subj, subj_len, pos) if rc == PCRE_ERROR_NOMATCH then break end if rc < 0 then if not compile_once then destroy_compiled_regex(compiled) end return nil, nil, "pcre_exec() failed: " .. rc end if rc == 0 then if band(flags, FLAG_DFA) == 0 then if not compile_once then destroy_compiled_regex(compiled) end return nil, nil, "capture size too small" end rc = 1 end count = count + 1 local prefix_len = compiled.captures[0] - cp_pos local cv = compiled.replace if cv.lengths ~= nil then local e = new_script_engine(subj, compiled, rc) if e == nil then return nil, nil, "failed to create script engine" end local bit_len = ngx_lua_ffi_script_eval_len(e, cv) local new_dst_len = dst_len + prefix_len + bit_len dst_buf, dst_buf_size, dst_pos, dst_len = check_buf_size(dst_buf, dst_buf_size, dst_pos, dst_len, new_dst_len) if prefix_len > 0 then ffi_copy(dst_pos, ffi_cast(c_str_type, subj) + cp_pos, prefix_len) dst_pos = dst_pos + prefix_len end if bit_len > 0 then ngx_lua_ffi_script_eval_data(e, cv, dst_pos) dst_pos = dst_pos + bit_len end else local bit_len = cv.value.len dst_buf, dst_buf_size, dst_pos, dst_len = check_buf_size(dst_buf, dst_buf_size, dst_pos, dst_len, dst_len + prefix_len + bit_len) if prefix_len > 0 then ffi_copy(dst_pos, ffi_cast(c_str_type, subj) + cp_pos, prefix_len) dst_pos = dst_pos + prefix_len end if bit_len > 0 then ffi_copy(dst_pos, cv.value.data, bit_len) dst_pos = dst_pos + bit_len end end cp_pos = compiled.captures[1] pos = cp_pos if pos == compiled.captures[0] then pos = pos + 1 if pos > subj_len then break end end if not global then break end end if not compile_once then destroy_compiled_regex(compiled) end if count > 0 then if cp_pos < subj_len then local suffix_len = subj_len - cp_pos local new_dst_len = dst_len + suffix_len local _ dst_buf, _, dst_pos, dst_len = check_buf_size(dst_buf, dst_buf_size, dst_pos, dst_len, new_dst_len) ffi_copy(dst_pos, ffi_cast(c_str_type, subj) + cp_pos, suffix_len) end return ffi_string(dst_buf, dst_len), count end return subj, 0 end local function re_sub_helper(subj, regex, replace, opts, global) local repl_type = type(replace) if repl_type == "function" then return re_sub_func_helper(subj, regex, replace, opts, global) end if repl_type ~= "string" then replace = tostring(replace) end return re_sub_str_helper(subj, regex, replace, opts, global) end function ngx.re.sub(subj, regex, replace, opts) return re_sub_helper(subj, regex, replace, opts, false) end function ngx.re.gsub(subj, regex, replace, opts) return re_sub_helper(subj, regex, replace, opts, true) end return _M
Simpan
Batal
Isi Zip:
Unzip
Create
Buat Folder
Buat File
Terminal / Execute
Run
Chmod Bulk
All File
All Folder
All File dan Folder
Apply