Lua - Reddit – Telegram
Lua - Reddit
30 subscribers
281 photos
31 videos
4.26K links
News and discussion for the Lua programming language.

Subreddit: https://www.reddit.com/r/lua

Powered by : @r_channels & @reddit2telegram
Download Telegram
Can nested loop have different types of loops within?

for example

for initialization, min/max value, iteration --yes this is numeric for idc
do
--insert stuff for 1st loop
while (condition)
do
--insert stuff for 2nd loop
repeat
--insert stuff for 3rd loop
until (condition)
end
end

i was wondering if it's possible to do so, since in many instance, nested loops will use loops of the same type...

https://redd.it/1k9ci93
@r_lua
Lua by example?

I'm thinking of developing a Lua by example. Is this something the community would like to see?

https://redd.it/1k9qek4
@r_lua
Advice

Hi. New here. And to Lua as a whole. I am currently learning Lua to embed it into C++ and possibly use it together with the C++ inline assembler for game development. However Lua is not a walk in the park. The basics of Lua are. And I am stuck there. The basics. Actually, outside of the basic input output, data type conversions (Tostring/tonumber), io.open()/ file:read() / file:close(), os.execute() and maybe "require", i cant say i understand much else.. Trust me i tried but this isnt as easy as promised.. Lua has a very special complexity surrounding it that you only discover after starting..

What advice do you have for a freshman college student like me learning Lua. I should add this is not a part of the program I am doing. Its just a personal interest. How did you master Lua or at least know enough of it to produce a game in it either in pure Lua or Lua embedded in C.

https://redd.it/1kbpn57
@r_lua
trying to rewrite lua-resty-fastcgi but it fails to connects

I am trying to rewrite FastCGI extension which was written for Lua Resty module of NGINX by benagricola, but it keeps on failing to connect to any PHP-FastCGI server (throws fastCGI : recv header error: closed which means that FastCGI is not available) i tried adjusting the timeout but it didn't work

I am using the extension like this

set $cginoscriptname '';

location ~ ^/@FastCGI(/+)?(((a-zA-Z0-9\_\-+(/+))+)?(a-zA-Z0-9\-\_+\.a-zA-Z0-9+))? {
internal;
ifmodifiedsince off;
contentbyluablock {
local fastcgi = require "fastcgi"
local fcgi = setmetatable({}, fastcgi)

fcgi:connect("
127.0.0.1", 25680)

local ok, err = fcgi:request({
noscript
filename = ngx.var"document_root" .. ngx.var"cgi_noscript_name",
noscriptname = ngx.var["cginoscriptname"],
document
root = ngx.var"document_root",
serverport = ngx.var["balancerport"],
pathinfo = ngx.var["fastcgipathinfo"],
query
string = ngx.var"query_string",
requesturi = ngx.var["requesturi"],
documenturi = ngx.var["requesturi"],
serverprotocol = ngx.var["serverprotocol"],
requestmethod = ngx.var["requestmethod"],
geoip2datacountrycode = ngx.var["geoip2datacountrycode"],
geoip2datacountryname = ngx.var["geoip2datacountryname"],
geoip2datacityname = ngx.var["geoip2datacityname"]
}, {
cachedict = "fastcgiCache",
cache
valid = 300,
keepalive = true,
keepalivetimeout = 120000,
keepalive
poolsize = 100,
hide
headers = { "X-Powered-By", "X-Page-Speed", "X-Application-Version", "X-Varnish", "Last-Modified", "Cache-Control", "Vary", "X-CF-Powered-By" },
intercepterrors = true,
read
timeout = 60000,
cacheMethods = { "GET" },
headerchunksize = 50 1024,
body_chunk_size = 30
1024
})
if not ok then
ngx.exit(ngx.HTTPBADGATEWAY)
end
}
include /etc/nginx/fastcgiparams;
access
log on;
}

and in my PATH Resolver (off-topic, but I have to include it in my question)

local uri = ngx.var"request_uri" or "/"
if type(uri) ~= "string" then
ngx.log(ngx.ERR, "URI is not a string: ", type(uri))
uri = "/"
end
ngx.log(ngx.DEBUG, "Request URI: ", uri or "Unknown!")
ngx.log(ngx.DEBUG, "URI: ", ngx.var"uri" or "Unknown!")

local PATH = ngx.var"document_root" .. uri
local PATH = string.match(PATH, "^[^?]*")
if not
PATH or PATH == 1 then
PATH = PATH
end
local file, err = io.open(PATH, "rb")
if not file then
ngx.log(ngx.ERR, "Failed to open file: " .. err)
ngx.status = ngx.HTTP
NOTFOUND
ngx.exit(ngx.HTTP
NOTFOUND)
return
end
file:close()

ngx.var["cgi
noscriptname"] = ngx.var["uri"]
local res = ngx.location.capture("/
@FastCGI", {
-- method = ngx.HTTP
GET,
args = ngx.var"args",
})
ngx.status = res.status
for k, v in pairs(res.header) do
ngx.headerk = v
end
ngx.print(res.body)
ngx.log(ngx.DEBUG, "#1 : " .. uri)

and my extension fork

local ngx = require "ngx"
local bit = require "bit"
local binutil = require 'resty.binutil'

local M = {}
M.index = M

local FCGI = {

HEADER
LEN = 0x08,
trying to rewrite lua-resty-fastcgi but it fails to connects

I am trying to rewrite FastCGI extension which was written for Lua Resty module of NGINX by **benagricola**, but it keeps on failing to connect to any PHP-FastCGI server (throws `fastCGI : recv header error: closed` which means that FastCGI is not available) i tried adjusting the timeout but it didn't work

I am using the extension like this

set $cgi_noscript_name '';

location ~ ^/@FastCGI(/+)?((([a-zA-Z0-9\_\-]+(/+))+)?([a-zA-Z0-9\-\_]+\.[a-zA-Z0-9]+))? {
internal;
if_modified_since off;
content_by_lua_block {
local fastcgi = require "fastcgi"
local fcgi = setmetatable({}, fastcgi)

fcgi:connect("127.0.0.1", 25680)

local ok, err = fcgi:request({
noscript_filename = ngx.var["document_root"] .. ngx.var["cgi_noscript_name"],
noscript_name = ngx.var["cgi_noscript_name"],
document_root = ngx.var["document_root"],
server_port = ngx.var["balancer_port"],
path_info = ngx.var["fastcgi_path_info"],
query_string = ngx.var["query_string"],
request_uri = ngx.var["request_uri"],
document_uri = ngx.var["request_uri"],
server_protocol = ngx.var["server_protocol"],
request_method = ngx.var["request_method"],
geoip2_data_country_code = ngx.var["geoip2_data_country_code"],
geoip2_data_country_name = ngx.var["geoip2_data_country_name"],
geoip2_data_city_name = ngx.var["geoip2_data_city_name"]
}, {
cache_dict = "fastcgiCache",
cache_valid = 300,
keepalive = true,
keepalive_timeout = 120000,
keepalive_pool_size = 100,
hide_headers = { "X-Powered-By", "X-Page-Speed", "X-Application-Version", "X-Varnish", "Last-Modified", "Cache-Control", "Vary", "X-CF-Powered-By" },
intercept_errors = true,
read_timeout = 60000,
cacheMethods = { "GET" },
header_chunk_size = 50 * 1024,
body_chunk_size = 30 * 1024
})
if not ok then
ngx.exit(ngx.HTTP_BAD_GATEWAY)
end
}
include /etc/nginx/fastcgi_params;
access_log on;
}

and in my PATH Resolver (off-topic, but I have to include it in my question)

local uri = ngx.var["request_uri"] or "/"
if type(uri) ~= "string" then
ngx.log(ngx.ERR, "URI is not a string: ", type(uri))
uri = "/"
end
ngx.log(ngx.DEBUG, "Request URI: ", uri or "Unknown!")
ngx.log(ngx.DEBUG, "URI: ", ngx.var["uri"] or "Unknown!")

local ____PATH = ngx.var["document_root"] .. uri
local ___PATH = string.match(____PATH, "^[^?]*")
if not ___PATH or ___PATH == 1 then
___PATH = ____PATH
end
local file, err = io.open(___PATH, "rb")
if not file then
ngx.log(ngx.ERR, "Failed to open file: " .. err)
ngx.status = ngx.HTTP_NOT_FOUND
ngx.exit(ngx.HTTP_NOT_FOUND)
return
end
file:close()

ngx.var["cgi_noscript_name"] = ngx.var["uri"]
local res = ngx.location.capture("/@FastCGI", {
-- method = ngx.HTTP_GET,
args = ngx.var["args"],
})
ngx.status = res.status
for k, v in pairs(res.header) do
ngx.header[k] = v
end
ngx.print(res.body)
ngx.log(ngx.DEBUG, "#1 : " .. uri)

and my extension fork

local ngx = require "ngx"
local bit = require "bit"
local binutil = require 'resty.binutil'

local _M = {}
_M.__index = _M

local FCGI = {

HEADER_LEN = 0x08,
VERSION_1 = 0x01,
BEGIN_REQUEST = 0x01,
ABORT_REQUEST = 0x02,
END_REQUEST = 0x03,
PARAMS = 0x04,
STDIN = 0x05,
STDOUT = 0x06,
STDERR = 0x07,
DATA = 0x08,
GET_VALUES = 0x09,
GET_VALUES_RESULT = 0x10,
UNKNOWN_TYPE = 0x11,
MAXTYPE = 0x11,
BODY_MAX_LENGTH = 32768,
KEEP_CONN = 0x01,
NO_KEEP_CONN = 0x00,
NULL_REQUEST_ID = 0x00,
RESPONDER = 0x01,
AUTHORIZER = 0x02,
FILTER = 0x03
}

local FCGI_HEADER_FORMAT = {
{ "version", 1, FCGI.VERSION_1 },
{ "type", 1, nil },
{ "request_id", 2, 1 },
{ "content_length", 2, 0 },
{ "padding_length", 1, 0 },
{ "reserved", 1, 0 }
}

local function _pack(format, params)
local bytes = ""

for unused, field in ipairs(format) do
local fieldname = field[1]
local fieldlength = field[2]
local defaulval = field[3]

local value = params[fieldname] or defaulval
if value == nil then
ngx.log(ngx.ERR, "fastCGI : Missing value for field: " .. fieldname)
return nil
end
bytes = bytes .. binutil.ntob(value, fieldlength)
end

return bytes
end

local function _pack_header(params)
local align = 8
params.padding_length = bit.band(-(params.content_length or 0), align - 1)
return _pack(FCGI_HEADER_FORMAT, params), params.padding_length
end

local FCGI_BEGIN_REQ_FORMAT = {
{ "role", 2, FCGI.RESPONDER },
{ "flags", 1, 0 },
{ "reserved", 5, 0 }
}

local FCGI_PREPACKED = {
end_params = _pack_header({
type = FCGI.PARAMS,
}),
begin_request = _pack_header({
type = FCGI.BEGIN_REQUEST,
request_id = 1,
content_length = FCGI.HEADER_LEN,
}) .. _pack(FCGI_BEGIN_REQ_FORMAT, {
role = FCGI.RESPONDER,
flags = 1,
}),
abort_request = _pack_header({
type = FCGI.ABORT_REQUEST,
}),
empty_stdin = _pack_header({
type = FCGI.STDIN,
content_length = 0,
}),
}

local FCGI_END_REQ_FORMAT = {
{ "status", 4, nil },
{ "protocolStatus", 1, nil },
{ "reserved", 3, nil }
}


local FCGI_PADDING_BYTES = {
string.char(0),
string.char(0, 0),
string.char(0, 0, 0),
string.char(0, 0, 0, 0),
string.char(0, 0, 0, 0, 0),
string.char(0, 0, 0, 0, 0, 0),
string.char(0, 0, 0, 0, 0, 0, 0),
}

local function _pad(bytes)
if bytes == 0 then
return ""
else
return FCGI_PADDING_BYTES[bytes]
end
end

local function _unpack_hdr(format, str)
-- If we received nil, return nil
if not str then
return nil
end

local res, idx = {}, 1

-- Extract bytes based on format. Convert back to number and place in res rable
for _, field in ipairs(format) do
res[field[1]] = bton(str_sub(str, idx, idx + field[2] - 1))
idx = idx + field[2]
end

return res
end

local function _format_stdin(stdin)
local chunk_length
local to_send = {}
local stdin_chunk = { "", "", "" }
local header = ""
local padding, idx = 0, 1
local stdin_length = #stdin

-- We could potentially need to send more than one records' worth of data, so
-- loop to format.
repeat
-- While we still have stdin data, build up STDIN record in chunks
if stdin_length >
FCGI.BODY_MAX_LENGTH then
chunk_length = FCGI.BODY_MAX_LENGTH
else
chunk_length = stdin_length
end

header, padding = _pack_header({
type = FCGI.STDIN,
content_length = chunk_length,
})

stdin_chunk[1] = header
stdin_chunk[2] = string.sub(stdin, 1, chunk_length)
stdin_chunk[3] = _pad(padding)

to_send[idx] = table.concat(stdin_chunk)
stdin = string.sub(stdin, chunk_length + 1)
stdin_length = stdin_length - chunk_length
idx = idx + 1
until stdin_length == 0

return table.concat(to_send)
end


local function _send_stdin(sock, stdin)
local ok, bytes, err, chunk, partial

if type(stdin) == 'function' then
repeat
chunk, err, partial = stdin(FCGI.BODY_MAX_LENGTH)

-- If the iterator returns nil, then we have no more stdin
-- Send an empty stdin record to signify the end of the request
if chunk then
ngx.log(ngx.DEBUG, "Request body reader yielded ", #chunk, " bytes of data - sending")
ok, err = sock:send(_format_stdin(chunk))
if not ok then
ngx.log(ngx.DEBUG, "Unable to send ", #chunk, " bytes of stdin: ", err)
return nil, err
end
-- Otherwise iterator errored, return
elseif err ~= nil then
ngx.log(ngx.DEBUG, "Request body reader yielded an error: ", err)
return nil, err, partial
end
until chunk == nil
elseif stdin ~= nil then
ngx.log(ngx.DEBUG, "Sending ", #stdin, " bytes of read data")
bytes, err = sock:send(_format_stdin(stdin))

if not bytes then
return nil, err
end
elseif stdin == nil then
return
end

-- Send empty stdin record to signify end
bytes, err = sock:send(FCGI_PREPACKED.empty_stdin)

if not bytes then
return nil, err
end

return true, nil
end

local function build_header(record_type, content_len, padding_len, request_id)
return string.char(
FCGI.VERSION_1,
record_type,
bit.rshift(request_id, 8),
bit.band(request_id, 0xFF),
bit.rshift(content_len, 8),
bit.band(content_len, 0xFF),
padding_len,
0
)
end

local function encode_name_value(name, value)
local n, v = #name, #value
local parts = {}

if n < 128 then
parts[#parts + 1] = string.char(n)
else

parts[#parts + 1] = string.char(
bit.bor(bit.rshift(n, 24), 0x80),
bit.band(bit.rshift(n, 16), 0xFF),
bit.band(bit.rshift(n, 8), 0xFF),
bit.band(n, 0xFF)
)
end

if v < 128 then
parts[#parts + 1] = string.char(v)
else
parts[#parts + 1] = string.char(
bit.bor(bit.rshift(v, 24), 0x80),
bit.band(bit.rshift(v, 16), 0xFF),
bit.band(bit.rshift(v, 8), 0xFF),
bit.band(v, 0xFF)
)
end

parts[#parts + 1] = name
parts[#parts + 1] = value
return table.concat(parts)
end

function _M:connect(host, port)
self.fcgiSocket = ngx.socket.tcp()
if not self.fcgiSocket then
ngx.log(ngx.ERR, "fastCGI : failed to create TCP socket")
return nil, "fastCGI : failed to create TCP socket"
end
self.request_id = 0
self.fcgiSocket:settimeout(3000) -- tmp change
local ok, err = self.fcgiSocket:connect(host, port)
if not ok then
ngx.log(ngx.ERR, "fastCGI : connect error: " .. (err or "Unknown"))
ngx.exit(ngx.HTTP_BAD_GATEWAY)
return nil, "fastCGI : connect error: " .. (err or "Unknown")
else
self.fcgiSocket:settimeout(30000)
end
return true
end

function _M:close()
if not self.fcgiSocket then
ngx.log(ngx.ERR, "fastCGI : no socket")
return nil, "fastCGI : no socket"
end
local _, close_err = self.fcgiSocket:close()
self.fcgiSocket = nil
if close_err and close_err ~= "closed" then
ngx.log(ngx.ERR, "fastCGI : close failed: " .. (close_err or "Unknown"))
return nil, "fastCGI : close failed: " .. (close_err or "Unknown")
end
return true
end

function _M.get_reused_times()
if not self.fcgiSocket then
ngx.log(ngx.ERR, "fastCGI : no socket")
return nil, "fastCGI : no socket"
end

return self.fcgiSocket:getreusedtimes()
end

function _M.set_timeout(timeout)
if not self.fcgiSocket then
ngx.log(ngx.ERR, "fastCGI : no socket")
return nil, "fastCGI : no socket"
end

return self.fcgiSocket:settimeout(timeout)
end

function _M.set_keepalive(...)
if not self.fcgiSocket then
ngx.log(ngx.ERR, "fastCGI : no socket")
return nil, "fastCGI : no socket"
end

return self.fcgiSocket:setkeepalive(...)
end

function _M:request(params, opts, stdin)
opts = opts or {}
if not self.fcgiSocket then
ngx.log(ngx.ERR, "fastCGI : not connected")
return nil, "fastCGI : not connected"
end

self.request_id = (self.request_id % 65535) + 1
local request_id = self.request_id

local function cleanup(ok)
if not self.fcgiSocket then return end
if ok and opts.keepalive then
local ka_ok, ka_err = self.fcgiSocket:setkeepalive(
opts.keepalive_timeout or 60000,
opts.keepalive_pool_size or 10
)
if not ka_ok and ka_err ~= "closed" then
ngx.log(ngx.ERR, "fastCGI : keepalive failed: " .. (ka_err or "Unknown"))
return nil, "fastCGI : keepalive failed: " .. (ka_err or "Unknown")
end
else

local _, close_err = self.fcgiSocket:close()
self.fcgiSocket = nil
if close_err and close_err ~= "closed" then
ngx.log(ngx.ERR, "fastCGI : close failed: " .. (close_err or "Unknown"))
return nil, "fastCGI : close failed: " .. (close_err or "Unknown")
end
end
end

local ok, err = xpcall(function()
local cache = nil
local cache_key = nil
if not (opts.cache_bypass and opts.cache_bypass()) and not ngx.var["skip_cache"] then
cache = ngx.shared[opts.cache_dict or "fastcgiCache"]
cache_key = table.concat({
ngx.var.scheme,
ngx.var.host,
ngx.var.uri,
ngx.var.args or "",
params.noscript_filename
}, "|")
local cached = cache:get(cache_key)
if cached then
ngx.status = cached.status
for k, v in pairs(cached.headers) do
ngx.header[k] = v
end
ngx.say(cached.body)
return ngx.exit(ngx.HTTP_OK)
end
end

local flags = 0
if opts.keepalive then
flags = FCGI.KEEP_CONN
end
local begin_body = string.char(0, FCGI.RESPONDER, flags, 0, 0, 0, 0, 0)

local header = build_header(FCGI.BEGIN_REQUEST, #begin_body, 0, request_id)
local ok, err = self.fcgiSocket:send(header .. begin_body)
if not ok then
ngx.log(ngx.ERR, "fastCGI : failed to send begin request: " .. (err or "Unknown"))
return nil, "fastCGI : failed to send begin request: " .. (err or "Unknown")
end

local fcgi_params = {}

if params.noscript_filename then
fcgi_params["SCRIPT_FILENAME"] = params.noscript_filename

local noscript_name = params.noscript_name
local path_info = params.path_info
if not noscript_name or not path_info then

local _uri = params.request_uri or ngx.var["request_uri"] or ""

_uri = _uri:match("^[^?]+") or ""

local m, n = _uri:match("(.+%.php)(/.*)")
if m then
noscript_name = noscript_name or (m or _uri)
path_info = path_info or n
else
noscript_name = noscript_name or _uri
path_info = path_info or ""
end
end
fcgi_params["SCRIPT_NAME"] = noscript_name or ""
fcgi_params["PATH_INFO"] = path_info or ""
end

fcgi_params["REQUEST_METHOD"] = params.request_method or ngx.var["request_method"]
fcgi_params["QUERY_STRING"] = params.query_string or ngx.var["query_string"] or ""
fcgi_params["SERVER_PROTOCOL"] = params.server_protocol or ngx.var["server_protocol"]
fcgi_params["REMOTE_ADDR"] = ngx.var["remote_addr"] or ""
fcgi_params["REMOTE_PORT"] = ngx.var["remote_port"] or ""
fcgi_params["SERVER_ADDR"] = ngx.var["server_addr"] or ""
fcgi_params["SERVER_PORT"] = ngx.var["server_port"] or ""
fcgi_params["SERVER_NAME"] = ngx.var["server_name"] or ""
fcgi_params["DOCUMENT_ROOT"] = params.document_root or ngx.var["document_root"] or ""
fcgi_params["DOCUMENT_URI"] = params.document_uri or ngx.var["request_uri"] or ""
fcgi_params["COUNTRY_CODE"] = params.geoip2_data_country_code or ngx.var["geoip2_data_country_code"] or ""
fcgi_params["COUNTRY_NAME"] = params.geoip2_data_country_name or ngx.var["geoip2_data_country_name"] or ""
fcgi_params["CITY_NAME"] = params.geoip2_data_city_name or ngx.var["geoip2_data_city_name"] or ""
fcgi_params["HTTP_PROXY"] = params.http_proxy or ""

local headers = ngx.req.get_headers()
if headers["Content-Type"] then
fcgi_params["CONTENT_TYPE"] = headers["Content-Type"]
end
if ngx.var["content_length"] then
fcgi_params["CONTENT_LENGTH"] = ngx.var["content_length"]
end

if params.fastcgi_params then
for k, v in pairs(params.fastcgi_params) do
fcgi_params[k] = v
end
end

for k, v in pairs(headers) do
if type(k) == "string" and type(v) == "string" then
local hk = "HTTP_" .. k:upper():gsub("-", "_")

if hk ~= "HTTP_CONTENT_TYPE" and hk ~= "HTTP_CONTENT_LENGTH" then
fcgi_params[hk] = v
end
end
end

local all_params = {}
for k, v in pairs(fcgi_params) do
all_params[#all_params + 1] = encode_name_value(k, tostring(v))
end
local pstr = table.concat(all_params)
local pos, plen = 1, #pstr
local chunk
local clen, pad
local bytes, sendERR
while plen > 0 do
chunk = pstr:sub(pos, pos + 65535 - 1)
clen, pad = #chunk, (8 - (#chunk % 8)) % 8
bytes, sendERR = self.fcgiSocket:send(build_header(FCGI.PARAMS, clen, pad, request_id) ..
chunk .. string.rep("\0", pad))
if not bytes then
ngx.log(ngx.ERR, "fastCGI : Failed to send params: " .. (sendERR or "Unknown"))
return nil, "fastCGI : Failed to send params: " .. (sendERR or "Unknown")
end
pos = pos + clen
plen = plen - clen
end
self.fcgiSocket:send(build_header(FCGI.PARAMS, 0, 0, request_id))

self.fcgiSocket:settimeout(opts.read_timeout or 60000)
local method = fcgi_params.REQUEST_METHOD
if method == "POST" or method == "PUT" or method == "PATCH" then
ngx.req.read_body()
local body_sock = ngx.req.socket(true)
local sendOK
local chunk_
local data, recv_err, partial
if body_sock then
repeat
data, recv_err, partial = body_sock:receive(opts.body_chunk_size or 8192)
ngx.log(ngx.DEBUG, "Attempting to read end request")

if not data or partial then
ngx.log(ngx.ERR, "Unable to parse FCGI end request body : " .. (err or "Unknown"))
return nil, "Unable to parse FCGI end request body : " .. (err or "Unknown")
end
chunk_ = data or partial
if chunk_ then
pad = (8 - (#chunk_ % 8)) % 8
sendOK, sendERR = self.fcgiSocket:send(build_header(FCGI.STDIN, #chunk_, pad, request_id) ..
chunk_ .. (pad > 0 and string.rep("\0", pad) or ""))
if not sendOK then
ngx.log(ngx.ERR, "Failed to send stdin: " .. (sendERR or "Unknown"))
return nil, "Failed to send stdin: " .. (sendERR or "Unknown")
end
end
until not data or recv_err
end
end
self.fcgiSocket:send(build_header(FCGI.STDIN, 0, 0, request_id))

local stdout, stderr = "", {}
local parsed_headers = false
local read_bytes = ""
local partial = ""
local bytes_to_read, hdrByte, rcvERR
local hdr, typ, rcvClen, rcvPad
local sep, raw, rest
local hn, hv, hName
local cacheMethod
local read_data
while true do
hdrByte, rcvERR = self.fcgiSocket:receive(opts.header_chunk_size or 8)
if (rcvERR == "closed") then
rcvERR = "connection closed"
end
if not hdrByte then
ngx.log(ngx.ERR, "fastCGI : recv header error: " .. (rcvERR or "Unknown"))
return nil, "fastCGI : recv header error: " .. (rcvERR or "Unknown")
end
hdr = _unpack_hdr(FCGI.HEADER_FORMAT, hdrByte)
if not hdr then
ngx.log(ngx.ERR, "Unable to parse FCGI record header : " .. (rcvERR or "Unknown"))
return nil, "Unable to parse FCGI record header : " .. (rcvERR or "Unknown")
end
typ = hdr.type
rcvClen = hdr.content_length
rcvPad = hdr.padding_length

if hdr.version ~= FCGI.VERSION_1 then
ngx.log(ngx.ERR, "invalid protocol version: " .. hdr.version)
return nil, "invalid protocol version: " .. hdr.version
end

ngx.log(ngx.DEBUG, "New content length is " .. rcvClen .. " padding ", rcvPad)

if rcvClen > 0 then
read_bytes, rcvERR, partial = self.fcgiSocket:receive(rcvClen)
if not read_bytes or partial then
ngx.log(ngx.ERR, "fastCGI : recv content error: " .. (rcvERR or "Unknown"))
return nil, "fastCGI : recv content error: " .. (rcvERR or "Unknown")
end
end

if rcvClen <= 65535 then
bytes_to_read = rcvClen
else
bytes_to_read = 65535
end

if bytes_to_read > 0 then
read_data, rcvERR, partial = self.fcgiSocket:receive(bytes_to_read)

if not read_data then
return nil, "Unable to retrieve request body: " .. rcvERR .. ' < ' .. partial .. ' >'
end

rcvClen = rcvClen - bytes_to_read
ngx.log(ngx.DEBUG, "Reducing content length by ", bytes_to_read, " bytes to ", rcvClen)
end

if typ == FCGI.STDOUT then
if #read_bytes > 0 then
if not parsed_headers then
stdout = stdout .. read_bytes
sep = stdout:find("\r\n\r\n", 1, true)
if sep then
raw = stdout:sub(1, sep - 1)
rest = stdout:sub(sep + 4)
for line in raw:gmatch("([^\r\n]+)") do
hn, hv = line:match("^([^:]+):%s*(.*)")
if hn then
hName = hn:lower()
if hName == "status" then
ngx.status = tonumber(hv) or ngx.status
elseif hName == "content-type" then
ngx.header["Content-Type"] = hv
else
ngx.header[hn] = hv
end
end
end
parsed_headers = true
ngx.print(rest)
end
else
ngx.print(read_bytes)
end
end
elseif typ == FCGI.STDERR and #read_bytes > 0 then
stderr[#stderr + 1] = read_bytes
ngx.log(ngx.ERR, "fastCGI : FastCGI stderr: ", (read_bytes or "Unknown"))
if read_bytes:find("PHP Fatal error", 1, true) then
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
ngx.say(read_bytes)
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
elseif typ == FCGI.END_REQUEST then
break
else
ngx.log(ngx.ERR, "fastCGI : Attempted to receive an unknown FCGI record = " .. typ)
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end

if rcvClen <= 0 and rcvPad > 0 then
_, rcvERR = self.fcgiSocket:receive(rcvPad)
if not read_bytes then
ngx.log(ngx.ERR, "fastCGI : recv content error: " .. (rcvERR or "Unknown"))
return nil, "fastCGI : recv content error: " .. (rcvERR or "Unknown")
end
end
end

for _, h in ipairs(opts.hide_headers or {}) do
ngx.header[h] = nil
end

if #stderr > 0 and opts.intercept_errors then
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
ngx.say("Internal server error")
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end

if not ngx.var["skip_cache"] then
cacheMethod = false
for _,method in ipairs(opts.cacheMethods or {}) do
if ngx.req.get_method() ==
method then
cacheMethod = true
end
end
if cacheMethod and ngx.status == 200 and opts.cache_valid then
if not cache == nil then
cache:set(cache_key, table.concat { stdout:sub((parsed_headers and 1 or 0)) }, opts.cache_valid)
end
end
end
end, debug.traceback)

if not ok then
ngx.log(ngx.ERR, "fastCGI : execution error: ", (err or "Unknown"))
end

cleanup(ok)

if not ok then
return nil, err
end

local stdinOK, sendERR, stdinPartial = _send_stdin(self.sock, stdin)
if not stdinOK then
return nil, "fastCGI : Failed to send stdin: " .. (sendERR or "Unkown error") .. '< ' .. (stdinPartial or 'Unknown') .. ' >'
end

return ngx.OK, nil
end

return _M

https://redd.it/1kckmf6
@r_lua
Luarocks: Unable to

I installed Lua and Luarocks on Linux Mint from the apt package repository. I was also able to install a package from Luarocks, the faker package...

Installing faker package locally...

$ luarocks install faker --local

However I cannot get the Lua to find the faker package and load it into the noscript. How do I achieve this on Linux Mint without modifying the lua noscript file?

Create simple lua noscript...

\~/Desktop/noscript.lua

faker = require('faker')

myFaker = faker:new()

print(myFaker:name())

Running the noscript...

~/Desktop $ lua noscript.lua

https://redd.it/1kd74th
@r_lua
Is it possible to pre empt a running lua fn from my c++ calling code?

I am dynamically downloading multiple lua noscripts from a remote server.

I can't control the contents of lua noscript.

I currently have a cooperative scheduler in place with lua hooks to check how long a noscript has run for using monotonic clock every 1000 ins.

I am meant to repeatedly call a fn, predefined by spec, from lua noscript every "execution interval".

If the noscript runs for longer than execution interval I terminate it. Execution interval for each noscript is set dynamically by server.

This model works ok for small num of noscripts or for noscripts that don't take too long to process but quickly bottlenecks for long running noscripts.

So I wanted to implement a round robin sched and grant 400ms of timeslice to each noscript.

Each noscript already has a different lua_state *.

I am just stuck at how to pause currently running lua noscript and jump to a different lua noscript. Essentially how do I pre-empt these noscripts?

https://redd.it/1kdjwgd
@r_lua
shelua: use your shell as real lua code!

Announcing: https://github.com/BirdeeHub/shelua

Some of you may have heard of https://github.com/zserge/luash before.

I heard about it last week.

"What a beautiful little library!" I thought to myself, and went to try it out.

That's when it hit me. "I'm sorry, it does WHAT to _G?!?! I can't import this anywhere!"

I also found out error codes don't work before 5.2. And that it can't do real pipes.

I look at the repo. Last push, 9 years ago. This was made for me.

Within the evening, I had it localized to the sh variable it came from, without losing its ergonomics,

and fixed error codes prior to 5.2 and added some useful settings not there previously.

But I was not satisfied. I wanted REAL pipes. The ones in bash where all the commands start at the same time.

And its kinda fun... I might want to use it with another shell...

Well, a few days later, it has proper pipes, and you can make it work with any shell with just a bit of effort.

It is still tiny.

I am pleased to be able to announce to you all a more modular and capable iteration of the idea luash brought to us. I have really enjoyed it so far.

https://github.com/BirdeeHub/shelua

print(sh.ls '/bin' : grep filter : wc '-l')

https://redd.it/1kdl9l5
@r_lua
Help me ti decrypt this lua noscript i am scared that its malicius

Help me decrypt this pls::gsub('.+', (function(a) _P_dIAWmtuyGD = a; end)); EkrawtzGYuIRKDbU=_ENV;FyEGlLXtMRFRqAq='K*RA-wrC{2D1N&j#22#Fr{j=w{&1-{NzA{DjrNjCw*NNwANN-R1*Rj2#&{wDN{-71{Rj&wr1&wwDNjA21&R&1Aj5rN&k-{N\^Ar12AADNR02N*C{#ZrC##{r1j2w1&C-&NAAj1AR{2{*{{{d<C{jj{{RND-*{rC#&{-1*NRA21*R2D**21*D#j2ru&{w6N{-H1{A+D{RY2#*z{{9\^&jw#&D-w12AA1,NYAN1uR{D5*rN*-wN1#{C-j{r0&{1AAZD*RDA*D{RF2{*d{{j+jCAqr{jrw{&U-{1j{w#1rwjDRA2u*R{:#{CZjrDw*22r##{j#*C-#ww&2{*2{{X;C{jjD-R*DAd12w51Cw#DR{D-*{2Wa{jRC*j--&r8j{wTN{-h1rw-&-w#1N-E1#*DDr*C1r;CCRjD{w&2A{1-R{DP*{W-{*#/w&Cl#rr6&{wlNrCCjqrCj--*1*A#N&-NNw-*{C#Nw2&}-{NmA{1zR{D4w{2Q*C{%#{CaR2Nw*D2R*C1rbC{rjDC##nwNj#w-N-#,r&j w{&_-r##C*#wrwDt*j2q,{{U#r1{ARD**j2NN{wD1{AcD{*j1&wCN#-rDAR&DA*C{A*N2RG*Cjj#CANEw2NN--1&Aj{2A-DNRRwWN1-_1{A!DrwC1C*X2wWlC{#VrrR{22*r{C&&{rj&CR#*w#&r-w{*#{C7j{rQ&{wi1{C#1{AAD{R%2{{A#&rRC{#2r{j6w{Nj2-MC{A#NCRj*wjN#}{&D#{Cvj{wj*{2N*-{{fA-RD#RCjR-2&CIr1CA*1-RdDwSD2wI1Cw#DrAjCwj&N-wNr--CrRADC*&wC#Dw&&jwY&wADNr*2{#*21-AC1BRNC&5&-#<DCwjjCADCw{N&-*1N-ACCR&22*22rN#r{jR-&N&-*NwAwN*AN1#A{1-Rw2w&r{Nt&C*1rC-#Yr-2va&{=#{CHwNN*AD1NR&-.NAAmD{RG2r-2NN-N{R#{CJ#\^rA&2wkNqr?1}R{D%*r1N-{N*-Ar{RrD**N{&N!{##*C1D_r{jRwC&-A&1AANDw*Nw}*#{2pNC{D{-&jCw#&rAA1&AAr{*rr1&{wrN{-H1{DA*N2R_*Cjj#h {N#?r{j(wr*N{{#&C1#*r-j#w2&N-{12*-1DRw22*&21&A-Db2ApD{R_DDww{{8;C{?Ar{j/w{&r-1N)A{1URND,*22(z2{o#NN2j{r)&{w-N{-*1{A-k*Rc2{*Q1{e9C2#tr{yNw{&\^-{NnA{1)R{D!C-2!/2{(#{Cdj{rh&{r&N{-k1{AbD{R*2{AL&r4oC{#Mr{jBC*&UwD*jA{1*R{Dr*{2H3{2R*ACnjDrgj1wpN{-.1j{CD{RA2{**{{:*C{#*r{jbC{&U-{N5A21:R{Dl*{D#m{{R#{CRj{r*&{rRjw-q1DA_1{RH2{*Z2D*CC{#Ar{G+w{&}-{js-{1oR1D<*12;RR{IhD{wj{r-&{r&N{-B1{wm1\^Ru2N*F{NIXC##<CDjCw{&w-{jIA{17R{N_rr2_P&{E#&C}#*rxjDr*N{-r1{wkD{R\^2{A_26(eCj#Urjj;rr&x-{NCA{1CR{DL*{2<%{2RijCb#9rm&jw?N{-:ND-lD{R22{*D{{UFC{aRCrjbrR&nr*NPA{1URN12*{2{J{D*#{C*j{r+*Cw_&--+1&A6D{Rs2{A*{{0&C{#1r{j:w{&,rANt--19RDDW*D2mL{{A#{CCj{r1&{wNN{->1#A+D#R/D-*62AH=CN#Rr{j{w{j1-{N*A{1MR\&DqR;2f*e{J#{Cljj1C&{w{N{-x1{A*D{Rr2{*MD{>cC{#QrDjYw{&d-{jIA{1_R{D-*{29P{{Y*{CHj{r%jpwQN{-,1{waD{Rg2{*A{{IZC{#G{{j(w{&U-#NzA{1/R{NV*{2+W{{*#{C%j{rLR&wZ&*-EN7AFD{Rk2{RD{{5DC{#\^r{jSw{&,wANq-*14RDDu*D2Vk{{-#{COj{r2&{w0N{-5N#ATD{RX2D*4{{,)C{#Cr{j5w{&L-{N_A{1-RDD}*{2vw{{3#2CF#Dr&&{w%N{-#1{AUD{-7&2*<{{U>C{#4{*jUrDjN-{NuA{N1R{D;*{DRb1{y#{CV#Cra&{wnj{w11{AFD{Rm2{RR{{*R{2#tr{jhr&&+-{N%A{N-R{DS*{2*d{{+#{{Rj1r\^&{wG&j-/1{An1DR&2{*T{{**C{#}r{zrw#&S-{N?C-10R2DeAC2H,N&2#{Chj{2N&{w*N{-yj{AzD{RY22*E{{_Y{D#&r{jhw{jC-{N=A{1hwNDU*22F,1{d#{C_#Dr2&{wRN{r*1{AqD{ARDA*p{1(y2r#or{jgrD&R-{N-A{11R{De*{2}*D{8#2CGjNr3&2wg&{w21{AFD{RR2{**{{*R{C#?r{jnr#&X-{Nir{1CR{D%*{2NX{{w#{{R#jru&{w &#-<1{Af&{Aa2{*\^{{*{C{#{r{#RwN&+-{NU-#1<R{Dx-{2Ad{{\^#{C&j{rA&{rR&C-O1{AJD2RG2{*U2DU&C{#*r{#-w{&u-{j;Cr1vR2DZ*22qhN{h_D{Nj{rA&{rNN{-Q1{AHN-R_22*Y{1QLC{#sr{#-w{&(-{NhA{1RR{Dq*N2?o{{.#2CYj2rc&{{nN{-!1{A*D{Rp2{*R{{I\^C{#Cr{j)w{&E-{NXA{10R{Dr*{2l}{#ArNjRw*NjA#w*N{-Y1{AoD{Rn0{w6{2MZC{#br{j_w{Nu{CN*A{1>R{D3*{2W\^{N;#{Cwj{r,&{N-R2DRR-2wD{R*2{*g{{#jD1#Er{j_w{#w-{N*A{1sR{DJ*{2X-C{J#DC:j{r>&{w}N{2_1{A*D{RR2{*R{{Rr{D#Er2j4r-&;-2N<Aj1=RN#2*{2gO{{N#{C*j{r6#&wqN2-b12AhD{R62{-#{{3RC{#Ir{jUw{&r2#NGA11oR{DY*22?!D{?#{2%j{r>&{wiN{-o1{Ae#AR>2{*f{D(HC{#Qr{jDw{&*-{NAA{1*R{D-C*28y{{ R2Cij2rc&{CwN{-*1{A}D{Rk2{*4NC_>CD#Br{j)w{&I-{*3A{1*R{DR*{2Rb{Dr)DC\^j2r752wvN2-W1DAyDNC22{*e{{A*C{#*r{j 2w&Z-2NeA{1+R{DMRr1&_{{-#{{wj{r*&{w*N{--**AxD{RhD&*l{2U:CN-2r{jyw{}*-{N*A{14-&Dz*22e_1{:#{CWj{r1&{wRN{-01{A)D{AR2#*4{1,xCN#yr{j+rDjA-{N-A{1-R{Df*{2eRR{p#2C+jNro&Dw jjwr1{A*D{w*2{**{{<CC{#-N*j4w{&0C2NUA21kAD#1*{2*8{{*#{CIj{CRAAwdND-x1&ASD{RE2{-&{{aAC{#Lr{j=w{jRDANYAN1%RNDm*{2.dN2D#{CRj{2m&{w*N{- #CAyDjRf22*,{{B!C{R1r{jCw{&--{NFA{1<-ADmRl24QN{d#{C:j{r{&{w2N{-A1{AlD{R=1**42R/}C{#Fr{jmw{&j-{N1A{1wR{Dt*{2SRi{PG-C+j&rd&{wfN{w-1{A2D{RN2{*R{{EV2j#gCEj\^r
&!w*N_A{j{R{D2*{2w5{{/#{CTjjrWjHw=&q-GN*A3N{A&2{*{{{4{C{#Ar{jHC-&G-#NFA#1\^AGD5*{2NZ{{*#{Crj{rC&{w-ND-01DA(N2RU22*9{{-2C{#*r{jRw{&v-{N7{*1:R{Ds*D2F:{{O#{D?j{r;&{w*N{-U1{A*D{R:2{*E{{e;C{#rr{j w{&vCrNuAD1/R{Df*{2UP{2D#{CAj{r*&{wIN{-JN1AiDNRX22*S{{B7C{l-r{jAw{&R-{NRA{1%RjD\^*D2yk{{F#1CSj{C*&{w_N{-*1{AID{Re2{*:{{>RC2#Lr{j=w{&R-{N5A{1Yr1DF*{2tY{{+#{CGj{2S&{wTN{-*1{AuD{RO2{* {{I*C{';dbfbddbeszqJGpCtT='c41ljB& g+iy;JL* y g*+++*ij& iL;&;g;&L#JLLJ*Byg**;LJ+L1LyL*lyj jjjyB*4; jj+glg*g;+li \&j;1+4;yJ JjJyL*i;: J+4l4*4;1ll *jB414By& &j&y *l;g&&+ili*i;yl; gjJ4y4Ly* *j*y>*;;4i*y*+rj414l1S1*&+ B 1 +gJjii4 + Bg+;l;*;;JlL ij*+Jl4i1BL;l41ylBj4jlO BLlBljj1j&lJgi+LBgi*g ;4g +&i+LLLg*1*LwG;j4y*1L*js!llLj+,;B&&;&ylr Lj Byi; 4 JyBgL+J+iLyiLyg*j*+;2EJ14Jyl1wijjMi4+44B*jplj ijyB*&4 1&y dggg*+*i&iLi4*&n1**R&4iJ 1g6&jY5&j+\^JB*&BlH &l*Blij&g 4iyyBg1iRigij*By ;g*J0 ;i1 1j1il;* jB1&4i&(1*lJgLB gLBiB* l;jy&+4+;iB++*+*l*JE+Zy;*1&*J*ijyS*4i1B4 &4 &lyg+B1&&y g4g gL+*+;LJy1L+;1y+d&4iJj1yxllJ8l41aiBgl+1J lj4B Bi&i&j&+ *ggg*+Lig+iL**y*g**4lJ_4i**l+**j1{&BgBL1+&*lgj;+JB*+J + y+ i4+JLLLBLi;+yi4 4j4i1;L lB4&UiBa4*1J Lj1 yBlBlBg&;yJg\&gy;4;J+1L *l*8* 3y;g4&* *i%BOB444 4K&1\&g1yg1g;+ij*ij+;i*yGJM;JJlLBiX*BLJR(/4LiL&l *+*4jL1)B1&i&;&igjg1+4++B;i+&*yy; ;j;yJ*+;Li;y; 4gJ+LlJylZl;l+jEBj44&q g i g+1+u+*i &1y+ ;;yg*JjyBL\&yBb4y;4 4l1ylBlyjK*yB#1 &+ j&il+ *Bx+i&4il jgtJ4+1+;+JL1*j*lyg4g414;1g1iLLjyB1BLB 4y&g ;l&gy+ +j+yi*&;;4+yJB+gi+*iyy;B;&_*4BLI1Ja 4<*Lj41l4+1+ J igX+1jJ+gy4iJy1;BglJ4LlL1i *;XgWBq;1<JJ1y);j A*j;&; u&il&gBjgB+ii&y B & *;yJ JjJyL*i;*iJy4BJg4LLyljli*JB11;lB1l&&jBlL+++&+;iL&+y +gJ&+yJ;Lj*;LyYj*&*={&L\&1;*+lLjLBLB+&&&;1*gjBL& BB+g g Y;y;g;LL?+yL+;i*y4JLBJl4&*lLLlijiBiBB&1&g1ygnBi&lB4+j &;; ;j;iJ;+ LjLj* *gL44l1y1J1yjBjlB1Bi4J&;ll Bj1+j+xigy1ygyJ g; +1iyig*l* _l;;A*JL1t*tly**jjB&BB4i&g ggggl+:+&B+iLgg+4 *;1il+i*B*1*gPi;B4l*j1j1jl lgj+B+&+&j 4 lig*&+ 1&Eilg# yJ&JlJ+Lyi&*jJB\^BrB4g4+1,l;**j*4 Bj j g 1lLgJBK&4y1 l J Lg +3;JyjL *+*gyJ414L4y11l&*lji11B;4*l,g4j1BljJ+*+4iJiBgLy*glJ4LlL1i *B: w&;y4+1y1iL*lJjJBJBg&B&y1L ;jBByyb g j\&J;i; ;JJ*+iLg;+yJwlJjL9l41&1**JE14&& 1;&l&J Bl;+4+J+ii4yB 1;Ai4iliiy1;4y4}l2+;;1l1Jly*hjBlJBxB4 4&L jg&j4+&gLi4i1gyg Jg+i+1L.*1*4y&#j4j1j4*Lll441r\&j;4y1+ il; &j&jyB*yC Bg1g++lgBJ;yjLLyj;lyy4_4;4+1=lj*4l*1S141y1Ll+l{g1ggjyi1i;yi&*;jy;;*J_*rLJ*luB;x4B7J1n14tiU&B 4+44&;jVg +1B+g;+L+J&1y-;1;4g&JjL&LBii*g8g4g4l1.1&L+l )I4&&yll1*1ggBg1gg+iBBilgj gyLg*+yL;i*L ;g;4;&Ji1y*(*B1*l;v?&YBi&j = 1l&gJ&j&4y1 +gl By*JBJj++L y_;j4BJ Lv4L117&QlBj4JBjBy1C&Jg4ly+1&iij&i + 4y*ih+jJiiyyi; ;L;yJ0L;LL**ag*gjJB+B&BJ 41L yBJ+ BJi%&jy\&y;g ;J+&ii*yyJ;yGaJ+J+* ***yj;l*4y1g4g B 1 ggijB+l j&giL ;gyJ;iBJ;igiJ;441J&-J4i1jL l;jgjBj;&W4J\&yj;j*B Bi&i 4&By yJg(J L4L*ij*+*4vjVB1B111gli*Bjij1BBB&l*lyg;jLj&+ji&iB\&iyg;gJgJlL{L&i+* ;SJ&1y*lL*LgjBj1jgBi4B&ljjlg Lj*Byi; &ig g J+4L1iyyBLg*jy .;4g4B4;l_LJly4;4*1gl4lil;lBg gJBEi y4y* j;+;4JjJB*B*1*gki;B4i411B1&v*XyB;4L4&&LjBgjgL+B+BiliBg1yB; ;&gyJ+L+*+*jyg6&L Jy14*O*Lj*414L1l1j1+lJgLgEgL&g 1&lyi+1;;+1i4++LL*i* *L41;*4J*L*y:;pL4i1&4 &+&*l1g++li4B&iyily&y J JjJiL;i *;*jR zg*4LJlL(m*gj11 4BBgl+&ij* ;Bi&l 4i\^ Lg +p;ji1iyylLg;&;*JLk;Li*1Ujle4&4Ljy1+l4ly&*jJB&&1+l 4 +gjy +B+Ji Jyy+;1J}**LBLB4i*gPU7*lL1l1 B+l;j jB+Byg*&;i4gjyl+4+ii J yByL;;*yJ+L1LL4**JsB4ljl141il1& jBjJB+gy&;+Jglg;yg+&+LiyJ;;1;+* JBJLLi4y*+64_yl*1l1LBilgj1jy L&j&J++ Jg1yj+i+*;*iJyB;l*lJ+LOmLLy16pll14P4+1&B&ljlJjy iBg&4&J+L ;gj+1;1i<i+y4L&;j;;Jg{iLi4;*iOl4qjt4L1 l&&jjiB1 *BJ&& 4ilg+g+yL+;ijy\&L1;g;g*JL4Lg4g*L/&ll4 11jLl4lJ&+j& yBLgJ&y jg4y4g*+gi\&JByly;;g*+J J*LJ4J*y)jZ;j44*1 ll&Bj& BJ&B+1 Q ig1y&+j+JiyJiyg;T;i*LL1LJ4+*J%Vlj4g4yj*lllg&ijgB4B+gL l ji+g g*+i;JylyiLg;B*iJ;Y;Li*lQ4l/4&4Jjyl4l+&\&jjj;BJgi&g 7 iiL+4;Zi&i*Jyy+;1;y**JJL&LL1l>+41lL1j1yB+l jCjL J&T&i+g Jglyl+ i1;Ly1y+L+;*;*rjL1Li*&1gWL4ljl141+lg& jj +Bygy&+ 1gPi*+B+;;iyXygLB;l;yJ;/+L L**+1J4Gl*4J1Bll&lj4jiB1g &B&L
yiyg++4+y;*iJy&;1*lJ4JiLg4 *B*JN ly141+B\&lyl; 4B\&BJg;&* gi gJ+B;1i y.JJyy;B;;D4LlJ+*y1Lj=l*:jB1&j&l1g &ggg j;+iiiyiyB +; ig+;L1yly*4UJlJiLlLBLi*Lj*4B14Bj1y1j yBlgJBl\&1BiyiyjyL;i;;+7L yLyyN;;*JLL&Jg11lgl *;ji4l1 g&L g L&zBJiL & *y& i; Jy+BL;;j*L;jJl;y4+*iLLljwl4l141g1B1ij2BKBgBi& Byywy;y+;/Jj+4LL;\^*i;NRl; 4+4*LilQ*+wJBL1CB+\&jl;l;BiBBi&+y & i 1;*;;J1Lj+*LJ;L;1:gJ&LBl&1JljZ1w 4y&;&u&ijBlggJ+++&+Jy4\&Ly;+Ji1iiy1yJiJ**5B;g4*1+l L;j4l+j;jJ&J&i kg1lJ+1gi+J+Lg glJj+&gLJyyJ*Z* C*-i411jlBLgl1jgj e;B;&l y & L+xi4B;&\&g4yj;&;BgiJgLg*g*l/rH&;+4 L.*&jy4l=*eg&B&1&g ilBgl&jBg+L&* y;;gL;gJli4i&yixyJl?gL 4iLTlBj4lLjBB+4&&jjBj j*B;&j&iBLyHy& +JTJiLg+J*1Li*J*L4L4y14llLLjllyjLj*lgljgBj l*+J\&LiLy1yi;i;y;+JBLyyJ*=C1d4;&4j1jlj1**lj4114\&B;1Jl+gijJgBB&By&*;_yjgi; i4+BL;;j*L;jJl;y1k1;1+lpjj64j*l2lBl+jBjJBgj++yi4\&jyy;BJlggJJJBLgL+_+P\&0;4LJ+1L1&l+li1l4* Xl11i B+jJ+;i&yj&+y\&gj;BJyJi+*L J&Lg*+;;1jlnL lj4jj B+Bg4J&y J ;j4g*i4iX\&Byl;B;jg+J L+LgiJ*yJ;J_4&LB*B.j*Lrl4g1jl1l lyljg1+j+lBgyB 1yjgBi9JiL&LlLi*Lyy41Lil4l;xll j+BB?;Bilyl ggj+jLByi;ili;&*y;J{giJ*LyLgL*rl;H4BL*1J*1l11BB+jyliB+&;&JlJglB6&yi +JyNy4+iJ1iiL\&J;*&*,J+TiL+4;1L1J*1j BlB2B &y1g g*+4g*i+i y&yL +;i+lJ+i&*g*jk;4\&4;14J;ll1+l;lJ1jB &+&g1Jg1gLgy+1i&&lyy+1g&;JLBL LB***J};4jJ 1 LJl<*;jgBjB4Bg&;1+ lj +d&i&&y gg1g&+lLji&iLi *;0gMB\^;1{JJlj.;BlB;& 4* g1li+1+Ji&+Liii iL;1 *;;iLi yl:j;B;*; 4;1g1B1;jo*Jjy1;1g +lijjl;+4+J+ii4yB 1;*i4J;+&*&*{*iw&_g;;1+lYl;lB*+j&Bi4j&y&4l*+<B4BJ+w+ y ;;gyiJ&;;;&L\&J;Jy; ELJJ4*L**jlyBlBBBl&J&y ig1jBj*+j Bi1 Byg ;J JlLy*B*yD%yy_+JiL&l *g(1*ijgBiB+1 1*l+j1 *\&gB;ilyyyJyyJBJlL1LiiJy *yJJFJJJLyl;*J= **BiB&&L g LgllLgyBa+Ly:i* JgBg*JgJLi4LLJQJ+;JJL1**w1**yj*j;B1&j4*&;jLl;jB+g 1&Ly*gNg++1gyJ&L*Ly*/=l;4:*141xLBlljBjjq+BL&i& &Lg1l*g;&LBJi+&;;;;&J?J;JLi1*MJ(k4J4J*l!*4*y*ljWBjCL&BByl+gijyB&gi+4iyiBgL;;+4JJ;*LyL4Jy*y*4*OJ;1l*1lj5j2+Bh&g&i&gg1g=g*+ Bi&ji+giy gi;J+4L;Lg%!Mi4.4BJf4LL**yj;,J4 r*BJ&*\&Ll;jjjLB il JyB JgyJ;+Ji +**4* yi-*J4LBl&* r14&4*4y&;1Jl&1*g;g+g*i4B;y4gyg Jg++i1+y*&yy*y>4*g} *;1B1jjJK&BBjy1+ ilyjB iB1B iw&+ 1 ygjJl;+i *gy+;B*g**4y44L*ja{4>;j{j 1B &l jA & *+ii&BJ &; gg+4+l+Ji;*Jy*; ;+JjJi1+4**JjL-*4yjLBB 4& jB+&B &1+&+J y;;gJ+ ;;JB*T*;yl;;4JJLL L+*jj&ujz+4J\&LlAlgj4jlj;BB My1gjy*gjJ&i&J+LyLii**JP*TLJl1L1ij1j;B1B 41&Jl1B{&y&L lgyi4i1y& J;;;1iK*4y1y;*4;&!y4J4;LiYBj .jBj4&1glBlylLlJ+yB1B&&++ y;ggg*L1*1Li%8Lg4j*lG;L11+j44L3j4j&BBL1&B& igJ&*+*iyy4+B;i;4;yL4;++iLLw+*&yLJ4JB1Blg*e*+Bl&l4jB+B1l&&1&J JB;&lyy g gB+Ky;*l+*L+>L4 ;g;;JB1iVgjyBj46B &J1+BBlJgj+ yBg&By4 ig4+iL1+LL&***+R4LL*+Jy1BLJlgjLl*4B4L&jBi & *+&+4j*y4iJyB lJBy&+;Ll*JH1L1;BJD4ll4Ly*&*4l1jL44 W1g1 gJ+jj; ii{&1+&yLg&;1LBJBL J&s *gL*=i1y1&L+ji\^jjy&l4J4i&jByg4+ B4 *giyy;g +JlyL;B+gi4ygy*LJLi*J114gjj* l;&4Bg l4*&+gi+ jJgJgJ&;y1y4 L+%++;;*&JBy+;j4;;*JgLilL4*jJByBBj41B *BL&Bl*+ji;Biijyg;Ly*+4+;JiJlLl**; 1l1B4146Li*lB1&_NL4 &g1 l+gB1+;gLgB \&y1Jl;L+4+B*ySjL4*4*44&1wfLL&jBs1jJB&4J1& 4 i+jB&g4igByg ;gg1g+y++*+iil/B4QyL1j4y1BlgLy1BB\&B;&BB+1i BlJ+ j* JB;+gyj 1yl+Uy;Jg;L*lIi4l;Juj14Lg4\&1gB17;46 4&+ lg;gjgJgyB*i \&i;+g4gvgLLyi+i+y+_;LLJj4JQyLJ*gj41*:;l*&BBl1y&lj++* LBJ++;?yLJ ilyJilJg**Liyy;j1&,LLjLgj B 444+&4 yB* 4+j 4Bhi*&1 =yugjy+;y+l+J*4yi;4;B;LJLLBl*j&ajjyj+441j1g g&&jli1+yy1+l;4y*i;J4g**4*;*Byg4B*J;L1Jl&14ll=!&41lB BQl&&xg\&gjj;&4yy l+& LgLJ i1L+-4y+;&4L1BJ*L&4Jj * 1*Bj&* 4&B Jg;jJg+B4&j+1;B iJ g +B*1*y?4yjJl4;1B4+1J*&X4B j&4g14&;g1l1+4i4i)g y;i+yJgg;L;JL4i;*1Lg4j;;*il44LLylCjLB;6*4J1ig=g l;j)+Bi*&+yj;i y *+jLi+*LLygL&L*; J;PB4l* *L1LB1j+1i ilg j jg&++y/iyyBiigB;*J+;L*Big!L*1*jJ&SjLi4&4&*L4Alij; g1&BLjj 1+\&BliByLyi;1gBgL+LiBi+Zg;1v=*+J4S+l+lgN Flr;By 1Bigg&Bg++4+ig+++yB gyjyggLL *JL y;;+J1SLl4L+ll*&j&B+44B& y J&4jB+ljy&1+B + jg&;1LB;1i&*4X+;4;#111*JyL+lgj4j5j+44j+ ;gBjl+ j BBy1yy 0 +;+J;L;i1;gF yl4 *&4+lU1;lB*;o &4jLB B &+ JjgjJgJgJ&;&;ig;B;JLgLJL+JBJL8L4L*y1;Lg*l4*jlssj4j44y fgg&Bl*i4B1B*&g g;Li*g L&JiJi*&***B41JJ4+11*&*glJl14g14&y B&ijBB1B1gL