404

[ Avaa Bypassed ]




Upload:

Command:

elspacio@3.147.83.181: ~ $
-- Copyright (C) by OpenResty Inc.


local base = require "resty.core.base"
base.allows_subsystem("http")


require "resty.core.phase"  -- for ngx.get_phase

local assert = assert
local error = error
local ipairs = ipairs
local tonumber = tonumber
local tostring = tostring
local type = type
local str_find = string.find
local table_concat = table.concat
local ffi = require "ffi"
local C = ffi.C
local ffi_new = ffi.new
local ffi_str = ffi.string
local ngx_phase = ngx.get_phase
local get_string_buf = base.get_string_buf
local get_size_ptr = base.get_size_ptr
local get_request = base.get_request
local FFI_AGAIN = base.FFI_AGAIN
local FFI_BAD_CONTEXT = base.FFI_BAD_CONTEXT
local FFI_DECLINED = base.FFI_DECLINED
local FFI_ERROR = base.FFI_ERROR
local FFI_NO_REQ_CTX = base.FFI_NO_REQ_CTX
local FFI_OK = base.FFI_OK
local co_yield = coroutine._yield


ffi.cdef[[
typedef int                         ngx_pid_t;
typedef uintptr_t                   ngx_msec_t;
typedef unsigned char               u_char;
typedef struct ngx_http_lua_pipe_s  ngx_http_lua_pipe_t;

typedef struct {
    ngx_pid_t               _pid;
    ngx_msec_t              write_timeout;
    ngx_msec_t              stdout_read_timeout;
    ngx_msec_t              stderr_read_timeout;
    ngx_msec_t              wait_timeout;
    ngx_http_lua_pipe_t    *pipe;
} ngx_http_lua_ffi_pipe_proc_t;

int ngx_http_lua_ffi_pipe_spawn(ngx_http_request_t *r,
    ngx_http_lua_ffi_pipe_proc_t *proc,
    const char *file, const char **argv, int merge_stderr, size_t buffer_size,
    const char **environ, u_char *errbuf, size_t *errbuf_size);

int ngx_http_lua_ffi_pipe_proc_read(ngx_http_request_t *r,
    ngx_http_lua_ffi_pipe_proc_t *proc, int from_stderr, int reader_type,
    size_t length, u_char **buf, size_t *buf_size, u_char *errbuf,
    size_t *errbuf_size);

int ngx_http_lua_ffi_pipe_get_read_result(ngx_http_request_t *r,
    ngx_http_lua_ffi_pipe_proc_t *proc, int from_stderr, u_char **buf,
    size_t *buf_size, u_char *errbuf, size_t *errbuf_size);

ssize_t ngx_http_lua_ffi_pipe_proc_write(ngx_http_request_t *r,
    ngx_http_lua_ffi_pipe_proc_t *proc, const u_char *data, size_t len,
    u_char *errbuf, size_t *errbuf_size);

ssize_t ngx_http_lua_ffi_pipe_get_write_result(ngx_http_request_t *r,
    ngx_http_lua_ffi_pipe_proc_t *proc, u_char *errbuf, size_t *errbuf_size);

int ngx_http_lua_ffi_pipe_proc_shutdown_stdin(
    ngx_http_lua_ffi_pipe_proc_t *proc, u_char *errbuf, size_t *errbuf_size);

int ngx_http_lua_ffi_pipe_proc_shutdown_stdout(
    ngx_http_lua_ffi_pipe_proc_t *proc, u_char *errbuf, size_t *errbuf_size);

int ngx_http_lua_ffi_pipe_proc_shutdown_stderr(
    ngx_http_lua_ffi_pipe_proc_t *proc, u_char *errbuf, size_t *errbuf_size);

int ngx_http_lua_ffi_pipe_proc_wait(ngx_http_request_t *r,
    ngx_http_lua_ffi_pipe_proc_t *proc, char **reason, int *status,
    u_char *errbuf, size_t *errbuf_size);

int ngx_http_lua_ffi_pipe_proc_kill(ngx_http_lua_ffi_pipe_proc_t *proc,
    int signal, u_char *errbuf, size_t *errbuf_size);

void ngx_http_lua_ffi_pipe_proc_destroy(ngx_http_lua_ffi_pipe_proc_t *proc);
]]


if not pcall(function() return C.ngx_http_lua_ffi_pipe_spawn end) then
    error("pipe API is not supported due to either a platform issue " ..
          "or lack of the HAVE_SOCKET_CLOEXEC_PATCH patch", 2)
end


local _M = { version = base.version }


local ERR_BUF_SIZE = 256
local VALUE_BUF_SIZE = 512
local PIPE_READ_ALL   = 0
local PIPE_READ_BYTES = 1
local PIPE_READ_LINE  = 2
local PIPE_READ_ANY   = 3


local proc_set_timeouts
do
    local MAX_TIMEOUT = 0xffffffff

    function proc_set_timeouts(proc, write_timeout, stdout_read_timeout,
                               stderr_read_timeout, wait_timeout)

        -- the implementation below is straightforward but could not be JIT
        -- compiled by the latest LuaJIT. When called in loops, LuaJIT will try
        -- to unroll it, and fall back to interpreter after it reaches the
        -- unroll limit.
        --[[
        local function set_timeout(proc, attr, timeout)
            if timeout then
                if timeout > MAX_TIMEOUT then
                    error("bad timeout value", 3)
                end
                proc[attr] = timeout
            end
        end
        set_timeout(...)
        ]]

        if write_timeout then
            if write_timeout < 0 or MAX_TIMEOUT < write_timeout then
                error("bad write_timeout option", 3)
            end

            proc.write_timeout = write_timeout
        end

        if stdout_read_timeout then
            if stdout_read_timeout < 0 or MAX_TIMEOUT < stdout_read_timeout then
                error("bad stdout_read_timeout option", 3)
            end

            proc.stdout_read_timeout = stdout_read_timeout
        end

        if stderr_read_timeout then
            if stderr_read_timeout < 0 or MAX_TIMEOUT < stderr_read_timeout then
                error("bad stderr_read_timeout option", 3)
            end

            proc.stderr_read_timeout = stderr_read_timeout
        end

        if wait_timeout then
            if wait_timeout < 0 or MAX_TIMEOUT < wait_timeout then
                error("bad wait_timeout option", 3)
            end

            proc.wait_timeout = wait_timeout
        end
    end
end


local function check_proc_instance(proc)
    if type(proc) ~= "cdata" then
        error("not a process instance", 3)
    end
end


local proc_read
do
    local value_buf = ffi_new("char[?]", VALUE_BUF_SIZE)
    local buf = ffi_new("char *[1]")
    local buf_size = ffi_new("size_t[1]")

    function proc_read(proc, stderr, reader_type, len)
        check_proc_instance(proc)

        local r = get_request()
        if not r then
            error("no request found")
        end

        buf[0] = value_buf
        buf_size[0] = VALUE_BUF_SIZE
        local errbuf = get_string_buf(ERR_BUF_SIZE)
        local errbuf_size = get_size_ptr()
        errbuf_size[0] = ERR_BUF_SIZE
        local rc = C.ngx_http_lua_ffi_pipe_proc_read(r, proc, stderr,
                                                     reader_type, len, buf,
                                                     buf_size, errbuf,
                                                     errbuf_size)
        if rc == FFI_NO_REQ_CTX then
            error("no request ctx found")
        end

        if rc == FFI_BAD_CONTEXT then
            error(ffi_str(errbuf, errbuf_size[0]), 2)
        end

        while true do
            if rc == FFI_ERROR then
                return nil, ffi_str(errbuf, errbuf_size[0])
            end

            if rc == FFI_OK then
                local p = buf[0]
                if p ~= value_buf then
                    p = ffi_new("char[?]", buf_size[0])
                    buf[0] = p
                    C.ngx_http_lua_ffi_pipe_get_read_result(r, proc, stderr,
                                                            buf, buf_size,
                                                            errbuf, errbuf_size)
                    assert(p == buf[0])
                end

                return ffi_str(p, buf_size[0])
            end

            if rc == FFI_DECLINED then
                local err = ffi_str(errbuf, errbuf_size[0])

                local p = buf[0]
                if p ~= value_buf then
                    p = ffi_new("char[?]", buf_size[0])
                    buf[0] = p
                    C.ngx_http_lua_ffi_pipe_get_read_result(r, proc, stderr,
                                                            buf, buf_size,
                                                            errbuf, errbuf_size)
                    assert(p == buf[0])
                end

                local partial = ffi_str(p, buf_size[0])
                return nil, err, partial
            end

            assert(rc == FFI_AGAIN)

            co_yield()

            buf[0] = value_buf
            buf_size[0] = VALUE_BUF_SIZE
            errbuf = get_string_buf(ERR_BUF_SIZE)
            errbuf_size = get_size_ptr()
            errbuf_size[0] = ERR_BUF_SIZE
            rc = C.ngx_http_lua_ffi_pipe_get_read_result(r, proc, stderr, buf,
                                                         buf_size, errbuf,
                                                         errbuf_size)
        end
    end

end


local function proc_write(proc, data)
    check_proc_instance(proc)

    local r = get_request()
    if not r then
        error("no request found", 2)
    end

    local data_type = type(data)
    if data_type ~= "string" then
        if data_type == "table" then
            data = table_concat(data, "")

        elseif data_type == "number" then
            data = tostring(data)

        else
            error("bad data arg: string, number, or table expected, got "
                  .. data_type, 2)
        end
    end

    local errbuf = get_string_buf(ERR_BUF_SIZE)
    local errbuf_size = get_size_ptr()
    errbuf_size[0] = ERR_BUF_SIZE
    local rc = C.ngx_http_lua_ffi_pipe_proc_write(r, proc, data, #data, errbuf,
                                                  errbuf_size)
    if rc == FFI_NO_REQ_CTX then
        error("no request ctx found", 2)
    end

    if rc == FFI_BAD_CONTEXT then
        error(ffi_str(errbuf, errbuf_size[0]), 2)
    end

    while true do
        if rc == FFI_ERROR then
            return nil, ffi_str(errbuf, errbuf_size[0])
        end

        if rc >= 0 then
            -- rc holds the bytes sent
            return tonumber(rc)
        end

        assert(rc == FFI_AGAIN)

        co_yield()

        errbuf = get_string_buf(ERR_BUF_SIZE)
        errbuf_size = get_size_ptr()
        errbuf_size[0] = ERR_BUF_SIZE
        rc = C.ngx_http_lua_ffi_pipe_get_write_result(r, proc, errbuf,
                                                      errbuf_size)
    end
end


local function proc_shutdown(proc, direction)
    check_proc_instance(proc)

    local rc
    local errbuf = get_string_buf(ERR_BUF_SIZE)
    local errbuf_size = get_size_ptr()
    errbuf_size[0] = ERR_BUF_SIZE

    if direction == "stdin" then
        rc = C.ngx_http_lua_ffi_pipe_proc_shutdown_stdin(proc, errbuf,
                                                         errbuf_size)

    elseif direction == "stdout" then
        rc = C.ngx_http_lua_ffi_pipe_proc_shutdown_stdout(proc, errbuf,
                                                          errbuf_size)

    elseif direction == "stderr" then
        rc = C.ngx_http_lua_ffi_pipe_proc_shutdown_stderr(proc, errbuf,
                                                          errbuf_size)

    else
        error("bad shutdown arg: " .. direction, 2)
    end

    if rc == FFI_ERROR then
        return nil, ffi_str(errbuf, errbuf_size[0])
    end

    return true
end


local proc_wait
do
    local reason = ffi_new("char *[1]")
    local status = ffi_new("int[1]")

    function proc_wait(proc)
        check_proc_instance(proc)

        local r = get_request()
        if not r then
            error("no request found", 2)
        end

        local errbuf = get_string_buf(ERR_BUF_SIZE)
        local errbuf_size = get_size_ptr()
        errbuf_size[0] = ERR_BUF_SIZE
        local rc = C.ngx_http_lua_ffi_pipe_proc_wait(r, proc, reason, status,
                                                     errbuf, errbuf_size)
        if rc == FFI_NO_REQ_CTX then
            error("no request ctx found", 2)
        end

        if rc == FFI_BAD_CONTEXT then
            error(ffi_str(errbuf, errbuf_size[0]), 2)
        end

        if rc == FFI_ERROR then
            return nil, ffi_str(errbuf, errbuf_size[0])
        end

        if rc == FFI_OK then
            return true, ffi_str(reason[0]), tonumber(status[0])
        end

        if rc == FFI_DECLINED then
            return false, ffi_str(reason[0]), tonumber(status[0])
        end

        local ok, exit_reason, exit_status
        ok, exit_reason, exit_status = co_yield()
        return ok, exit_reason, exit_status
    end
end


local function proc_kill(proc, signal)
    check_proc_instance(proc)

    if type(signal) ~= "number" then
        error("bad signal arg: number expected, got " .. tostring(signal), 2)
    end

    local errbuf = get_string_buf(ERR_BUF_SIZE)
    local errbuf_size = get_size_ptr()
    errbuf_size[0] = ERR_BUF_SIZE

    local rc = C.ngx_http_lua_ffi_pipe_proc_kill(proc, signal, errbuf,
                                                 errbuf_size)
    if rc == FFI_ERROR then
        return nil, ffi_str(errbuf, errbuf_size[0])
    end

    return true
end


local mt = {
    __gc = C.ngx_http_lua_ffi_pipe_proc_destroy,

    __index = {
        pid = function (proc)
            return proc._pid
        end,

        set_timeouts = function (proc, write_timeout, stdout_read_timeout,
                                 stderr_read_timeout, wait_timeout)
            proc_set_timeouts(proc, write_timeout, stdout_read_timeout,
                              stderr_read_timeout, wait_timeout)
        end,

        stdout_read_all = function (proc)
            local data, err, partial = proc_read(proc, 0, PIPE_READ_ALL, 0)
            return data, err, partial
        end,

        stdout_read_bytes = function (proc, len)
            if len <= 0 then
                if len < 0 then
                    error("bad len argument", 2)
                end

                return ""
            end

            local data, err, partial = proc_read(proc, 0, PIPE_READ_BYTES, len)
            return data, err, partial
        end,

        stdout_read_line = function (proc)
            local data, err, partial = proc_read(proc, 0, PIPE_READ_LINE, 0)
            return data, err, partial
        end,

        stdout_read_any = function (proc, max)
            if type(max) ~= "number" then
                max = tonumber(max)
            end

            if not max or max <= 0 then
                error("bad max argument", 2)
            end

            local data, err, partial = proc_read(proc, 0, PIPE_READ_ANY, max)
            return data, err, partial
        end,

        stderr_read_all = function (proc)
            local data, err, partial = proc_read(proc, 1, PIPE_READ_ALL, 0)
            return data, err, partial
        end,

        stderr_read_bytes = function (proc, len)
            if len <= 0 then
                if len < 0 then
                    error("bad len argument", 2)
                end

                return ""
            end

            local data, err, partial = proc_read(proc, 1, PIPE_READ_BYTES, len)
            return data, err, partial
        end,

        stderr_read_line = function (proc)
            local data, err, partial = proc_read(proc, 1, PIPE_READ_LINE, 0)
            return data, err, partial
        end,

        stderr_read_any = function (proc, max)
            if type(max) ~= "number" then
                max = tonumber(max)
            end

            if not max or max <= 0 then
                error("bad max argument", 2)
            end

            local data, err, partial = proc_read(proc, 1, PIPE_READ_ANY, max)
            return data, err, partial
        end,

        write = proc_write,
        shutdown = proc_shutdown,
        wait = proc_wait,
        kill = proc_kill,
    }
}
local Proc = ffi.metatype("ngx_http_lua_ffi_pipe_proc_t", mt)


local pipe_spawn
do
    local sh_exe = "/bin/sh"
    local opt_c = "-c"
    local shell_args = ffi_new("const char* [?]", 4)
    shell_args[0] = sh_exe
    shell_args[1] = opt_c
    shell_args[3] = nil

    local write_timeout = 10000
    local stdout_read_timeout = 10000
    local stderr_read_timeout = 10000
    local wait_timeout = 10000

    -- reference shell cmd's constant strings here to prevent them from getting
    -- collected by the Lua GC.
    _M._gc_ref_c_opt = opt_c

    function pipe_spawn(args, opts)
        if ngx_phase() == "init" then
            error("API disabled in the current context", 2)
        end

        local exe
        local proc_args
        local proc_envs

        local args_type = type(args)
        if args_type == "table" then
            local nargs = 0

            for i, arg in ipairs(args)  do
                nargs = nargs + 1

                if type(arg) ~= "string" then
                    args[i] = tostring(arg)
                end
            end

            if nargs == 0 then
                error("bad args arg: non-empty table expected", 2)
            end

            exe = args[1]
            proc_args = ffi_new("const char* [?]", nargs + 1, args)
            proc_args[nargs] = nil

        elseif args_type == "string" then
            exe = sh_exe
            shell_args[2] = args
            proc_args = shell_args

        else
            error("bad args arg: table expected, got " .. args_type, 2)
        end

        local merge_stderr = 0
        local buffer_size = 4096
        local proc = Proc()

        if opts then
            merge_stderr = opts.merge_stderr and 1 or 0

            if opts.buffer_size then
                buffer_size = tonumber(opts.buffer_size)

                if not buffer_size or buffer_size < 1 then
                    error("bad buffer_size option", 2)
                end
            end

            if opts.environ then
                local environ = opts.environ
                local environ_type = type(environ)
                if environ_type ~= "table" then
                    error("bad environ option: table expected, got " ..
                          environ_type, 2)
                end

                local nenv = 0

                for i, env in ipairs(environ) do
                    nenv = nenv + 1

                    local env_type = type(env)
                    if env_type ~= "string" then
                        error("bad value at index " .. i .. " of environ " ..
                              "option: string expected, got " .. env_type, 2)
                    end

                    if not str_find(env, "=", 2, true) then
                        error("bad value at index " .. i .. " of environ " ..
                              "option: 'name=[value]' format expected, got '" ..
                              env .. "'", 2)
                    end
                end

                if nenv > 0 then
                    proc_envs = ffi_new("const char* [?]", nenv + 1, environ)
                    proc_envs[nenv] = nil
                end
            end

            proc_set_timeouts(proc,
                              opts.write_timeout or write_timeout,
                              opts.stdout_read_timeout or stdout_read_timeout,
                              opts.stderr_read_timeout or stderr_read_timeout,
                              opts.wait_timeout or wait_timeout)

        else
            proc_set_timeouts(proc,
                              write_timeout,
                              stdout_read_timeout,
                              stderr_read_timeout,
                              wait_timeout)
        end

        local errbuf = get_string_buf(ERR_BUF_SIZE)
        local errbuf_size = get_size_ptr()
        local r = get_request()
        errbuf_size[0] = ERR_BUF_SIZE
        local rc = C.ngx_http_lua_ffi_pipe_spawn(r, proc, exe, proc_args,
                                                 merge_stderr, buffer_size,
                                                 proc_envs, errbuf, errbuf_size)
        if rc == FFI_ERROR then
            return nil, ffi_str(errbuf, errbuf_size[0])
        end

        return proc
    end
end  -- do


_M.spawn = pipe_spawn


return _M

Filemanager

Name Type Size Permission Actions
ssl Folder 0755
balancer.lua File 6.01 KB 0644
base64.lua File 1.68 KB 0644
errlog.lua File 4.31 KB 0644
ocsp.lua File 3.65 KB 0644
pipe.lua File 19.14 KB 0644
process.lua File 2.95 KB 0644
re.lua File 7.55 KB 0644
req.lua File 340 B 0644
resp.lua File 365 B 0644
semaphore.lua File 4.98 KB 0644
ssl.lua File 12.79 KB 0644