static const char* curlimpl_str =
"--\n"
"-- Author: Alexey Melnichuk <alexeymelnichuck@gmail.com>\n"
"--\n"
"-- Copyright (C) 2014-2018 Alexey Melnichuk <alexeymelnichuck@gmail.com>\n"
"--\n"
"-- Licensed according to the included 'LICENSE' document\n"
"--\n"
"-- This file is part of Lua-cURL library.\n"
"--\n"
"\n"
"local module_info = {\n"
" _NAME = \"Lua-cURL\";\n"
" _VERSION = \"0.3.8\";\n"
" _LICENSE = \"MIT\";\n"
" _COPYRIGHT = \"Copyright (c) 2014-2018 Alexey Melnichuk\";\n"
"}\n"
"\n"
"local function hash_id(str)\n"
" local id = string.match(str, \"%((.-)%)\") or string.match(str, ': (%x+)$')\n"
" return id\n"
"end\n"
"\n"
"local function clone(t, o)\n"
" o = o or {}\n"
" for k,v in pairs(t) do o[k]=v end\n"
" return o\n"
"end\n"
"\n"
"local function wrap_function(k)\n"
" return function(self, ...)\n"
" local ok, err = self._handle[k](self._handle, ...)\n"
" if ok == self._handle then return self end\n"
" return ok, err\n"
" end\n"
"end\n"
"\n"
"local function wrap_setopt_flags(k, flags)\n"
" k = \"setopt_\" .. k\n"
" local flags2 = clone(flags)\n"
" for k, v in pairs(flags) do flags2[v] = v end\n"
"\n"
" return function(self, v)\n"
" v = assert(flags2[v], \"Unsupported value \" .. tostring(v))\n"
" local ok, err = self._handle[k](self._handle, v)\n"
" if ok == self._handle then return self end\n"
" return ok, err\n"
" end\n"
"end\n"
"\n"
"local function new_buffers()\n"
" local buffers = {resp = {}, _ = {}}\n"
"\n"
" function buffers:append(e, ...)\n"
" local resp = assert(e:getinfo_response_code())\n"
" if not self._[e] then self._[e] = {} end\n"
"\n"
" local b = self._[e]\n"
"\n"
" if self.resp[e] ~= resp then\n"
" b[#b + 1] = {\"response\", resp}\n"
" self.resp[e] = resp\n"
" end\n"
"\n"
" b[#b + 1] = {...}\n"
"end\n"
"\n"
" function buffers:next()\n"
" for e, t in pairs(self._) do\n"
" local m = table.remove(t, 1)\n"
" if m then return e, m end\n"
" end\n"
" end\n"
"\n"
" return buffers\n"
"end\n"
"\n"
"local function make_iterator(self, perform)\n"
" local curl = require \"lcurl.safe\"\n"
"\n"
" local buffers = new_buffers()\n"
" -- reset callbacks to all easy handles\n"
" local function reset_easy(self)\n"
" if not self._easy_mark then -- that means we have some new easy handles\n"
" for h, e in pairs(self._easy) do if h ~= 'n' then \n"
" e:setopt_writefunction (function(str) buffers:append(e, \"data\", str) end)\n"
" e:setopt_headerfunction(function(str) buffers:append(e, \"header\", str) end)\n"
" end end\n"
" self._easy_mark = true\n"
" end\n"
" return self._easy.n\n"
" end\n"
"\n"
" if 0 == reset_easy(self) then return end\n"
"\n"
" assert(perform(self))\n"
"\n"
" return function()\n"
" -- we can add new handle during iteration\n"
" local remain = reset_easy(self)\n"
"\n"
" -- wait next event\n"
" while true do\n"
" local e, t = buffers:next()\n"
" if t then return t[2], t[1], e end\n"
" if remain == 0 then break end\n"
"\n"
" self:wait()\n"
"\n"
" local n = assert(perform(self))\n"
"\n"
" if n <= remain then\n"
" while true do\n"
" local e, ok, err = assert(self:info_read())\n"
" if e == 0 then break end\n"
" if ok then\n"
" ok = e:getinfo_response_code() or ok\n"
" buffers:append(e, \"done\", ok)\n"
" else buffers:append(e, \"error\", err) end\n"
" self:remove_handle(e)\n"
" e:unsetopt_headerfunction()\n"
" e:unsetopt_writefunction()\n"
" end\n"
" end\n"
"\n"
" remain = n\n"
" end\n"
" end\n"
"end\n"
"\n"
"-- name = <string>/<stream>/<file>/<buffer>/<content>\n"
"--\n"
"-- <stream> = {\n"
"-- stream = function/object\n"
"-- length = ?number\n"
"-- name = ?string\n"
"-- type = ?string\n"
"-- headers = ?table\n"
"-- }\n"
"--\n"
"-- <file> = {\n"
"-- file = string\n"
"-- type = ?string\n"
"-- name = ?string\n"
"-- headers = ?table\n"
"-- }\n"
"--\n"
"-- <buffer> = {\n"
"-- data = string\n"
"-- name = string\n"
"-- type = ?string\n"
"-- headers = ?table\n"
"-- }\n"
"--\n"
"-- <content> = {\n"
"-- content = string -- or first key in table\n"
"-- type = ?string\n"
"-- headers = ?table\n"
"-- }\n"
"-- \n"
"\n"
"local function form_add_element(form, name, value)\n"
" local vt = type(value)\n"
" if vt == \"string\" then return form:add_content(name, value) end\n"
"\n"
" assert(type(name) == \"string\")\n"
" assert(vt == \"table\")\n"
" assert((value.name == nil) or (type(value.name ) == 'string'))\n"
" assert((value.type == nil) or (type(value.type ) == 'string'))\n"
" assert((value.headers == nil) or (type(value.headers) == 'table' ))\n"
"\n"
" if value.stream then\n"
" local vst = type(value.stream)\n"
"\n"
" if vst == 'function' then\n"
" assert(type(value.length) == 'number')\n"
" local length = value.length\n"
" return form:add_stream(name, value.name, value.type, value.headers, length, value.stream)\n"
" end\n"
"\n"
" if (vst == 'table') or (vst == 'userdata') then\n"
" local length = value.length or assert(value.stream:length())\n"
" assert(type(length) == 'number')\n"
" return form:add_stream(name, value.name, value.type, value.headers, length, value.stream)\n"
" end\n"
"\n"
" error(\"Unsupported stream type: \" .. vst)\n"
" end\n"
"\n"
" if value.file then\n"
" assert(type(value.file) == 'string')\n"
" return form:add_file(name, value.file, value.type, value.filename, value.headers)\n"
" end\n"
"\n"
" if value.data then\n"
" assert(type(value.data) == 'string')\n"
" assert(type(value.name) == 'string')\n"
" return form:add_buffer(name, value.name, value.data, value.type, value.headers)\n"
" end\n"
"\n"
" local content = value[1] or value.content\n"
" if content then\n"
" assert(type(content) == 'string')\n"
" if value.type then\n"
" return form:add_content(name, content, value.type, value.headers)\n"
" end\n"
" return form:add_content(name, content, value.headers)\n"
" end\n"
"\n"
" return form\n"
"end\n"
"\n"
"local function form_add(form, data)\n"
" for k, v in pairs(data) do\n"
" local ok, err = form_add_element(form, k, v)\n"
" if not ok then return nil, err end\n"
" end\n"
"\n"
" return form\n"
"end\n"
"\n"
"local function class(ctor)\n"
" local C = {}\n"
" C.__index = function(self, k)\n"
" local fn = C[k]\n"
"\n"
" if not fn and self._handle[k] then\n"
" fn = wrap_function(k)\n"
" C[k] = fn\n"
" end\n"
" return fn\n"
" end\n"
"\n"
" function C:new(...)\n"
" local h, err = ctor()\n"
" if not h then return nil, err end\n"
"\n"
" local o = setmetatable({\n"
" _handle = h\n"
" }, self)\n"
"\n"
" if self.__init then return self.__init(o, ...) end\n"
"\n"
" return o\n"
" end\n"
"\n"
" function C:handle()\n"
" return self._handle\n"
" end\n"
"\n"
" return C\n"
"end\n"
"\n"
"local function Load_cURLv2(cURL, curl)\n"
"\n"
"-------------------------------------------\n"
"local Easy = class(curl.easy) do\n"
"\n"
"local perform = wrap_function(\"perform\")\n"
"local setopt_share = wrap_function(\"setopt_share\")\n"
"local setopt_readfunction = wrap_function(\"setopt_readfunction\")\n"
"\n"
"local NONE = {}\n"
"\n"
"function Easy:_call_readfunction(...)\n"
" if self._rd_ud == NONE then\n"
" return self._rd_fn(...)\n"
" end\n"
" return self._rd_fn(self._rd_ud, ...)\n"
"end\n"
"\n"
"function Easy:setopt_readfunction(fn, ...)\n"
" assert(fn)\n"
"\n"
" if select('#', ...) == 0 then\n"
" if type(fn) == \"function\" then\n"
" self._rd_fn = fn\n"
" self._rd_ud = NONE\n"
" else\n"
" self._rd_fn = assert(fn.read)\n"
" self._rd_ud = fn\n"
" end\n"
" else\n"
" self._rd_fn = fn\n"
" self._ud_fn = ...\n"
" end\n"
"\n"
" return setopt_readfunction(self, fn, ...)\n"
"end\n"
"\n"
"function Easy:perform(opt)\n"
" opt = opt or {}\n"
"\n"
" local oerror = opt.errorfunction or function(err) return nil, err end\n"
"\n"
" if opt.readfunction then\n"
" local ok, err = self:setopt_readfunction(opt.readfunction)\n"
" if not ok then return oerror(err) end\n"
" end\n"
"\n"
" if opt.writefunction then\n"
" local ok, err = self:setopt_writefunction(opt.writefunction)\n"
" if not ok then return oerror(err) end\n"
" end\n"
"\n"
" if opt.headerfunction then\n"
" local ok, err = self:setopt_headerfunction(opt.headerfunction)\n"
" if not ok then return oerror(err) end\n"
" end\n"
"\n"
" local ok, err = perform(self)\n"
" if not ok then return oerror(err) end\n"
"\n"
" return self \n"
"end\n"
"\n"
"function Easy:post(data)\n"
" local form = curl.form()\n"
" local ok, err = true\n"
"\n"
" for k, v in pairs(data) do\n"
" if type(v) == \"string\" then\n"
" ok, err = form:add_content(k, v)\n"
" else\n"
" assert(type(v) == \"table\")\n"
" if v.stream_length then\n"
" local len = assert(tonumber(v.stream_length))\n"
" assert(v.file)\n"
" if v.stream then\n"
" ok, err = form:add_stream(k, v.file, v.type, v.headers, len, v.stream)\n"
" else\n"
" ok, err = form:add_stream(k, v.file, v.type, v.headers, len, self._call_readfunction, self)\n"
" end\n"
" elseif v.data then\n"
" ok, err = form:add_buffer(k, v.file, v.data, v.type, v.headers)\n"
" else\n"
" ok, err = form:add_file(k, v.file, v.type, v.filename, v.headers)\n"
" end\n"
" end\n"
" if not ok then break end\n"
" end\n"
"\n"
" if not ok then\n"
" form:free()\n"
" return nil, err\n"
" end\n"
"\n"
" ok, err = self:setopt_httppost(form)\n"
" if not ok then\n"
" form:free()\n"
" return nil, err\n"
" end\n"
"\n"
" return self\n"
"end\n"
"\n"
"function Easy:setopt_share(s)\n"
" return setopt_share(self, s:handle())\n"
"end\n"
"\n"
"Easy.setopt_proxytype = wrap_setopt_flags(\"proxytype\", {\n"
" [\"HTTP\" ] = curl.PROXY_HTTP;\n"
" [\"HTTP_1_0\" ] = curl.PROXY_HTTP_1_0;\n"
" [\"SOCKS4\" ] = curl.PROXY_SOCKS4;\n"
" [\"SOCKS5\" ] = curl.PROXY_SOCKS5;\n"
" [\"SOCKS4A\" ] = curl.PROXY_SOCKS4A;\n"
" [\"SOCKS5_HOSTNAME\" ] = curl.PROXY_SOCKS5_HOSTNAME;\n"
" [\"HTTPS\" ] = curl.PROXY_HTTPS;\n"
"})\n"
"\n"
"Easy.setopt_httpauth = wrap_setopt_flags(\"httpauth\", {\n"
" [\"NONE\" ] = curl.AUTH_NONE;\n"
" [\"BASIC\" ] = curl.AUTH_BASIC;\n"
" [\"DIGEST\" ] = curl.AUTH_DIGEST;\n"
" [\"GSSNEGOTIATE\" ] = curl.AUTH_GSSNEGOTIATE;\n"
" [\"NEGOTIATE\" ] = curl.AUTH_NEGOTIATE;\n"
" [\"NTLM\" ] = curl.AUTH_NTLM;\n"
" [\"DIGEST_IE\" ] = curl.AUTH_DIGEST_IE;\n"
" [\"GSSAPI\" ] = curl.AUTH_GSSAPI;\n"
" [\"NTLM_WB\" ] = curl.AUTH_NTLM_WB;\n"
" [\"ONLY\" ] = curl.AUTH_ONLY;\n"
" [\"ANY\" ] = curl.AUTH_ANY;\n"
" [\"ANYSAFE\" ] = curl.AUTH_ANYSAFE;\n"
"})\n"
"\n"
"Easy.setopt_ssh_auth_types = wrap_setopt_flags(\"ssh_auth_types\", {\n"
" [\"NONE\" ] = curl.SSH_AUTH_NONE;\n"
" [\"ANY\" ] = curl.SSH_AUTH_ANY;\n"
" [\"PUBLICKEY\" ] = curl.SSH_AUTH_PUBLICKEY;\n"
" [\"PASSWORD\" ] = curl.SSH_AUTH_PASSWORD;\n"
" [\"HOST\" ] = curl.SSH_AUTH_HOST;\n"
" [\"GSSAPI\" ] = curl.SSH_AUTH_GSSAPI;\n"
" [\"KEYBOARD\" ] = curl.SSH_AUTH_KEYBOARD;\n"
" [\"AGENT\" ] = curl.SSH_AUTH_AGENT;\n"
" [\"DEFAULT\" ] = curl.SSH_AUTH_DEFAULT;\n"
"})\n"
"\n"
"end\n"
"-------------------------------------------\n"
"\n"
"-------------------------------------------\n"
"local Multi = class(curl.multi) do\n"
"\n"
"local perform = wrap_function(\"perform\")\n"
"local add_handle = wrap_function(\"add_handle\")\n"
"local remove_handle = wrap_function(\"remove_handle\")\n"
"\n"
"function Multi:__init()\n"
" self._easy = {n = 0}\n"
" return self\n"
"end\n"
"\n"
"function Multi:perform()\n"
" return make_iterator(self, perform)\n"
"end\n"
"\n"
"function Multi:add_handle(e)\n"
" assert(self._easy.n >= 0)\n"
"\n"
" local h = e:handle()\n"
" if self._easy[h] then return self end\n"
"\n"
" local ok, err = add_handle(self, h)\n"
" if not ok then return nil, err end\n"
" self._easy[h], self._easy.n = e, self._easy.n + 1\n"
" self._easy_mark = nil\n"
"\n"
" return self\n"
"end\n"
"\n"
"function Multi:remove_handle(e)\n"
" local h = e:handle()\n"
"\n"
" if self._easy[h] then\n"
" self._easy[h], self._easy.n = nil, self._easy.n - 1\n"
" end\n"
" assert(self._easy.n >= 0)\n"
"\n"
" return remove_handle(self, h)\n"
"end\n"
"\n"
"function Multi:info_read(...)\n"
" while true do\n"
" local h, ok, err = self:handle():info_read(...)\n"
" if not h then return nil, ok end\n"
" if h == 0 then return h end\n"
"\n"
" local e = self._easy[h]\n"
" if e then\n"
" if ... then\n"
" self._easy[h], self._easy.n = nil, self._easy.n - 1\n"
" end\n"
" return e, ok, err\n"
" end\n"
" end\n"
"end\n"
"\n"
"end\n"
"-------------------------------------------\n"
"\n"
"-------------------------------------------\n"
"local Share = class(curl.share) do\n"
"\n"
"Share.setopt_share = wrap_setopt_flags(\"share\", {\n"
" [ \"COOKIE\" ] = curl.LOCK_DATA_COOKIE;\n"
" [ \"DNS\" ] = curl.LOCK_DATA_DNS;\n"
" [ \"SSL_SESSION\" ] = curl.LOCK_DATA_SSL_SESSION;\n"
"})\n"
"\n"
"end\n"
"-------------------------------------------\n"
"\n"
"assert(cURL.easy_init == nil)\n"
"function cURL.easy_init() return Easy:new() end\n"
"\n"
"assert(cURL.multi_init == nil)\n"
"function cURL.multi_init() return Multi:new() end\n"
"\n"
"assert(cURL.share_init == nil)\n"
"function cURL.share_init() return Share:new() end\n"
"\n"
"end\n"
"\n"
"local function Load_cURLv3(cURL, curl)\n"
"\n"
"-------------------------------------------\n"
"local Form = class(curl.form) do\n"
"\n"
"function Form:__init(opt)\n"
" if opt then return self:add(opt) end\n"
" return self\n"
"end\n"
"\n"
"function Form:add(data)\n"
" return form_add(self, data)\n"
"end\n"
"\n"
"function Form:__tostring()\n"
" local id = hash_id(tostring(self._handle))\n"
" return string.format(\"%s %s (%s)\", module_info._NAME, 'Form', id)\n"
"end\n"
"\n"
"end\n"
"-------------------------------------------\n"
"\n"
"-------------------------------------------\n"
"local Easy = class(curl.easy) do\n"
"\n"
"function Easy:__init(opt)\n"
" if opt then return self:setopt(opt) end\n"
" return self\n"
"end\n"
"\n"
"local perform = wrap_function(\"perform\")\n"
"function Easy:perform(opt)\n"
" if opt then\n"
" local ok, err = self:setopt(opt)\n"
" if not ok then return nil, err end\n"
" end\n"
"\n"
" return perform(self)\n"
"end\n"
"\n"
"local setopt_httppost = wrap_function(\"setopt_httppost\")\n"
"function Easy:setopt_httppost(form)\n"
" return setopt_httppost(self, form:handle())\n"
"end\n"
"\n"
"if curl.OPT_STREAM_DEPENDS then\n"
"\n"
"local setopt_stream_depends = wrap_function(\"setopt_stream_depends\")\n"
"function Easy:setopt_stream_depends(easy)\n"
" return setopt_stream_depends(self, easy:handle())\n"
"end\n"
"\n"
"local setopt_stream_depends_e = wrap_function(\"setopt_stream_depends_e\")\n"
"function Easy:setopt_stream_depends_e(easy)\n"
" return setopt_stream_depends_e(self, easy:handle())\n"
"end\n"
"\n"
"end\n"
"\n"
"local setopt = wrap_function(\"setopt\")\n"
"local custom_setopt = {\n"
" [curl.OPT_HTTPPOST or true] = 'setopt_httppost';\n"
" [curl.OPT_STREAM_DEPENDS or true] = 'setopt_stream_depends';\n"
" [curl.OPT_STREAM_DEPENDS_E or true] = 'setopt_stream_depends_e';\n"
"}\n"
"custom_setopt[true] = nil\n"
"\n"
"function Easy:setopt(k, v)\n"
" if type(k) == 'table' then\n"
" local t = k\n"
"\n"
" local t2\n"
" local hpost = t.httppost or t[curl.OPT_HTTPPOST]\n"
" if hpost and hpost._handle then\n"
" t = t2 or clone(t); t2 = t;\n"
" if t.httppost then t.httppost = hpost:handle() end\n"
" if t[curl.OPT_HTTPPOST] then t[curl.OPT_HTTPPOST] = hpost:handle() end\n"
" end\n"
"\n"
" local easy = t.stream_depends or t[curl.OPT_STREAM_DEPENDS]\n"
" if easy and easy._handle then\n"
" t = t2 or clone(t); t2 = t;\n"
" if t.stream_depends then t.stream_depends = easy:handle() end\n"
" if t[curl.OPT_STREAM_DEPENDS] then t[curl.OPT_STREAM_DEPENDS] = easy:handle() end\n"
" end\n"
"\n"
" local easy = t.stream_depends_e or t[curl.OPT_STREAM_DEPENDS_E]\n"
" if easy and easy._handle then\n"
" t = t2 or clone(t); t2 = t;\n"
" if t.stream_depends_e then t.stream_depends_e = easy:handle() end\n"
" if t[curl.OPT_STREAM_DEPENDS_E] then t[curl.OPT_STREAM_DEPENDS_E] = easy:handle() end\n"
" end\n"
"\n"
" return setopt(self, t)\n"
" end\n"
"\n"
" local setname = custom_setopt[k]\n"
" if setname then\n"
" return self[setname](self, v)\n"
" end\n"
"\n"
" return setopt(self, k, v)\n"
"end\n"
"\n"
"function Easy:__tostring()\n"
" local id = hash_id(tostring(self._handle))\n"
" return string.format(\"%s %s (%s)\", module_info._NAME, 'Easy', id)\n"
"end\n"
"\n"
"end\n"
"-------------------------------------------\n"
"\n"
"-------------------------------------------\n"
"local Multi = class(curl.multi) do\n"
"\n"
"local add_handle = wrap_function(\"add_handle\")\n"
"local remove_handle = wrap_function(\"remove_handle\")\n"
"\n"
"function Multi:__init(opt)\n"
" self._easy = {n = 0}\n"
" if opt then self:setopt(opt) end\n"
" return self\n"
"end\n"
"\n"
"function Multi:iperform()\n"
" return make_iterator(self, self.perform)\n"
"end\n"
"\n"
"function Multi:add_handle(e)\n"
" assert(self._easy.n >= 0)\n"
"\n"
" local h = e:handle()\n"
" if self._easy[h] then\n"
" return nil, curl.error(curl.ERROR_MULTI, curl.E_MULTI_ADDED_ALREADY or curl.E_MULTI_BAD_EASY_HANDLE)\n"
" end\n"
"\n"
" local ok, err = add_handle(self, h)\n"
" if not ok then return nil, err end\n"
" self._easy[h], self._easy.n = e, self._easy.n + 1\n"
" self._easy_mark = nil\n"
"\n"
" return self\n"
"end\n"
"\n"
"function Multi:remove_handle(e)\n"
" local h = e:handle()\n"
"\n"
" if self._easy[h] then\n"
" self._easy[h], self._easy.n = nil, self._easy.n - 1\n"
" end\n"
" assert(self._easy.n >= 0)\n"
"\n"
" return remove_handle(self, h)\n"
"end\n"
"\n"
"function Multi:info_read(...)\n"
" while true do\n"
" local h, ok, err = self:handle():info_read(...)\n"
" if not h then return nil, ok end\n"
" if h == 0 then return h end\n"
"\n"
" local e = self._easy[h]\n"
" if e then\n"
" if ... then\n"
" self._easy[h], self._easy.n = nil, self._easy.n - 1\n"
" end\n"
" return e, ok, err\n"
" end\n"
" end\n"
"end\n"
"\n"
"local function wrap_callback(...)\n"
" local n = select(\"#\", ...)\n"
" local fn, ctx, has_ctx\n"
" if n >= 2 then\n"
" has_ctx, fn, ctx = true, assert(...)\n"
" else\n"
" fn = assert(...)\n"
" if type(fn) ~= \"function\" then\n"
" has_ctx, fn, ctx = true, assert(fn.socket), fn\n"
" end\n"
" end\n"
" if has_ctx then\n"
" return function(...) return fn(ctx, ...) end\n"
" end\n"
" return function(...) return fn(...) end\n"
"end\n"
"\n"
"local function wrap_socketfunction(self, cb)\n"
" return function(h, ...)\n"
" local e = self._easy[h]\n"
" if e then return cb(e, ...) end\n"
" return 0\n"
" end\n"
"end\n"
"\n"
"local setopt_socketfunction = wrap_function(\"setopt_socketfunction\")\n"
"function Multi:setopt_socketfunction(...)\n"
" local cb = wrap_callback(...)\n"
"\n"
" return setopt_socketfunction(self, wrap_socketfunction(self, cb))\n"
"end\n"
"\n"
"local setopt = wrap_function(\"setopt\")\n"
"function Multi:setopt(k, v)\n"
" if type(k) == 'table' then\n"
" local t = k\n"
"\n"
" local socketfunction = t.socketfunction or t[curl.OPT_SOCKETFUNCTION]\n"
" if socketfunction then\n"
" t = clone(t)\n"
" local fn = wrap_socketfunction(self, socketfunction)\n"
" if t.socketfunction then t.socketfunction = fn end\n"
" if t[curl.OPT_SOCKETFUNCTION] then t[curl.OPT_SOCKETFUNCTION] = fn end\n"
" end\n"
"\n"
" return setopt(self, t)\n"
" end\n"
"\n"
" if k == curl.OPT_SOCKETFUNCTION then\n"
" return self:setopt_socketfunction(v)\n"
" end\n"
"\n"
" return setopt(self, k, v)\n"
"end\n"
"\n"
"function Multi:__tostring()\n"
" local id = hash_id(tostring(self._handle))\n"
" return string.format(\"%s %s (%s)\", module_info._NAME, 'Multi', id)\n"
"end\n"
"\n"
"end\n"
"-------------------------------------------\n"
"\n"
"setmetatable(cURL, {__index = curl})\n"
"\n"
"function cURL.form(...) return Form:new(...) end\n"
"\n"
"function cURL.easy(...) return Easy:new(...) end\n"
"\n"
"function cURL.multi(...) return Multi:new(...) end\n"
"\n"
"end\n"
"\n"
"return function(curl)\n"
" local cURL = clone(module_info)\n"
"\n"
" Load_cURLv3(cURL, curl)\n"
"\n"
" Load_cURLv2(cURL, curl)\n"
"\n"
" return cURL\n"
"end\n"
;