aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2025-03-04 02:19:37 -0300
committerHisham Muhammad <hisham@gobolinux.org>2025-03-10 10:51:04 -0300
commitcc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a (patch)
tree44b6e247a28934361ff979d32f677832a1d281a8
parent9e162d9e980f7e17c0ea41e0cd29173d01ada330 (diff)
downloadluarocks-cc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a.tar.gz
luarocks-cc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a.tar.bz2
luarocks-cc887b9b25571e9ce0afa0cd5e4a4a2cbf130d3a.zip
[wip] vendor in dependencies
-rw-r--r--vendor/lua-bz2/LICENSE13
-rw-r--r--vendor/lua-bz2/README27
-rw-r--r--vendor/lua-bz2/bz2/ltn12.lua93
-rw-r--r--vendor/lua-bz2/compat-5.3.c948
-rw-r--r--vendor/lua-bz2/compat-5.3.h424
-rw-r--r--vendor/lua-bz2/lbz.c52
-rw-r--r--vendor/lua-bz2/lbz2_common.c57
-rw-r--r--vendor/lua-bz2/lbz2_common.h25
-rw-r--r--vendor/lua-bz2/lbz2_file_reader.c164
-rw-r--r--vendor/lua-bz2/lbz2_file_reader.h25
-rw-r--r--vendor/lua-bz2/lbz2_file_writer.c141
-rw-r--r--vendor/lua-bz2/lbz2_file_writer.h25
-rw-r--r--vendor/lua-bz2/lbz2_stream.c263
-rw-r--r--vendor/lua-bz2/lbz2_stream.h25
-rw-r--r--vendor/lua-bz2/lua-bz2-0.2.1-1.rockspec48
-rw-r--r--vendor/lua-zlib/.gitattributes1
-rw-r--r--vendor/lua-zlib/README163
-rw-r--r--vendor/lua-zlib/lua-zlib-1.1-0.rockspec42
-rw-r--r--vendor/lua-zlib/lua_zlib.c1295
-rw-r--r--vendor/luafilesystem/.gitignore2
-rw-r--r--vendor/luafilesystem/.travis.yml34
-rw-r--r--vendor/luafilesystem/LICENSE21
-rw-r--r--vendor/luafilesystem/README.md28
-rw-r--r--vendor/luafilesystem/luafilesystem-scm-1.rockspec28
-rw-r--r--vendor/luafilesystem/src/.gitignore2
-rw-r--r--vendor/luafilesystem/src/lfs.c1182
-rw-r--r--vendor/luafilesystem/src/lfs.def4
-rw-r--r--vendor/luafilesystem/src/lfs.h35
-rw-r--r--vendor/luasec/.gitignore3
-rw-r--r--vendor/luasec/CHANGELOG257
-rw-r--r--vendor/luasec/INSTALL39
-rw-r--r--vendor/luasec/LICENSE21
-rw-r--r--vendor/luasec/README.md6
-rw-r--r--vendor/luasec/luasec-1.3.2-1.rockspec105
-rw-r--r--vendor/luasec/src/Makefile66
-rw-r--r--vendor/luasec/src/compat.h63
-rw-r--r--vendor/luasec/src/config.c108
-rw-r--r--vendor/luasec/src/context.c1099
-rw-r--r--vendor/luasec/src/context.h47
-rw-r--r--vendor/luasec/src/ec.c116
-rw-r--r--vendor/luasec/src/ec.h22
-rw-r--r--vendor/luasec/src/https.lua147
-rw-r--r--vendor/luasec/src/luasocket/LICENSE21
-rw-r--r--vendor/luasec/src/luasocket/Makefile26
-rw-r--r--vendor/luasec/src/luasocket/buffer.c278
-rw-r--r--vendor/luasec/src/luasocket/buffer.h45
-rw-r--r--vendor/luasec/src/luasocket/io.c30
-rw-r--r--vendor/luasec/src/luasocket/io.h65
-rw-r--r--vendor/luasec/src/luasocket/socket.h78
-rw-r--r--vendor/luasec/src/luasocket/timeout.c220
-rw-r--r--vendor/luasec/src/luasocket/timeout.h28
-rw-r--r--vendor/luasec/src/luasocket/usocket.c441
-rw-r--r--vendor/luasec/src/luasocket/usocket.h70
-rw-r--r--vendor/luasec/src/luasocket/wsocket.c429
-rw-r--r--vendor/luasec/src/luasocket/wsocket.h38
-rw-r--r--vendor/luasec/src/options.c185
-rw-r--r--vendor/luasec/src/options.h22
-rw-r--r--vendor/luasec/src/options.lua93
-rw-r--r--vendor/luasec/src/ssl.c1092
-rw-r--r--vendor/luasec/src/ssl.h41
-rw-r--r--vendor/luasec/src/ssl.lua313
-rw-r--r--vendor/luasec/src/x509.c750
-rw-r--r--vendor/luasec/src/x509.h31
-rw-r--r--vendor/luasocket/.editorconfig23
-rw-r--r--vendor/luasocket/.gitignore15
-rw-r--r--vendor/luasocket/.luacheckrc31
-rw-r--r--vendor/luasocket/CHANGELOG.md65
-rw-r--r--vendor/luasocket/FIX28
-rw-r--r--vendor/luasocket/LICENSE19
-rw-r--r--vendor/luasocket/README.md12
-rw-r--r--vendor/luasocket/TODO81
-rw-r--r--vendor/luasocket/WISH22
-rw-r--r--vendor/luasocket/logo.ps210
-rw-r--r--vendor/luasocket/luasocket-scm-3.rockspec135
-rw-r--r--vendor/luasocket/luasocket.sln35
-rw-r--r--vendor/luasocket/src/auxiliar.c154
-rw-r--r--vendor/luasocket/src/auxiliar.h54
-rw-r--r--vendor/luasocket/src/buffer.c273
-rw-r--r--vendor/luasocket/src/buffer.h52
-rw-r--r--vendor/luasocket/src/compat.c39
-rw-r--r--vendor/luasocket/src/compat.h22
-rw-r--r--vendor/luasocket/src/except.c129
-rw-r--r--vendor/luasocket/src/except.h46
-rw-r--r--vendor/luasocket/src/ftp.lua329
-rw-r--r--vendor/luasocket/src/headers.lua104
-rw-r--r--vendor/luasocket/src/http.lua424
-rwxr-xr-xvendor/luasocket/src/inet.c537
-rw-r--r--vendor/luasocket/src/inet.h56
-rw-r--r--vendor/luasocket/src/io.c28
-rw-r--r--vendor/luasocket/src/io.h70
-rw-r--r--vendor/luasocket/src/ltn12.lua318
-rwxr-xr-xvendor/luasocket/src/luasocket.c104
-rw-r--r--vendor/luasocket/src/luasocket.h36
-rwxr-xr-xvendor/luasocket/src/makefile461
-rw-r--r--vendor/luasocket/src/mbox.lua93
-rwxr-xr-xvendor/luasocket/src/mime.c852
-rw-r--r--vendor/luasocket/src/mime.h22
-rw-r--r--vendor/luasocket/src/mime.lua81
-rw-r--r--vendor/luasocket/src/options.c480
-rw-r--r--vendor/luasocket/src/options.h113
-rw-r--r--vendor/luasocket/src/pierror.h28
-rw-r--r--vendor/luasocket/src/select.c214
-rw-r--r--vendor/luasocket/src/select.h23
-rw-r--r--vendor/luasocket/src/serial.c171
-rw-r--r--vendor/luasocket/src/smtp.lua256
-rwxr-xr-xvendor/luasocket/src/socket.h75
-rw-r--r--vendor/luasocket/src/socket.lua149
-rw-r--r--vendor/luasocket/src/tcp.c480
-rw-r--r--vendor/luasocket/src/tcp.h43
-rw-r--r--vendor/luasocket/src/timeout.c226
-rw-r--r--vendor/luasocket/src/timeout.h40
-rw-r--r--vendor/luasocket/src/tp.lua134
-rwxr-xr-xvendor/luasocket/src/udp.c488
-rw-r--r--vendor/luasocket/src/udp.h39
-rw-r--r--vendor/luasocket/src/unix.c69
-rw-r--r--vendor/luasocket/src/unix.h26
-rw-r--r--vendor/luasocket/src/unixdgram.c405
-rw-r--r--vendor/luasocket/src/unixdgram.h28
-rw-r--r--vendor/luasocket/src/unixstream.c355
-rw-r--r--vendor/luasocket/src/unixstream.h29
-rw-r--r--vendor/luasocket/src/url.lua331
-rw-r--r--vendor/luasocket/src/usocket.c454
-rw-r--r--vendor/luasocket/src/usocket.h59
-rwxr-xr-xvendor/luasocket/src/wsocket.c434
-rw-r--r--vendor/luasocket/src/wsocket.h33
-rw-r--r--vendor/md5/.gitignore4
-rw-r--r--vendor/md5/README.md47
-rw-r--r--vendor/md5/rockspec/md5-1.2-1.rockspec35
-rw-r--r--vendor/md5/src/compat-5.2.c21
-rw-r--r--vendor/md5/src/compat-5.2.h15
-rwxr-xr-xvendor/md5/src/des56.c548
-rw-r--r--vendor/md5/src/des56.def5
-rwxr-xr-xvendor/md5/src/des56.h77
-rw-r--r--vendor/md5/src/ldes56.c152
-rwxr-xr-xvendor/md5/src/ldes56.h1
-rwxr-xr-xvendor/md5/src/md5.c262
-rw-r--r--vendor/md5/src/md5.def5
-rwxr-xr-xvendor/md5/src/md5.h40
-rw-r--r--vendor/md5/src/md5.lua26
-rw-r--r--vendor/md5/src/md5lib.c200
140 files changed, 23142 insertions, 0 deletions
diff --git a/vendor/lua-bz2/LICENSE b/vendor/lua-bz2/LICENSE
new file mode 100644
index 00000000..cc1b14dc
--- /dev/null
+++ b/vendor/lua-bz2/LICENSE
@@ -0,0 +1,13 @@
1Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org>
2
3Permission to use, copy, modify, and/or distribute this software for any
4purpose with or without fee is hereby granted, provided that the above
5copyright notice and this permission notice appear in all copies.
6
7THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/vendor/lua-bz2/README b/vendor/lua-bz2/README
new file mode 100644
index 00000000..a5361ad6
--- /dev/null
+++ b/vendor/lua-bz2/README
@@ -0,0 +1,27 @@
1A Lua binding to Julian Seward's libbzip2.
2
3Current maintainer: harningt@gmail.com
4Previous maintainer: evan@yelp.com
5
6This software is released under a BSD-style license (to be exact, the ISC
7license). The full license can be found in the LICENSE file included with this
8source code.
9
10Requirements:
11 * libbzip2
12 * Lua >= 5.1
13
14Tested Operating Systems:
15 * Mac OSX 10.5
16 * Linux
17 * Ubuntu
18 * Gentoo
19
20Patches to make this work fully on Windows and other OSes are welcome.
21
22More information about Lua: http://www.lua.org/
23More information about bzip2: http://www.bzip.org/
24
25Current Repository Details
26 Project : https://github.com/harningt/lua-bz2/tree
27 Public Git : git://github.com/harningt/lua-bz2.git
diff --git a/vendor/lua-bz2/bz2/ltn12.lua b/vendor/lua-bz2/bz2/ltn12.lua
new file mode 100644
index 00000000..d2da675d
--- /dev/null
+++ b/vendor/lua-bz2/bz2/ltn12.lua
@@ -0,0 +1,93 @@
1local _M = {}
2local bz2 = require("bz2")
3
4_M.filter = {}
5_M.source = {}
6_M.sink = {}
7
8local function buildProcessor(filter, err)
9 if not filter then
10 return nil, err
11 end
12 return function(chunk)
13 if not filter then
14 return nil, "closed"
15 end
16 -- Skip empty chunks due to unexpected 'flushing'
17 if chunk and #chunk == 0 then
18 return ""
19 end
20 -- On nil, update closes the stream out as ltn12 expects
21 local ret, err = filter:update(chunk)
22 if not chunk then
23 filter:close()
24 filter = nil
25 end
26 if not ret then
27 return nil, err
28 end
29 return ret
30 end
31
32end
33
34function _M.filter.compress(blockSize100k, verbosity, workFactor)
35 return buildProcessor(bz2.initCompress(blockSize100k, verbosity, workFactor))
36end
37
38function _M.filter.decompress(verbosity, small)
39 return buildProcessor(bz2.initDecompress(verbosity, small))
40end
41
42function _M.sink.file(name, blockSize100k, verbosity, workFactor)
43 local writer, err = bz2.openWrite(name, blockSize100k, verbosity, workFactor)
44 if not writer then
45 return nil, err
46 end
47 return function(data)
48 if not writer then
49 return nil, "closed"
50 end
51 if not data then
52 writer:close()
53 writer = nil
54 return
55 end
56 if #data == 0 then
57 return 1
58 end
59 local ret, err = writer:write(data)
60 if not ret then
61 return nil, err
62 end
63 return 1
64 end
65end
66
67function _M.source.file(name, verbosity, small)
68 local reader, err = bz2.openRead(name, verbosity, small)
69 if not reader then
70 return nil, err
71 end
72 return function()
73 if not reader then
74 return
75 end
76 local ret, err = reader:read(true)
77 if ret and #ret == 0 then
78 reader:close()
79 reader = nil
80 return
81 end
82 if not ret then
83 return nil, err
84 end
85 if err then
86 reader:close()
87 reader = nil
88 end
89 return ret
90 end
91end
92
93return _M
diff --git a/vendor/lua-bz2/compat-5.3.c b/vendor/lua-bz2/compat-5.3.c
new file mode 100644
index 00000000..42b0a4bb
--- /dev/null
+++ b/vendor/lua-bz2/compat-5.3.c
@@ -0,0 +1,948 @@
1#include <stddef.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <errno.h>
6#include <stdio.h>
7#include "compat-5.3.h"
8
9/* don't compile it again if it already is included via compat53.h */
10#ifndef COMPAT53_C_
11#define COMPAT53_C_
12
13
14
15/* definitions for Lua 5.1 only */
16#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
17
18#ifndef COMPAT53_FOPEN_NO_LOCK
19# if defined(_MSC_VER)
20# define COMPAT53_FOPEN_NO_LOCK 1
21# else /* otherwise */
22# define COMPAT53_FOPEN_NO_LOCK 0
23# endif /* VC++ only so far */
24#endif /* No-lock fopen_s usage if possible */
25
26#if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK
27# include <share.h>
28#endif /* VC++ _fsopen for share-allowed file read */
29
30#ifndef COMPAT53_HAVE_STRERROR_R
31# if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
32 (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) || \
33 defined(__APPLE__)
34# define COMPAT53_HAVE_STRERROR_R 1
35# else /* none of the defines matched: define to 0 */
36# define COMPAT53_HAVE_STRERROR_R 0
37# endif /* have strerror_r of some form */
38#endif /* strerror_r */
39
40#ifndef COMPAT53_HAVE_STRERROR_S
41# if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \
42 defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__)
43# define COMPAT53_HAVE_STRERROR_S 1
44# else /* not VC++ or C11 */
45# define COMPAT53_HAVE_STRERROR_S 0
46# endif /* strerror_s from VC++ or C11 */
47#endif /* strerror_s */
48
49#ifndef COMPAT53_LUA_FILE_BUFFER_SIZE
50# define COMPAT53_LUA_FILE_BUFFER_SIZE 4096
51#endif /* Lua File Buffer Size */
52
53
54static char* compat53_strerror (int en, char* buff, size_t sz) {
55#if COMPAT53_HAVE_STRERROR_R
56 /* use strerror_r here, because it's available on these specific platforms */
57 if (sz > 0) {
58 buff[0] = '\0';
59 /* we don't care whether the GNU version or the XSI version is used: */
60 if (strerror_r(en, buff, sz)) {
61 /* Yes, we really DO want to ignore the return value!
62 * GCC makes that extra hard, not even a (void) cast will do. */
63 }
64 if (buff[0] == '\0') {
65 /* Buffer is unchanged, so we probably have called GNU strerror_r which
66 * returned a static constant string. Chances are that strerror will
67 * return the same static constant string and therefore be thread-safe. */
68 return strerror(en);
69 }
70 }
71 return buff; /* sz is 0 *or* strerror_r wrote into the buffer */
72#elif COMPAT53_HAVE_STRERROR_S
73 /* for MSVC and other C11 implementations, use strerror_s since it's
74 * provided by default by the libraries */
75 strerror_s(buff, sz, en);
76 return buff;
77#else
78 /* fallback, but strerror is not guaranteed to be threadsafe due to modifying
79 * errno itself and some impls not locking a static buffer for it ... but most
80 * known systems have threadsafe errno: this might only change if the locale
81 * is changed out from under someone while this function is being called */
82 (void)buff;
83 (void)sz;
84 return strerror(en);
85#endif
86}
87
88
89COMPAT53_API int lua_absindex (lua_State *L, int i) {
90 if (i < 0 && i > LUA_REGISTRYINDEX)
91 i += lua_gettop(L) + 1;
92 return i;
93}
94
95
96static void compat53_call_lua (lua_State *L, char const code[], size_t len,
97 int nargs, int nret) {
98 lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code);
99 if (lua_type(L, -1) != LUA_TFUNCTION) {
100 lua_pop(L, 1);
101 if (luaL_loadbuffer(L, code, len, "=none"))
102 lua_error(L);
103 lua_pushvalue(L, -1);
104 lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code);
105 }
106 lua_insert(L, -nargs-1);
107 lua_call(L, nargs, nret);
108}
109
110
111static const char compat53_arith_code[] =
112 "local op,a,b=...\n"
113 "if op==0 then return a+b\n"
114 "elseif op==1 then return a-b\n"
115 "elseif op==2 then return a*b\n"
116 "elseif op==3 then return a/b\n"
117 "elseif op==4 then return a%b\n"
118 "elseif op==5 then return a^b\n"
119 "elseif op==6 then return -a\n"
120 "end\n";
121
122COMPAT53_API void lua_arith (lua_State *L, int op) {
123 if (op < LUA_OPADD || op > LUA_OPUNM)
124 luaL_error(L, "invalid 'op' argument for lua_arith");
125 luaL_checkstack(L, 5, "not enough stack slots");
126 if (op == LUA_OPUNM)
127 lua_pushvalue(L, -1);
128 lua_pushnumber(L, op);
129 lua_insert(L, -3);
130 compat53_call_lua(L, compat53_arith_code,
131 sizeof(compat53_arith_code)-1, 3, 1);
132}
133
134
135static const char compat53_compare_code[] =
136 "local a,b=...\n"
137 "return a<=b\n";
138
139COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op) {
140 int result = 0;
141 switch (op) {
142 case LUA_OPEQ:
143 return lua_equal(L, idx1, idx2);
144 case LUA_OPLT:
145 return lua_lessthan(L, idx1, idx2);
146 case LUA_OPLE:
147 luaL_checkstack(L, 5, "not enough stack slots");
148 idx1 = lua_absindex(L, idx1);
149 idx2 = lua_absindex(L, idx2);
150 lua_pushvalue(L, idx1);
151 lua_pushvalue(L, idx2);
152 compat53_call_lua(L, compat53_compare_code,
153 sizeof(compat53_compare_code)-1, 2, 1);
154 result = lua_toboolean(L, -1);
155 lua_pop(L, 1);
156 return result;
157 default:
158 luaL_error(L, "invalid 'op' argument for lua_compare");
159 }
160 return 0;
161}
162
163
164COMPAT53_API void lua_copy (lua_State *L, int from, int to) {
165 int abs_to = lua_absindex(L, to);
166 luaL_checkstack(L, 1, "not enough stack slots");
167 lua_pushvalue(L, from);
168 lua_replace(L, abs_to);
169}
170
171
172COMPAT53_API void lua_len (lua_State *L, int i) {
173 switch (lua_type(L, i)) {
174 case LUA_TSTRING:
175 lua_pushnumber(L, (lua_Number)lua_objlen(L, i));
176 break;
177 case LUA_TTABLE:
178 if (!luaL_callmeta(L, i, "__len"))
179 lua_pushnumber(L, (lua_Number)lua_objlen(L, i));
180 break;
181 case LUA_TUSERDATA:
182 if (luaL_callmeta(L, i, "__len"))
183 break;
184 /* FALLTHROUGH */
185 default:
186 luaL_error(L, "attempt to get length of a %s value",
187 lua_typename(L, lua_type(L, i)));
188 }
189}
190
191
192COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p) {
193 int abs_i = lua_absindex(L, i);
194 lua_pushlightuserdata(L, (void*)p);
195 lua_rawget(L, abs_i);
196 return lua_type(L, -1);
197}
198
199COMPAT53_API void lua_rawsetp (lua_State *L, int i, const void *p) {
200 int abs_i = lua_absindex(L, i);
201 luaL_checkstack(L, 1, "not enough stack slots");
202 lua_pushlightuserdata(L, (void*)p);
203 lua_insert(L, -2);
204 lua_rawset(L, abs_i);
205}
206
207
208COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum) {
209 lua_Number n = lua_tonumber(L, i);
210 if (isnum != NULL) {
211 *isnum = (n != 0 || lua_isnumber(L, i));
212 }
213 return n;
214}
215
216
217COMPAT53_API void luaL_checkversion (lua_State *L) {
218 (void)L;
219}
220
221
222COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg) {
223 if (!lua_checkstack(L, sp+LUA_MINSTACK)) {
224 if (msg != NULL)
225 luaL_error(L, "stack overflow (%s)", msg);
226 else {
227 lua_pushliteral(L, "stack overflow");
228 lua_error(L);
229 }
230 }
231}
232
233
234COMPAT53_API int luaL_getsubtable (lua_State *L, int i, const char *name) {
235 int abs_i = lua_absindex(L, i);
236 luaL_checkstack(L, 3, "not enough stack slots");
237 lua_pushstring(L, name);
238 lua_gettable(L, abs_i);
239 if (lua_istable(L, -1))
240 return 1;
241 lua_pop(L, 1);
242 lua_newtable(L);
243 lua_pushstring(L, name);
244 lua_pushvalue(L, -2);
245 lua_settable(L, abs_i);
246 return 0;
247}
248
249
250COMPAT53_API lua_Integer luaL_len (lua_State *L, int i) {
251 lua_Integer res = 0;
252 int isnum = 0;
253 luaL_checkstack(L, 1, "not enough stack slots");
254 lua_len(L, i);
255 res = lua_tointegerx(L, -1, &isnum);
256 lua_pop(L, 1);
257 if (!isnum)
258 luaL_error(L, "object length is not an integer");
259 return res;
260}
261
262
263COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
264 luaL_checkstack(L, nup+1, "too many upvalues");
265 for (; l->name != NULL; l++) { /* fill the table with given functions */
266 int i;
267 lua_pushstring(L, l->name);
268 for (i = 0; i < nup; i++) /* copy upvalues to the top */
269 lua_pushvalue(L, -(nup + 1));
270 lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
271 lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */
272 }
273 lua_pop(L, nup); /* remove upvalues */
274}
275
276
277COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname) {
278 luaL_checkstack(L, 1, "not enough stack slots");
279 luaL_getmetatable(L, tname);
280 lua_setmetatable(L, -2);
281}
282
283
284COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname) {
285 void *p = lua_touserdata(L, i);
286 luaL_checkstack(L, 2, "not enough stack slots");
287 if (p == NULL || !lua_getmetatable(L, i))
288 return NULL;
289 else {
290 int res = 0;
291 luaL_getmetatable(L, tname);
292 res = lua_rawequal(L, -1, -2);
293 lua_pop(L, 2);
294 if (!res)
295 p = NULL;
296 }
297 return p;
298}
299
300
301static int compat53_countlevels (lua_State *L) {
302 lua_Debug ar;
303 int li = 1, le = 1;
304 /* find an upper bound */
305 while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
306 /* do a binary search */
307 while (li < le) {
308 int m = (li + le)/2;
309 if (lua_getstack(L, m, &ar)) li = m + 1;
310 else le = m;
311 }
312 return le - 1;
313}
314
315static int compat53_findfield (lua_State *L, int objidx, int level) {
316 if (level == 0 || !lua_istable(L, -1))
317 return 0; /* not found */
318 lua_pushnil(L); /* start 'next' loop */
319 while (lua_next(L, -2)) { /* for each pair in table */
320 if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */
321 if (lua_rawequal(L, objidx, -1)) { /* found object? */
322 lua_pop(L, 1); /* remove value (but keep name) */
323 return 1;
324 }
325 else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */
326 lua_remove(L, -2); /* remove table (but keep name) */
327 lua_pushliteral(L, ".");
328 lua_insert(L, -2); /* place '.' between the two names */
329 lua_concat(L, 3);
330 return 1;
331 }
332 }
333 lua_pop(L, 1); /* remove value */
334 }
335 return 0; /* not found */
336}
337
338static int compat53_pushglobalfuncname (lua_State *L, lua_Debug *ar) {
339 int top = lua_gettop(L);
340 lua_getinfo(L, "f", ar); /* push function */
341 lua_pushvalue(L, LUA_GLOBALSINDEX);
342 if (compat53_findfield(L, top + 1, 2)) {
343 lua_copy(L, -1, top + 1); /* move name to proper place */
344 lua_pop(L, 2); /* remove pushed values */
345 return 1;
346 }
347 else {
348 lua_settop(L, top); /* remove function and global table */
349 return 0;
350 }
351}
352
353static void compat53_pushfuncname (lua_State *L, lua_Debug *ar) {
354 if (*ar->namewhat != '\0') /* is there a name? */
355 lua_pushfstring(L, "function " LUA_QS, ar->name);
356 else if (*ar->what == 'm') /* main? */
357 lua_pushliteral(L, "main chunk");
358 else if (*ar->what == 'C') {
359 if (compat53_pushglobalfuncname(L, ar)) {
360 lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
361 lua_remove(L, -2); /* remove name */
362 }
363 else
364 lua_pushliteral(L, "?");
365 }
366 else
367 lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
368}
369
370#define COMPAT53_LEVELS1 12 /* size of the first part of the stack */
371#define COMPAT53_LEVELS2 10 /* size of the second part of the stack */
372
373COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1,
374 const char *msg, int level) {
375 lua_Debug ar;
376 int top = lua_gettop(L);
377 int numlevels = compat53_countlevels(L1);
378 int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0;
379 if (msg) lua_pushfstring(L, "%s\n", msg);
380 lua_pushliteral(L, "stack traceback:");
381 while (lua_getstack(L1, level++, &ar)) {
382 if (level == mark) { /* too many levels? */
383 lua_pushliteral(L, "\n\t..."); /* add a '...' */
384 level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */
385 }
386 else {
387 lua_getinfo(L1, "Slnt", &ar);
388 lua_pushfstring(L, "\n\t%s:", ar.short_src);
389 if (ar.currentline > 0)
390 lua_pushfstring(L, "%d:", ar.currentline);
391 lua_pushliteral(L, " in ");
392 compat53_pushfuncname(L, &ar);
393 lua_concat(L, lua_gettop(L) - top);
394 }
395 }
396 lua_concat(L, lua_gettop(L) - top);
397}
398
399
400COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
401 const char *serr = NULL;
402 int en = errno; /* calls to Lua API may change this value */
403 char buf[512] = { 0 };
404 if (stat) {
405 lua_pushboolean(L, 1);
406 return 1;
407 }
408 else {
409 lua_pushnil(L);
410 serr = compat53_strerror(en, buf, sizeof(buf));
411 if (fname)
412 lua_pushfstring(L, "%s: %s", fname, serr);
413 else
414 lua_pushstring(L, serr);
415 lua_pushnumber(L, (lua_Number)en);
416 return 3;
417 }
418}
419
420
421static int compat53_checkmode (lua_State *L, const char *mode, const char *modename, int err) {
422 if (mode && strchr(mode, modename[0]) == NULL) {
423 lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode);
424 return err;
425 }
426 return LUA_OK;
427}
428
429
430typedef struct {
431 lua_Reader reader;
432 void *ud;
433 int has_peeked_data;
434 const char *peeked_data;
435 size_t peeked_data_size;
436} compat53_reader_data;
437
438
439static const char *compat53_reader (lua_State *L, void *ud, size_t *size) {
440 compat53_reader_data *data = (compat53_reader_data *)ud;
441 if (data->has_peeked_data) {
442 data->has_peeked_data = 0;
443 *size = data->peeked_data_size;
444 return data->peeked_data;
445 } else
446 return data->reader(L, data->ud, size);
447}
448
449
450COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *source, const char *mode) {
451 int status = LUA_OK;
452 compat53_reader_data compat53_data = { 0, NULL, 1, 0, 0 };
453 compat53_data.reader = reader;
454 compat53_data.ud = data;
455 compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size));
456 if (compat53_data.peeked_data && compat53_data.peeked_data_size &&
457 compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */
458 status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX);
459 else
460 status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX);
461 if (status != LUA_OK)
462 return status;
463 /* we need to call the original 5.1 version of lua_load! */
464#undef lua_load
465 return lua_load(L, compat53_reader, &compat53_data, source);
466#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
467}
468
469
470typedef struct {
471 int n; /* number of pre-read characters */
472 FILE *f; /* file being read */
473 char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */
474} compat53_LoadF;
475
476
477static const char *compat53_getF (lua_State *L, void *ud, size_t *size) {
478 compat53_LoadF *lf = (compat53_LoadF *)ud;
479 (void)L; /* not used */
480 if (lf->n > 0) { /* are there pre-read characters to be read? */
481 *size = lf->n; /* return them (chars already in buffer) */
482 lf->n = 0; /* no more pre-read characters */
483 }
484 else { /* read a block from file */
485 /* 'fread' can return > 0 *and* set the EOF flag. If next call to
486 'compat53_getF' called 'fread', it might still wait for user input.
487 The next check avoids this problem. */
488 if (feof(lf->f)) return NULL;
489 *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */
490 }
491 return lf->buff;
492}
493
494
495static int compat53_errfile (lua_State *L, const char *what, int fnameindex) {
496 char buf[512] = {0};
497 const char *serr = compat53_strerror(errno, buf, sizeof(buf));
498 const char *filename = lua_tostring(L, fnameindex) + 1;
499 lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr);
500 lua_remove(L, fnameindex);
501 return LUA_ERRFILE;
502}
503
504
505static int compat53_skipBOM (compat53_LoadF *lf) {
506 const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */
507 int c;
508 lf->n = 0;
509 do {
510 c = getc(lf->f);
511 if (c == EOF || c != *(const unsigned char *)p++) return c;
512 lf->buff[lf->n++] = (char)c; /* to be read by the parser */
513 } while (*p != '\0');
514 lf->n = 0; /* prefix matched; discard it */
515 return getc(lf->f); /* return next character */
516}
517
518
519/*
520** reads the first character of file 'f' and skips an optional BOM mark
521** in its beginning plus its first line if it starts with '#'. Returns
522** true if it skipped the first line. In any case, '*cp' has the
523** first "valid" character of the file (after the optional BOM and
524** a first-line comment).
525*/
526static int compat53_skipcomment (compat53_LoadF *lf, int *cp) {
527 int c = *cp = compat53_skipBOM(lf);
528 if (c == '#') { /* first line is a comment (Unix exec. file)? */
529 do { /* skip first line */
530 c = getc(lf->f);
531 } while (c != EOF && c != '\n');
532 *cp = getc(lf->f); /* skip end-of-line, if present */
533 return 1; /* there was a comment */
534 }
535 else return 0; /* no comment */
536}
537
538
539COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) {
540 compat53_LoadF lf;
541 int status, readstatus;
542 int c;
543 int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
544 if (filename == NULL) {
545 lua_pushliteral(L, "=stdin");
546 lf.f = stdin;
547 }
548 else {
549 lua_pushfstring(L, "@%s", filename);
550#if defined(_MSC_VER)
551 /* This code is here to stop a deprecation error that stops builds
552 * if a certain macro is defined. While normally not caring would
553 * be best, some header-only libraries and builds can't afford to
554 * dictate this to the user. A quick check shows that fopen_s this
555 * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET,
556 * possibly even before that so we don't need to do any version
557 * number checks, since this has been there since forever. */
558
559 /* TO USER: if you want the behavior of typical fopen_s/fopen,
560 * which does lock the file on VC++, define the macro used below to 0 */
561#if COMPAT53_FOPEN_NO_LOCK
562 lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */
563 if (lf.f == NULL)
564 return compat53_errfile(L, "open", fnameindex);
565#else /* use default locking version */
566 if (fopen_s(&lf.f, filename, "r") != 0)
567 return compat53_errfile(L, "open", fnameindex);
568#endif /* Locking vs. No-locking fopen variants */
569#else
570 lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */
571 if (lf.f == NULL) return compat53_errfile(L, "open", fnameindex);
572#endif
573 }
574 if (compat53_skipcomment(&lf, &c)) /* read initial portion */
575 lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */
576 if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
577#if defined(_MSC_VER)
578 if (freopen_s(&lf.f, filename, "rb", lf.f) != 0)
579 return compat53_errfile(L, "reopen", fnameindex);
580#else
581 lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */
582 if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex);
583#endif
584 compat53_skipcomment(&lf, &c); /* re-read initial portion */
585 }
586 if (c != EOF)
587 lf.buff[lf.n++] = (char)c; /* 'c' is the first character of the stream */
588 status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode);
589 readstatus = ferror(lf.f);
590 if (filename) fclose(lf.f); /* close file (even in case of errors) */
591 if (readstatus) {
592 lua_settop(L, fnameindex); /* ignore results from 'lua_load' */
593 return compat53_errfile(L, "read", fnameindex);
594 }
595 lua_remove(L, fnameindex);
596 return status;
597}
598
599
600COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) {
601 int status = LUA_OK;
602 if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) {
603 status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX);
604 }
605 else {
606 status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX);
607 }
608 if (status != LUA_OK)
609 return status;
610 return luaL_loadbuffer(L, buff, sz, name);
611}
612
613
614#if !defined(l_inspectstat) && \
615 (defined(unix) || defined(__unix) || defined(__unix__) || \
616 defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \
617 (defined(__APPLE__) && defined(__MACH__)))
618/* some form of unix; check feature macros in unistd.h for details */
619# include <unistd.h>
620/* check posix version; the relevant include files and macros probably
621 * were available before 2001, but I'm not sure */
622# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
623# include <sys/wait.h>
624# define l_inspectstat(stat,what) \
625 if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
626 else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
627# endif
628#endif
629
630/* provide default (no-op) version */
631#if !defined(l_inspectstat)
632# define l_inspectstat(stat,what) ((void)0)
633#endif
634
635
636COMPAT53_API int luaL_execresult (lua_State *L, int stat) {
637 const char *what = "exit";
638 if (stat == -1)
639 return luaL_fileresult(L, 0, NULL);
640 else {
641 l_inspectstat(stat, what);
642 if (*what == 'e' && stat == 0)
643 lua_pushboolean(L, 1);
644 else
645 lua_pushnil(L);
646 lua_pushstring(L, what);
647 lua_pushinteger(L, stat);
648 return 3;
649 }
650}
651
652
653COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B) {
654 /* make it crash if used via pointer to a 5.1-style luaL_Buffer */
655 B->b.p = NULL;
656 B->b.L = NULL;
657 B->b.lvl = 0;
658 /* reuse the buffer from the 5.1-style luaL_Buffer though! */
659 B->ptr = B->b.buffer;
660 B->capacity = LUAL_BUFFERSIZE;
661 B->nelems = 0;
662 B->L2 = L;
663}
664
665
666COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s) {
667 if (B->capacity - B->nelems < s) { /* needs to grow */
668 char* newptr = NULL;
669 size_t newcap = B->capacity * 2;
670 if (newcap - B->nelems < s)
671 newcap = B->nelems + s;
672 if (newcap < B->capacity) /* overflow */
673 luaL_error(B->L2, "buffer too large");
674 newptr = (char*)lua_newuserdata(B->L2, newcap);
675 memcpy(newptr, B->ptr, B->nelems);
676 if (B->ptr != B->b.buffer)
677 lua_replace(B->L2, -2); /* remove old buffer */
678 B->ptr = newptr;
679 B->capacity = newcap;
680 }
681 return B->ptr+B->nelems;
682}
683
684
685COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l) {
686 memcpy(luaL_prepbuffsize(B, l), s, l);
687 luaL_addsize(B, l);
688}
689
690
691COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B) {
692 size_t len = 0;
693 const char *s = lua_tolstring(B->L2, -1, &len);
694 if (!s)
695 luaL_error(B->L2, "cannot convert value to string");
696 if (B->ptr != B->b.buffer)
697 lua_insert(B->L2, -2); /* userdata buffer must be at stack top */
698 luaL_addlstring(B, s, len);
699 lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1);
700}
701
702
703void luaL_pushresult (luaL_Buffer_53 *B) {
704 lua_pushlstring(B->L2, B->ptr, B->nelems);
705 if (B->ptr != B->b.buffer)
706 lua_replace(B->L2, -2); /* remove userdata buffer */
707}
708
709
710#endif /* Lua 5.1 */
711
712
713
714/* definitions for Lua 5.1 and Lua 5.2 */
715#if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM <= 502
716
717
718COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i) {
719 index = lua_absindex(L, index);
720 lua_pushinteger(L, i);
721 lua_gettable(L, index);
722 return lua_type(L, -1);
723}
724
725
726#ifndef LUA_EXTRASPACE
727#define LUA_EXTRASPACE (sizeof(void*))
728#endif
729
730COMPAT53_API void *lua_getextraspace (lua_State *L) {
731 int is_main = 0;
732 void *ptr = NULL;
733 luaL_checkstack(L, 4, "not enough stack slots available");
734 lua_pushliteral(L, "__compat53_extraspace");
735 lua_pushvalue(L, -1);
736 lua_rawget(L, LUA_REGISTRYINDEX);
737 if (!lua_istable(L, -1)) {
738 lua_pop(L, 1);
739 lua_createtable(L, 0, 2);
740 lua_createtable(L, 0, 1);
741 lua_pushliteral(L, "k");
742 lua_setfield(L, -2, "__mode");
743 lua_setmetatable(L, -2);
744 lua_pushvalue(L, -2);
745 lua_pushvalue(L, -2);
746 lua_rawset(L, LUA_REGISTRYINDEX);
747 }
748 lua_replace(L, -2);
749 is_main = lua_pushthread(L);
750 lua_rawget(L, -2);
751 ptr = lua_touserdata(L, -1);
752 if (!ptr) {
753 lua_pop(L, 1);
754 ptr = lua_newuserdata(L, LUA_EXTRASPACE);
755 if (is_main) {
756 memset(ptr, '\0', LUA_EXTRASPACE);
757 lua_pushthread(L);
758 lua_pushvalue(L, -2);
759 lua_rawset(L, -4);
760 lua_pushboolean(L, 1);
761 lua_pushvalue(L, -2);
762 lua_rawset(L, -4);
763 } else {
764 void* mptr = NULL;
765 lua_pushboolean(L, 1);
766 lua_rawget(L, -3);
767 mptr = lua_touserdata(L, -1);
768 if (mptr)
769 memcpy(ptr, mptr, LUA_EXTRASPACE);
770 else
771 memset(ptr, '\0', LUA_EXTRASPACE);
772 lua_pop(L, 1);
773 lua_pushthread(L);
774 lua_pushvalue(L, -2);
775 lua_rawset(L, -4);
776 }
777 }
778 lua_pop(L, 2);
779 return ptr;
780}
781
782
783COMPAT53_API int lua_isinteger (lua_State *L, int index) {
784 if (lua_type(L, index) == LUA_TNUMBER) {
785 lua_Number n = lua_tonumber(L, index);
786 lua_Integer i = lua_tointeger(L, index);
787 if (i == n)
788 return 1;
789 }
790 return 0;
791}
792
793
794COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum) {
795 int ok = 0;
796 lua_Number n = lua_tonumberx(L, i, &ok);
797 if (ok) {
798 if (n == (lua_Integer)n) {
799 if (isnum)
800 *isnum = 1;
801 return (lua_Integer)n;
802 }
803 }
804 if (isnum)
805 *isnum = 0;
806 return 0;
807}
808
809
810static void compat53_reverse (lua_State *L, int a, int b) {
811 for (; a < b; ++a, --b) {
812 lua_pushvalue(L, a);
813 lua_pushvalue(L, b);
814 lua_replace(L, a);
815 lua_replace(L, b);
816 }
817}
818
819
820COMPAT53_API void lua_rotate (lua_State *L, int idx, int n) {
821 int n_elems = 0;
822 idx = lua_absindex(L, idx);
823 n_elems = lua_gettop(L)-idx+1;
824 if (n < 0)
825 n += n_elems;
826 if ( n > 0 && n < n_elems) {
827 luaL_checkstack(L, 2, "not enough stack slots available");
828 n = n_elems - n;
829 compat53_reverse(L, idx, idx+n-1);
830 compat53_reverse(L, idx+n, idx+n_elems-1);
831 compat53_reverse(L, idx, idx+n_elems-1);
832 }
833}
834
835
836COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i) {
837 luaL_checkstack(L, 1, "not enough stack slots available");
838 index = lua_absindex(L, index);
839 lua_pushinteger(L, i);
840 lua_insert(L, -2);
841 lua_settable(L, index);
842}
843
844
845#if !defined(lua_str2number)
846# define lua_str2number(s, p) strtod((s), (p))
847#endif
848
849COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s) {
850 char* endptr;
851 lua_Number n = lua_str2number(s, &endptr);
852 if (endptr != s) {
853 while (*endptr != '\0' && isspace((unsigned char)*endptr))
854 ++endptr;
855 if (*endptr == '\0') {
856 lua_pushnumber(L, n);
857 return endptr - s + 1;
858 }
859 }
860 return 0;
861}
862
863
864COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
865 if (!luaL_callmeta(L, idx, "__tostring")) {
866 int t = lua_type(L, idx), tt = 0;
867 char const* name = NULL;
868 switch (t) {
869 case LUA_TNIL:
870 lua_pushliteral(L, "nil");
871 break;
872 case LUA_TSTRING:
873 case LUA_TNUMBER:
874 lua_pushvalue(L, idx);
875 break;
876 case LUA_TBOOLEAN:
877 if (lua_toboolean(L, idx))
878 lua_pushliteral(L, "true");
879 else
880 lua_pushliteral(L, "false");
881 break;
882 default:
883 tt = luaL_getmetafield(L, idx, "__name");
884 name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t);
885 lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx));
886 if (tt != LUA_TNIL)
887 lua_replace(L, -2);
888 break;
889 }
890 } else {
891 if (!lua_isstring(L, -1))
892 luaL_error(L, "'__tostring' must return a string");
893 }
894 return lua_tolstring(L, -1, len);
895}
896
897
898COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
899 lua_CFunction openf, int glb) {
900 luaL_checkstack(L, 3, "not enough stack slots available");
901 luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
902 if (lua_getfield(L, -1, modname) == LUA_TNIL) {
903 lua_pop(L, 1);
904 lua_pushcfunction(L, openf);
905 lua_pushstring(L, modname);
906 lua_call(L, 1, 1);
907 lua_pushvalue(L, -1);
908 lua_setfield(L, -3, modname);
909 }
910 if (glb) {
911 lua_pushvalue(L, -1);
912 lua_setglobal(L, modname);
913 }
914 lua_replace(L, -2);
915}
916
917
918#endif /* Lua 5.1 and 5.2 */
919
920
921#endif /* COMPAT53_C_ */
922
923
924/*********************************************************************
925* This file contains parts of Lua 5.2's and Lua 5.3's source code:
926*
927* Copyright (C) 1994-2014 Lua.org, PUC-Rio.
928*
929* Permission is hereby granted, free of charge, to any person obtaining
930* a copy of this software and associated documentation files (the
931* "Software"), to deal in the Software without restriction, including
932* without limitation the rights to use, copy, modify, merge, publish,
933* distribute, sublicense, and/or sell copies of the Software, and to
934* permit persons to whom the Software is furnished to do so, subject to
935* the following conditions:
936*
937* The above copyright notice and this permission notice shall be
938* included in all copies or substantial portions of the Software.
939*
940* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
941* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
942* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
943* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
944* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
945* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
946* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
947*********************************************************************/
948
diff --git a/vendor/lua-bz2/compat-5.3.h b/vendor/lua-bz2/compat-5.3.h
new file mode 100644
index 00000000..b730a4b8
--- /dev/null
+++ b/vendor/lua-bz2/compat-5.3.h
@@ -0,0 +1,424 @@
1#ifndef COMPAT53_H_
2#define COMPAT53_H_
3
4#include <stddef.h>
5#include <limits.h>
6#include <string.h>
7#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
8extern "C" {
9#endif
10#include <lua.h>
11#include <lauxlib.h>
12#include <lualib.h>
13#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
14}
15#endif
16
17
18#undef COMPAT53_INCLUDE_SOURCE
19#if defined(COMPAT53_PREFIX)
20/* - change the symbol names of functions to avoid linker conflicts
21 * - compat-5.3.c needs to be compiled (and linked) separately
22 */
23# if !defined(COMPAT53_API)
24# define COMPAT53_API extern
25# endif
26#else /* COMPAT53_PREFIX */
27/* - make all functions static and include the source.
28 * - compat-5.3.c doesn't need to be compiled (and linked) separately
29 */
30# define COMPAT53_PREFIX compat53
31# undef COMPAT53_API
32# if defined(__GNUC__) || defined(__clang__)
33# define COMPAT53_API __attribute__((__unused__)) static
34# else
35# define COMPAT53_API static
36# endif
37# define COMPAT53_INCLUDE_SOURCE
38#endif /* COMPAT53_PREFIX */
39
40#define COMPAT53_CONCAT_HELPER(a, b) a##b
41#define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b)
42
43
44
45/* declarations for Lua 5.1 */
46#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
47
48/* XXX not implemented:
49 * lua_arith (new operators)
50 * lua_upvalueid
51 * lua_upvaluejoin
52 * lua_version
53 * lua_yieldk
54 */
55
56#ifndef LUA_OK
57# define LUA_OK 0
58#endif
59#ifndef LUA_OPADD
60# define LUA_OPADD 0
61#endif
62#ifndef LUA_OPSUB
63# define LUA_OPSUB 1
64#endif
65#ifndef LUA_OPMUL
66# define LUA_OPMUL 2
67#endif
68#ifndef LUA_OPDIV
69# define LUA_OPDIV 3
70#endif
71#ifndef LUA_OPMOD
72# define LUA_OPMOD 4
73#endif
74#ifndef LUA_OPPOW
75# define LUA_OPPOW 5
76#endif
77#ifndef LUA_OPUNM
78# define LUA_OPUNM 6
79#endif
80#ifndef LUA_OPEQ
81# define LUA_OPEQ 0
82#endif
83#ifndef LUA_OPLT
84# define LUA_OPLT 1
85#endif
86#ifndef LUA_OPLE
87# define LUA_OPLE 2
88#endif
89
90/* LuaJIT/Lua 5.1 does not have the updated
91 * error codes for thread status/function returns (but some patched versions do)
92 * define it only if it's not found
93 */
94#if !defined(LUA_ERRGCMM)
95/* Use + 2 because in some versions of Lua (Lua 5.1)
96 * LUA_ERRFILE is defined as (LUA_ERRERR+1)
97 * so we need to avoid it (LuaJIT might have something at this
98 * integer value too)
99 */
100# define LUA_ERRGCMM (LUA_ERRERR + 2)
101#endif /* LUA_ERRGCMM define */
102
103typedef size_t lua_Unsigned;
104
105typedef struct luaL_Buffer_53 {
106 luaL_Buffer b; /* make incorrect code crash! */
107 char *ptr;
108 size_t nelems;
109 size_t capacity;
110 lua_State *L2;
111} luaL_Buffer_53;
112#define luaL_Buffer luaL_Buffer_53
113
114/* In PUC-Rio 5.1, userdata is a simple FILE*
115 * In LuaJIT, it's a struct where the first member is a FILE*
116 * We can't support the `closef` member
117 */
118typedef struct luaL_Stream {
119 FILE *f;
120} luaL_Stream;
121
122#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
123COMPAT53_API int lua_absindex (lua_State *L, int i);
124
125#define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith)
126COMPAT53_API void lua_arith (lua_State *L, int op);
127
128#define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare)
129COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op);
130
131#define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy)
132COMPAT53_API void lua_copy (lua_State *L, int from, int to);
133
134#define lua_getuservalue(L, i) \
135 (lua_getfenv((L), (i)), lua_type((L), -1))
136#define lua_setuservalue(L, i) \
137 (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i)))
138
139#define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len)
140COMPAT53_API void lua_len (lua_State *L, int i);
141
142#define lua_pushstring(L, s) \
143 (lua_pushstring((L), (s)), lua_tostring((L), -1))
144
145#define lua_pushlstring(L, s, len) \
146 ((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1))
147
148#ifndef luaL_newlibtable
149# define luaL_newlibtable(L, l) \
150 (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1))
151#endif
152#ifndef luaL_newlib
153# define luaL_newlib(L, l) \
154 (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l)))
155#endif
156
157#define lua_pushglobaltable(L) \
158 lua_pushvalue((L), LUA_GLOBALSINDEX)
159
160#define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp)
161COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p);
162
163#define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp)
164COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p);
165
166#define lua_rawlen(L, i) lua_objlen((L), (i))
167
168#define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL)
169
170#define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx)
171COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum);
172
173#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
174COMPAT53_API void luaL_checkversion (lua_State *L);
175
176#define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53)
177COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode);
178
179#define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex)
180COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode);
181
182#define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx)
183COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode);
184
185#define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53)
186COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg);
187
188#define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable)
189COMPAT53_API int luaL_getsubtable (lua_State* L, int i, const char *name);
190
191#define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len)
192COMPAT53_API lua_Integer luaL_len (lua_State *L, int i);
193
194#define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs)
195COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
196
197#define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable)
198COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname);
199
200#define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata)
201COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname);
202
203#define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback)
204COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level);
205
206#define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult)
207COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname);
208
209#define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult)
210COMPAT53_API int luaL_execresult (lua_State *L, int stat);
211
212#define lua_callk(L, na, nr, ctx, cont) \
213 ((void)(ctx), (void)(cont), lua_call((L), (na), (nr)))
214#define lua_pcallk(L, na, nr, err, ctx, cont) \
215 ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err)))
216
217#define lua_resume(L, from, nargs) \
218 ((void)(from), lua_resume((L), (nargs)))
219
220#define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53)
221COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B);
222
223#define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53)
224COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s);
225
226#define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53)
227COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l);
228
229#define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53)
230COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B);
231
232#define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53)
233COMPAT53_API void luaL_pushresult (luaL_Buffer_53 *B);
234
235#undef luaL_buffinitsize
236#define luaL_buffinitsize(L, B, s) \
237 (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s)))
238
239#undef luaL_prepbuffer
240#define luaL_prepbuffer(B) \
241 luaL_prepbuffsize((B), LUAL_BUFFERSIZE)
242
243#undef luaL_addchar
244#define luaL_addchar(B, c) \
245 ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \
246 ((B)->ptr[(B)->nelems++] = (c)))
247
248#undef luaL_addsize
249#define luaL_addsize(B, s) \
250 ((B)->nelems += (s))
251
252#undef luaL_addstring
253#define luaL_addstring(B, s) \
254 luaL_addlstring((B), (s), strlen((s)))
255
256#undef luaL_pushresultsize
257#define luaL_pushresultsize(B, s) \
258 (luaL_addsize((B), (s)), luaL_pushresult((B)))
259
260#if defined(LUA_COMPAT_APIINTCASTS)
261#define lua_pushunsigned(L, n) \
262 lua_pushinteger((L), (lua_Integer)(n))
263#define lua_tounsignedx(L, i, is) \
264 ((lua_Unsigned)lua_tointegerx((L), (i), (is)))
265#define lua_tounsigned(L, i) \
266 lua_tounsignedx((L), (i), NULL)
267#define luaL_checkunsigned(L, a) \
268 ((lua_Unsigned)luaL_checkinteger((L), (a)))
269#define luaL_optunsigned(L, a, d) \
270 ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d)))
271#endif
272
273#endif /* Lua 5.1 only */
274
275
276
277/* declarations for Lua 5.1 and 5.2 */
278#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502
279
280typedef int lua_KContext;
281
282typedef int (*lua_KFunction)(lua_State *L, int status, lua_KContext ctx);
283
284#define lua_dump(L, w, d, s) \
285 ((void)(s), lua_dump((L), (w), (d)))
286
287#define lua_getfield(L, i, k) \
288 (lua_getfield((L), (i), (k)), lua_type((L), -1))
289
290#define lua_gettable(L, i) \
291 (lua_gettable((L), (i)), lua_type((L), -1))
292
293#define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti)
294COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i);
295
296#define lua_getextraspace COMPAT53_CONCAT(COMPAT53_PREFIX, _getextraspace)
297COMPAT53_API void *lua_getextraspace (lua_State *L);
298
299#define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger)
300COMPAT53_API int lua_isinteger (lua_State *L, int index);
301
302#define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53)
303COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum);
304
305#define lua_numbertointeger(n, p) \
306 ((*(p) = (lua_Integer)(n)), 1)
307
308#define lua_rawget(L, i) \
309 (lua_rawget((L), (i)), lua_type((L), -1))
310
311#define lua_rawgeti(L, i, n) \
312 (lua_rawgeti((L), (i), (n)), lua_type((L), -1))
313
314#define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate)
315COMPAT53_API void lua_rotate (lua_State *L, int idx, int n);
316
317#define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti)
318COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i);
319
320#define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber)
321COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s);
322
323#define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring)
324COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len);
325
326#define luaL_getmetafield(L, o, e) \
327 (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL)
328
329#define luaL_newmetatable(L, tn) \
330 (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0)
331
332#define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53)
333COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
334 lua_CFunction openf, int glb );
335
336#endif /* Lua 5.1 and Lua 5.2 */
337
338
339
340/* declarations for Lua 5.2 */
341#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502
342
343/* XXX not implemented:
344 * lua_isyieldable
345 * lua_arith (new operators)
346 * lua_pushfstring (new formats)
347 */
348
349#define lua_getglobal(L, n) \
350 (lua_getglobal((L), (n)), lua_type((L), -1))
351
352#define lua_getuservalue(L, i) \
353 (lua_getuservalue((L), (i)), lua_type((L), -1))
354
355#define lua_pushlstring(L, s, len) \
356 (((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len)))
357
358#define lua_rawgetp(L, i, p) \
359 (lua_rawgetp((L), (i), (p)), lua_type((L), -1))
360
361#define LUA_KFUNCTION(_name) \
362 static int (_name)(lua_State *L, int status, lua_KContext ctx); \
363 static int (_name ## _52)(lua_State *L) { \
364 lua_KContext ctx; \
365 int status = lua_getctx(L, &ctx); \
366 return (_name)(L, status, ctx); \
367 } \
368 static int (_name)(lua_State *L, int status, lua_KContext ctx)
369
370#define lua_pcallk(L, na, nr, err, ctx, cont) \
371 lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52)
372
373#define lua_callk(L, na, nr, ctx, cont) \
374 lua_callk((L), (na), (nr), (ctx), cont ## _52)
375
376#define lua_yieldk(L, nr, ctx, cont) \
377 lua_yieldk((L), (nr), (ctx), cont ## _52)
378
379#ifdef lua_call
380# undef lua_call
381# define lua_call(L, na, nr) \
382 (lua_callk)((L), (na), (nr), 0, NULL)
383#endif
384
385#ifdef lua_pcall
386# undef lua_pcall
387# define lua_pcall(L, na, nr, err) \
388 (lua_pcallk)((L), (na), (nr), (err), 0, NULL)
389#endif
390
391#ifdef lua_yield
392# undef lua_yield
393# define lua_yield(L, nr) \
394 (lua_yieldk)((L), (nr), 0, NULL)
395#endif
396
397#endif /* Lua 5.2 only */
398
399
400
401/* other Lua versions */
402#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 504
403
404# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, 5.3, or 5.4)"
405
406#endif /* other Lua versions except 5.1, 5.2, 5.3, and 5.4 */
407
408
409
410/* helper macro for defining continuation functions (for every version
411 * *except* Lua 5.2) */
412#ifndef LUA_KFUNCTION
413#define LUA_KFUNCTION(_name) \
414 static int (_name)(lua_State *L, int status, lua_KContext ctx)
415#endif
416
417
418#if defined(COMPAT53_INCLUDE_SOURCE)
419# include "compat-5.3.c"
420#endif
421
422
423#endif /* COMPAT53_H_ */
424
diff --git a/vendor/lua-bz2/lbz.c b/vendor/lua-bz2/lbz.c
new file mode 100644
index 00000000..6e0d66e2
--- /dev/null
+++ b/vendor/lua-bz2/lbz.c
@@ -0,0 +1,52 @@
1/* This file implements the Lua binding to libbzip2.
2 *
3 * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org>
4 * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <lua.h>
20#include <lauxlib.h>
21
22/* This explicit define prevents compat-5.3.h from loading compat-5.3.c */
23#define COMPAT53_PREFIX compat53
24#include "compat-5.3.h"
25
26#include "lbz2_file_reader.h"
27#include "lbz2_file_writer.h"
28#include "lbz2_stream.h"
29
30static luaL_Reg lbz2_global[] = {
31 { NULL, NULL }
32};
33
34int luaopen_bz2(lua_State *L) {
35 luaL_newlib(L, lbz2_global);
36
37 lua_pushliteral(L, "bz2");
38 lua_setfield(L, -2, "_NAME");
39 lua_pushliteral(L, "0.1");
40 lua_setfield(L, -2, "_VERSION");
41
42 register_lbz2_file_reader(L);
43 register_lbz2_file_writer(L);
44 register_lbz2_stream(L);
45
46#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
47 lua_pushvalue(L, -1);
48 lua_setglobal(L, "bz2");
49#endif
50
51 return 1;
52}
diff --git a/vendor/lua-bz2/lbz2_common.c b/vendor/lua-bz2/lbz2_common.c
new file mode 100644
index 00000000..2aa76cfb
--- /dev/null
+++ b/vendor/lua-bz2/lbz2_common.c
@@ -0,0 +1,57 @@
1/* This file implements the Lua binding to libbzip2.
2 *
3 * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org>
4 * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19
20#include "lbz2_common.h"
21#include <bzlib.h>
22
23
24const char *lbz2_error(int bzerror) {
25 switch (bzerror) {
26 case BZ_OK:
27 return "OK";
28 case BZ_RUN_OK:
29 return "RUN_OK";
30 case BZ_FLUSH_OK:
31 return "FLUSH_OK";
32 case BZ_FINISH_OK:
33 return "FINISH_OK";
34 case BZ_STREAM_END:
35 return "STREAM_END";
36 case BZ_SEQUENCE_ERROR:
37 return "SEQUENCE_ERROR";
38 case BZ_PARAM_ERROR:
39 return "PARAM_ERROR";
40 case BZ_MEM_ERROR:
41 return "MEM_ERROR";
42 case BZ_DATA_ERROR:
43 return "DATA_ERROR";
44 case BZ_DATA_ERROR_MAGIC:
45 return "DATA_ERROR_MAGIC";
46 case BZ_IO_ERROR:
47 return "IO_ERROR";
48 case BZ_UNEXPECTED_EOF:
49 return "UNEXPECTED_EOF";
50 case BZ_OUTBUFF_FULL:
51 return "OUTBUFF_FULL";
52 case BZ_CONFIG_ERROR:
53 return "CONFIG_ERROR";
54 default:
55 return "UNKNOWN";
56 }
57}
diff --git a/vendor/lua-bz2/lbz2_common.h b/vendor/lua-bz2/lbz2_common.h
new file mode 100644
index 00000000..98e534bf
--- /dev/null
+++ b/vendor/lua-bz2/lbz2_common.h
@@ -0,0 +1,25 @@
1/* This file implements the Lua binding to libbzip2.
2 *
3 * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org>
4 * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19
20#ifndef LBZ2_COMMON_H
21#define LBZ2_COMMON_H
22
23const char *lbz2_error(int bzerror);
24
25#endif
diff --git a/vendor/lua-bz2/lbz2_file_reader.c b/vendor/lua-bz2/lbz2_file_reader.c
new file mode 100644
index 00000000..c101a1ee
--- /dev/null
+++ b/vendor/lua-bz2/lbz2_file_reader.c
@@ -0,0 +1,164 @@
1/* This file implements the Lua binding to libbzip2.
2 *
3 * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org>
4 * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <bzlib.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <lua.h>
24#include <lauxlib.h>
25
26/* This explicit define prevents compat-5.3.h from loading compat-5.3.c */
27#define COMPAT53_PREFIX compat53
28#include "compat-5.3.h"
29
30#include "lbz2_file_reader.h"
31#include "lbz2_common.h"
32
33#define LBZ2_FILE_READER_MT "LBZ2_FILE_READER_MT"
34
35typedef struct {
36 BZFILE *bz_stream;
37 FILE *f;
38} lbz2_file_reader;
39
40static lbz2_file_reader *lbz2_check_file_reader(lua_State *L, int index) {
41 return (lbz2_file_reader *)luaL_checkudata(L, index, LBZ2_FILE_READER_MT);
42}
43
44static int lbz2_file_reader_open(lua_State *L) {
45 lbz2_file_reader *reader;
46 int errorCode;
47 const char *fname = luaL_checkstring(L, 1);
48 int verbosity = luaL_optinteger(L, 3, 0);
49 int small = lua_toboolean(L, 4);
50
51 reader = lua_newuserdata(L, sizeof(*reader));
52 memset(reader, 0, sizeof(*reader));
53
54 luaL_getmetatable(L, LBZ2_FILE_READER_MT);
55 lua_setmetatable(L, -2);
56
57 reader->f = fopen(fname, "rb");
58
59 if (reader->f == NULL) {
60 return luaL_error(L, "Failed to fopen %s", fname);
61 }
62 reader->bz_stream = BZ2_bzReadOpen(&errorCode, reader->f, verbosity, small, NULL, 0);
63
64 if (BZ_OK != errorCode) {
65 fclose(reader->f);
66 reader->f = NULL;
67 lua_pushnil(L);
68 lua_pushstring(L, lbz2_error(errorCode));
69 return 2;
70 }
71 return 1;
72}
73
74static int lbz2_file_reader_close(lua_State *L) {
75 lbz2_file_reader *reader = lbz2_check_file_reader(L, 1);
76 int errorCode = BZ_OK;
77
78 if (reader->bz_stream) {
79 BZ2_bzReadClose(&errorCode, reader->bz_stream);
80 reader->bz_stream = NULL;
81 }
82 if (reader->f) {
83 fclose(reader->f);
84 reader->f = NULL;
85 }
86
87 lua_pushnil(L);
88 lua_setmetatable(L, 1);
89
90 if (BZ_OK != errorCode) {
91 lua_pushnil(L);
92 lua_pushstring(L, lbz2_error(errorCode));
93 return 2;
94 }
95 lua_pushboolean(L, 1);
96 return 1;
97}
98
99static int lbz2_file_reader_read(lua_State *L) {
100 lbz2_file_reader *reader = lbz2_check_file_reader(L, 1);
101 int errorCode = BZ_OK;
102 int dataLength;
103 luaL_Buffer B;
104 /* If passed a boolean, read a single *chunk* */
105 if (lua_isboolean(L, 2)) {
106 dataLength = LUAL_BUFFERSIZE;
107 } else {
108 dataLength = luaL_optinteger(L, 2, -1);
109 }
110
111 luaL_buffinit(L, &B);
112
113 /* Pull in chunks until all data read */
114 while(dataLength > 0 || dataLength == -1) {
115 char *buf = luaL_prepbuffer(&B);
116 int nextRead = (dataLength == -1 || dataLength > LUAL_BUFFERSIZE) ? LUAL_BUFFERSIZE : dataLength;
117 int read = BZ2_bzRead(&errorCode, reader->bz_stream, buf, nextRead);
118 if (read > 0) {
119 luaL_addsize(&B, read);
120 dataLength -= read;
121 }
122 if (BZ_OK != errorCode) {
123 goto handle_error;
124 }
125 }
126 luaL_pushresult(&B);
127 return 1;
128handle_error:
129 if(BZ_STREAM_END == errorCode) {
130 luaL_pushresult(&B);
131 lua_pushboolean(L, 1);
132 return 2;
133 } else {
134 lua_pushnil(L);
135 lua_pushstring(L, lbz2_error(errorCode));
136 return 2;
137 }
138}
139
140static luaL_Reg lbz2_file_reader_ops[] = {
141 { "read", lbz2_file_reader_read },
142 { "close", lbz2_file_reader_close },
143 { NULL, NULL }
144};
145
146static luaL_Reg lbz2_file_reader_global[] = {
147 { "openRead", lbz2_file_reader_open },
148 { NULL, NULL }
149};
150
151
152
153void register_lbz2_file_reader(lua_State *L) {
154 luaL_newmetatable(L, LBZ2_FILE_READER_MT);
155 lua_newtable(L);
156 luaL_setfuncs(L, lbz2_file_reader_ops, 0);
157 lua_setfield(L, -2, "__index");
158
159 lua_pushcfunction(L, lbz2_file_reader_close);
160 lua_setfield(L, -2, "__gc");
161 lua_pop(L, 1);
162
163 luaL_setfuncs(L, lbz2_file_reader_global, 0);
164}
diff --git a/vendor/lua-bz2/lbz2_file_reader.h b/vendor/lua-bz2/lbz2_file_reader.h
new file mode 100644
index 00000000..a183329d
--- /dev/null
+++ b/vendor/lua-bz2/lbz2_file_reader.h
@@ -0,0 +1,25 @@
1/* This file implements the Lua binding to libbzip2.
2 *
3 * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org>
4 * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19
20#ifndef LBZ2_FILE_READER_H
21#define LBZ2_FILE_READER_H
22
23void register_lbz2_file_reader(lua_State *L);
24
25#endif
diff --git a/vendor/lua-bz2/lbz2_file_writer.c b/vendor/lua-bz2/lbz2_file_writer.c
new file mode 100644
index 00000000..f35beca3
--- /dev/null
+++ b/vendor/lua-bz2/lbz2_file_writer.c
@@ -0,0 +1,141 @@
1/* This file implements the Lua binding to libbzip2.
2 *
3 * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org>
4 * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <bzlib.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <lua.h>
24#include <lauxlib.h>
25
26#include <assert.h>
27
28/* This explicit define prevents compat-5.3.h from loading compat-5.3.c */
29#define COMPAT53_PREFIX compat53
30#include "compat-5.3.h"
31
32#include "lbz2_file_writer.h"
33#include "lbz2_common.h"
34
35#define LBZ2_FILE_WRITER_MT "LBZ2_FILE_WRITER_MT"
36
37typedef struct {
38 BZFILE *bz_stream;
39 FILE *f;
40} lbz2_file_writer;
41
42static lbz2_file_writer *lbz2_check_file_writer(lua_State *L, int index) {
43 return (lbz2_file_writer *)luaL_checkudata(L, index, LBZ2_FILE_WRITER_MT);
44}
45
46static int lbz2_file_writer_open(lua_State *L) {
47 lbz2_file_writer *writer;
48 int errorCode;
49 const char *fname = luaL_checkstring(L, 1);
50 int blockSize100k = luaL_optinteger(L, 2, 9);
51 int verbosity = luaL_optinteger(L, 3, 0);
52 int workFactor = luaL_optinteger(L, 4, 0);
53
54 writer = lua_newuserdata(L, sizeof(*writer));
55 memset(writer, 0, sizeof(*writer));
56
57 luaL_getmetatable(L, LBZ2_FILE_WRITER_MT);
58 lua_setmetatable(L, -2);
59
60 writer->f = fopen(fname, "wb");
61
62 if (writer->f == NULL) {
63 return luaL_error(L, "Failed to fopen %s", fname);
64 }
65 writer->bz_stream = BZ2_bzWriteOpen(&errorCode, writer->f, blockSize100k, verbosity, workFactor);
66
67 if (BZ_OK != errorCode) {
68 fclose(writer->f);
69 writer->f = NULL;
70 lua_pushnil(L);
71 lua_pushstring(L, lbz2_error(errorCode));
72 return 2;
73 }
74 return 1;
75}
76
77static int lbz2_file_writer_close(lua_State *L) {
78 lbz2_file_writer *writer = lbz2_check_file_writer(L, 1);
79 int errorCode = BZ_OK;
80
81 if (writer->bz_stream) {
82 BZ2_bzWriteClose(&errorCode, writer->bz_stream, 0, NULL, NULL);
83 writer->bz_stream = NULL;
84 }
85 if (writer->f) {
86 fclose(writer->f);
87 writer->f = NULL;
88 }
89
90 lua_pushnil(L);
91 lua_setmetatable(L, 1);
92
93 if (BZ_OK != errorCode) {
94 lua_pushnil(L);
95 lua_pushstring(L, lbz2_error(errorCode));
96 return 2;
97 }
98 lua_pushboolean(L, 1);
99 return 1;
100}
101
102static int lbz2_file_writer_write(lua_State *L) {
103 lbz2_file_writer *writer = lbz2_check_file_writer(L, 1);
104 int errorCode = BZ_OK;
105 size_t dataLength;
106 const char *data = luaL_checklstring(L, 2, &dataLength);
107
108 BZ2_bzWrite(&errorCode, writer->bz_stream, (void *)data, dataLength);
109
110 if (BZ_OK != errorCode) {
111 lua_pushnil(L);
112 lua_pushstring(L, lbz2_error(errorCode));
113 return 2;
114 }
115 lua_pushboolean(L, 1);
116 return 1;
117}
118
119static luaL_Reg lbz2_file_writer_ops[] = {
120 { "write", lbz2_file_writer_write },
121 { "close", lbz2_file_writer_close },
122 { NULL, NULL }
123};
124
125static luaL_Reg lbz2_file_writer_global[] = {
126 { "openWrite", lbz2_file_writer_open },
127 { NULL, NULL }
128};
129
130void register_lbz2_file_writer(lua_State *L) {
131 luaL_newmetatable(L, LBZ2_FILE_WRITER_MT);
132 lua_newtable(L);
133 luaL_setfuncs(L, lbz2_file_writer_ops, 0);
134 lua_setfield(L, -2, "__index");
135
136 lua_pushcfunction(L, lbz2_file_writer_close);
137 lua_setfield(L, -2, "__gc");
138 lua_pop(L, 1);
139
140 luaL_setfuncs(L, lbz2_file_writer_global, 0);
141}
diff --git a/vendor/lua-bz2/lbz2_file_writer.h b/vendor/lua-bz2/lbz2_file_writer.h
new file mode 100644
index 00000000..4f2e5e09
--- /dev/null
+++ b/vendor/lua-bz2/lbz2_file_writer.h
@@ -0,0 +1,25 @@
1/* This file implements the Lua binding to libbzip2.
2 *
3 * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org>
4 * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19
20#ifndef LBZ2_FILE_WRITER_H
21#define LBZ2_FILE_WRITER_H
22
23void register_lbz2_file_writer(lua_State *L);
24
25#endif
diff --git a/vendor/lua-bz2/lbz2_stream.c b/vendor/lua-bz2/lbz2_stream.c
new file mode 100644
index 00000000..9eb2ab2b
--- /dev/null
+++ b/vendor/lua-bz2/lbz2_stream.c
@@ -0,0 +1,263 @@
1/* This file implements the Lua binding to libbzip2.
2 *
3 * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org>
4 * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <bzlib.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <lua.h>
24#include <lauxlib.h>
25
26#include <assert.h>
27
28/* This explicit define prevents compat-5.3.h from loading compat-5.3.c */
29#define COMPAT53_PREFIX compat53
30#include "compat-5.3.h"
31
32#include "lbz2_stream.h"
33#include "lbz2_common.h"
34
35#define LBZ2_STREAM_MT "LBZ2_STREAM_MT"
36
37typedef struct {
38 bz_stream bz_stream;
39 int isDecompressing;
40} lbz2_stream;
41
42static lbz2_stream *lbz2_check_stream(lua_State *L, int index) {
43 return (lbz2_stream *)luaL_checkudata(L, index, LBZ2_STREAM_MT);
44}
45
46static int lbz2_stream_initCompress(lua_State *L) {
47 lbz2_stream *stream;
48 int errorCode;
49 int blockSize100k = luaL_optinteger(L, 1, 9);
50 int verbosity = luaL_optinteger(L, 2, 0);
51 int workFactor = luaL_optinteger(L, 3, 0);
52
53 stream = lua_newuserdata(L, sizeof(*stream));
54 memset(stream, 0, sizeof(*stream));
55
56 stream->isDecompressing = 0;
57
58 luaL_getmetatable(L, LBZ2_STREAM_MT);
59 lua_setmetatable(L, -2);
60
61 errorCode = BZ2_bzCompressInit(&stream->bz_stream, blockSize100k, verbosity, workFactor);
62
63 if (BZ_OK != errorCode) {
64 lua_pushnil(L);
65 lua_pushstring(L, lbz2_error(errorCode));
66 return 2;
67 }
68 return 1;
69}
70
71static int lbz2_stream_initDecompress(lua_State *L) {
72 lbz2_stream *stream;
73 int errorCode;
74 int verbosity = luaL_optinteger(L, 1, 0);
75 int isSmall = lua_toboolean(L, 2);
76
77 stream = lua_newuserdata(L, sizeof(*stream));
78 memset(stream, 0, sizeof(*stream));
79
80 stream->isDecompressing = 1;
81
82 luaL_getmetatable(L, LBZ2_STREAM_MT);
83 lua_setmetatable(L, -2);
84
85 errorCode = BZ2_bzDecompressInit(&stream->bz_stream, verbosity, isSmall);
86
87 if (BZ_OK != errorCode) {
88 lua_pushnil(L);
89 lua_pushstring(L, lbz2_error(errorCode));
90 return 2;
91 }
92 return 1;
93}
94static int lbz2_stream_close(lua_State *L) {
95 lbz2_stream *stream = lbz2_check_stream(L, 1);
96 int errorCode = BZ_OK;
97
98 if (stream->bz_stream.state) {
99 if (stream->isDecompressing) {
100 errorCode = BZ2_bzDecompressEnd(&stream->bz_stream);
101 } else {
102 errorCode = BZ2_bzCompressEnd(&stream->bz_stream);
103 }
104 }
105
106 lua_pushnil(L);
107 lua_setmetatable(L, 1);
108
109 if (BZ_OK != errorCode) {
110 lua_pushnil(L);
111 lua_pushstring(L, lbz2_error(errorCode));
112 return 2;
113 }
114 lua_pushboolean(L, 1);
115 return 1;
116}
117
118static int lbz2_stream_perform_compress(lua_State *L, lbz2_stream *stream, int action) {
119 int errorCode = BZ_OK;
120 luaL_Buffer B;
121
122 luaL_buffinit(L, &B);
123
124 while (1) {
125 stream->bz_stream.avail_out = LUAL_BUFFERSIZE;
126 stream->bz_stream.next_out = luaL_prepbuffer(&B);
127 errorCode = BZ2_bzCompress(&stream->bz_stream, action);
128
129 switch (action) {
130 case BZ_RUN:
131 if (BZ_RUN_OK != errorCode) {
132 goto fail;
133 }
134 luaL_addsize(&B, LUAL_BUFFERSIZE - stream->bz_stream.avail_out);
135 if (stream->bz_stream.avail_in == 0 || stream->bz_stream.avail_out == LUAL_BUFFERSIZE) {
136 goto complete;
137 }
138 break;
139 case BZ_FLUSH:
140 if (BZ_FLUSH_OK != errorCode && BZ_RUN_OK != errorCode) {
141 goto fail;
142 }
143 luaL_addsize(&B, LUAL_BUFFERSIZE - stream->bz_stream.avail_out);
144 if (BZ_RUN_OK == errorCode) {
145 goto complete;
146 }
147 break;
148 case BZ_FINISH:
149 if (BZ_FINISH_OK != errorCode && BZ_STREAM_END != errorCode) {
150 goto fail;
151 }
152 luaL_addsize(&B, LUAL_BUFFERSIZE - stream->bz_stream.avail_out);
153 if (BZ_STREAM_END == errorCode) {
154 goto complete;
155 }
156 }
157 }
158complete:
159 luaL_pushresult(&B);
160 return 1;
161
162fail:
163 lua_pushnil(L);
164 lua_pushstring(L, lbz2_error(errorCode));
165 return 2;
166}
167
168static int lbz2_stream_perform_decompress(lua_State *L, lbz2_stream *stream) {
169 int errorCode = BZ_OK;
170 luaL_Buffer B;
171
172 luaL_buffinit(L, &B);
173
174 while (1) {
175 stream->bz_stream.avail_out = LUAL_BUFFERSIZE;
176 stream->bz_stream.next_out = luaL_prepbuffer(&B);
177 errorCode = BZ2_bzDecompress(&stream->bz_stream);
178
179 if (BZ_OK != errorCode && BZ_STREAM_END != errorCode) {
180 goto fail;
181 }
182 luaL_addsize(&B, LUAL_BUFFERSIZE - stream->bz_stream.avail_out);
183 /* Stream over with */
184 if (errorCode == BZ_STREAM_END) {
185 goto completeStream;
186 }
187 /* No more bytes left this round */
188 if (stream->bz_stream.avail_in == 0 && stream->bz_stream.avail_out == LUAL_BUFFERSIZE) {
189 goto complete;
190 }
191 }
192complete:
193 luaL_pushresult(&B);
194 return 1;
195
196completeStream:
197 luaL_pushresult(&B);
198 /* Report in addition to the data collected, the number of trailing bytes
199 * still available in the input buffer for other use. */
200 lua_pushinteger(L, stream->bz_stream.avail_in);
201 return 2;
202
203fail:
204 lua_pushnil(L);
205 lua_pushstring(L, lbz2_error(errorCode));
206 return 2;
207}
208static int lbz2_stream_update(lua_State *L) {
209 lbz2_stream *stream = lbz2_check_stream(L, 1);
210 size_t dataLength;
211 const char *data = luaL_optlstring(L, 2, NULL, &dataLength);
212
213 /* Update the pointers and feed the output buffer while data is available */
214 stream->bz_stream.avail_in = dataLength;
215 /* Cast away const-ness since input data is never altered */
216 stream->bz_stream.next_in = (char *)data;
217
218 /* For compression, need to specially flag finishing state */
219 if (!stream->isDecompressing) {
220 return lbz2_stream_perform_compress(L, stream, !data ? BZ_FINISH : BZ_RUN);
221 } else {
222 return lbz2_stream_perform_decompress(L, stream);
223 }
224}
225
226static int lbz2_stream_flush(lua_State *L) {
227 lbz2_stream *stream = lbz2_check_stream(L, 1);
228 if (!stream->isDecompressing) {
229 return lbz2_stream_perform_compress(L, stream, BZ_FLUSH);
230 } else {
231 /* Invalid for decompression */
232 lua_pushnil(L);
233 lua_pushstring(L, lbz2_error(BZ_SEQUENCE_ERROR));
234 return 2;
235 }
236}
237
238static luaL_Reg lbz2_stream_ops[] = {
239 { "update", lbz2_stream_update },
240 { "flush", lbz2_stream_flush },
241 { "close", lbz2_stream_close },
242 { NULL, NULL }
243};
244
245static luaL_Reg lbz2_stream_global[] = {
246 { "initCompress", lbz2_stream_initCompress },
247 { "initDecompress", lbz2_stream_initDecompress },
248 { NULL, NULL }
249};
250
251void register_lbz2_stream(lua_State *L) {
252 luaL_newmetatable(L, LBZ2_STREAM_MT);
253 lua_newtable(L);
254 luaL_setfuncs(L, lbz2_stream_ops, 0);
255 lua_setfield(L, -2, "__index");
256
257 lua_pushcfunction(L, lbz2_stream_close);
258 lua_setfield(L, -2, "__gc");
259 lua_pop(L, 1);
260
261 luaL_setfuncs(L, lbz2_stream_global, 0);
262}
263
diff --git a/vendor/lua-bz2/lbz2_stream.h b/vendor/lua-bz2/lbz2_stream.h
new file mode 100644
index 00000000..a321ea59
--- /dev/null
+++ b/vendor/lua-bz2/lbz2_stream.h
@@ -0,0 +1,25 @@
1/* This file implements the Lua binding to libbzip2.
2 *
3 * Copyright (c) 2008, Evan Klitzke <evan@eklitzke.org>
4 * Copyright (c) 2012, Thomas Harning Jr <harningt@gmail.com>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19
20#ifndef LBZ2_STREAM_H
21#define LBZ2_STREAM_H
22
23void register_lbz2_stream(lua_State *L);
24
25#endif
diff --git a/vendor/lua-bz2/lua-bz2-0.2.1-1.rockspec b/vendor/lua-bz2/lua-bz2-0.2.1-1.rockspec
new file mode 100644
index 00000000..c66770f6
--- /dev/null
+++ b/vendor/lua-bz2/lua-bz2-0.2.1-1.rockspec
@@ -0,0 +1,48 @@
1package = "lua-bz2"
2version = "0.2.1-1"
3source = {
4 url = "git+ssh://git@github.com/hishamhm/lua-bz2.git",
5 tag = "0.2.1"
6}
7description = {
8 summary = "A Lua binding to Julian Seward's libbzip2",
9 detailed = [[
10 Support for reading and writing .bz2 files
11 and handling streams compressed in bzip2 format.
12 ]],
13 homepage = "https://github.com/hishamhm/lua-bz2",
14 license = "ISC"
15}
16external_dependencies = {
17 BZ2 = {
18 library = "bz2"
19 }
20}
21build = {
22 type = "builtin",
23 modules = {
24 bz2 = {
25 defines = {
26 "COMPAT53_PREFIX=compat53"
27 },
28 incdirs = {
29 "$(BZ2_INCDIR)"
30 },
31 libdirs = {
32 "$(BZ2_LIBDIR)"
33 },
34 libraries = {
35 "bz2"
36 },
37 sources = {
38 "lbz.c",
39 "lbz2_common.c",
40 "lbz2_file_reader.c",
41 "lbz2_file_writer.c",
42 "lbz2_stream.c",
43 "compat-5.3.c"
44 }
45 },
46 ["bz2.ltn12"] = "bz2/ltn12.lua"
47 }
48}
diff --git a/vendor/lua-zlib/.gitattributes b/vendor/lua-zlib/.gitattributes
new file mode 100644
index 00000000..54be6288
--- /dev/null
+++ b/vendor/lua-zlib/.gitattributes
@@ -0,0 +1 @@
lua_zlib.c export-subst ident
diff --git a/vendor/lua-zlib/README b/vendor/lua-zlib/README
new file mode 100644
index 00000000..c438ee05
--- /dev/null
+++ b/vendor/lua-zlib/README
@@ -0,0 +1,163 @@
1**********************************************************************
2* Author : Brian Maher <maherb at brimworks dot com>
3* Library : lua_zlib - Lua 5.1 interface to zlib
4*
5* The MIT License
6*
7* Copyright (c) 2009 Brian Maher
8*
9* Permission is hereby granted, free of charge, to any person obtaining a copy
10* of this software and associated documentation files (the "Software"), to deal
11* in the Software without restriction, including without limitation the rights
12* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13* copies of the Software, and to permit persons to whom the Software is
14* furnished to do so, subject to the following conditions:
15*
16* The above copyright notice and this permission notice shall be included in
17* all copies or substantial portions of the Software.
18*
19* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25* THE SOFTWARE.
26**********************************************************************
27
28To use this library, you need zlib, get it here:
29 http://www.gzip.org/zlib/
30
31To build this library, you can use CMake and get it here:
32 http://www.cmake.org/cmake/resources/software.html
33
34...or you can use GNU Make.
35 make <platform>
36
37Loading the library:
38
39 If you built the library as a loadable package
40 [local] zlib = require 'zlib'
41
42 If you compiled the package statically into your application, call
43 the function "luaopen_zlib(L)". It will create a table with the zlib
44 functions and leave it on the stack.
45
46-- zlib functions --
47
48int major, int minor, int patch = zlib.version()
49
50 returns numeric zlib version for the major, minor, and patch
51 levels of the version dynamically linked in.
52
53function stream = zlib.deflate([ int compression_level ], [ int window_size ])
54
55 If no compression_level is provided uses Z_DEFAULT_COMPRESSION (6),
56 compression level is a number from 1-9 where zlib.BEST_SPEED is 1
57 and zlib.BEST_COMPRESSION is 9.
58
59 Returns a "stream" function that compresses (or deflates) all
60 strings passed in. Specifically, use it as such:
61
62 string deflated, bool eof, int bytes_in, int bytes_out =
63 stream(string input [, 'sync' | 'full' | 'finish'])
64
65 Takes input and deflates and returns a portion of it,
66 optionally forcing a flush.
67
68 A 'sync' flush will force all pending output to be flushed to
69 the return value and the output is aligned on a byte boundary,
70 so that the decompressor can get all input data available so
71 far. Flushing may degrade compression for some compression
72 algorithms and so it should be used only when necessary.
73
74 A 'full' flush will flush all output as with 'sync', and the
75 compression state is reset so that decompression can restart
76 from this point if previous compressed data has been damaged
77 or if random access is desired. Using Z_FULL_FLUSH too often
78 can seriously degrade the compression.
79
80 A 'finish' flush will force all pending output to be processed
81 and results in the stream become unusable. Any future
82 attempts to print anything other than the empty string will
83 result in an error that begins with IllegalState.
84
85 The eof result is true if 'finish' was specified, otherwise
86 it is false.
87
88 The bytes_in is how many bytes of input have been passed to
89 stream, and bytes_out is the number of bytes returned in
90 deflated string chunks.
91
92function stream = zlib.inflate([int windowBits])
93
94 Returns a "stream" function that decompresses (or inflates) all
95 strings passed in. Optionally specify a windowBits argument
96 that is passed to inflateInit2(), see zlib.h for details about
97 this argument. By default, gzip header detection is done, and
98 the max window size is used.
99
100 The "stream" function should be used as such:
101
102 string inflated, bool eof, int bytes_in, int bytes_out =
103 stream(string input)
104
105 Takes input and inflates and returns a portion of it. If it
106 detects the end of a deflation stream, then total will be the
107 total number of bytes read from input and all future calls to
108 stream() with a non empty string will result in an error that
109 begins with IllegalState.
110
111 No flush options are provided since the maximal amount of
112 input is always processed.
113
114 eof will be true when the input string is determined to be at
115 the "end of the file".
116
117 The bytes_in is how many bytes of input have been passed to
118 stream, and bytes_out is the number of bytes returned in
119 inflated string chunks.
120
121
122function compute_checksum = zlib.adler32()
123function compute_checksum = zlib.crc32()
124
125 Create a new checksum computation function using either the
126 adler32 or crc32 algorithms. This resulting function should be
127 used as such:
128
129 int checksum = compute_checksum(string input |
130 function compute_checksum)
131
132 The compute_checksum function takes as input either a string
133 that is logically getting appended to or another
134 compute_checksum function that is logically getting appended.
135 The result is the updated checksum.
136
137 For example, these uses will all result in the same checksum:
138
139 -- All in one call:
140 local csum = zlib.crc32()("one two")
141
142 -- Multiple calls:
143 local compute = zlib.crc32()
144 compute("one")
145 assert(csum == compute(" two"))
146
147 -- Multiple compute_checksums joined:
148 local compute1, compute2 = zlib.crc32(), zlib.crc32()
149 compute1("one")
150 compute2(" two")
151 assert(csum == compute1(compute2))
152
153NOTE: This library ships with an "lzlib" compatibility shim. However, the
154following things are not compatible:
155
156 * zlib.version() in lzlib returns a string, but this library returns a
157 numeric tuple (see above).
158
159 * zlib.{adler,crc}32() in lzlib returns the {adler,crc}32 initial value,
160 however if this value is used with calls to adler32 it works in
161 compatibility mode.
162
163To use this shim add the -DLZLIB_COMPAT compiler flag. \ No newline at end of file
diff --git a/vendor/lua-zlib/lua-zlib-1.1-0.rockspec b/vendor/lua-zlib/lua-zlib-1.1-0.rockspec
new file mode 100644
index 00000000..7927d6ce
--- /dev/null
+++ b/vendor/lua-zlib/lua-zlib-1.1-0.rockspec
@@ -0,0 +1,42 @@
1package = "lua-zlib"
2version = "1.2-0"
3source = {
4 url = "git://github.com/brimworks/lua-zlib.git",
5 tag = "v1.2",
6}
7description = {
8 summary = "Simple streaming interface to zlib for Lua.",
9 detailed = [[
10 Simple streaming interface to zlib for Lua.
11 Consists of two functions: inflate and deflate.
12 Both functions return "stream functions" (takes a buffer of input and returns a buffer of output).
13 This project is hosted on github.
14 ]],
15 homepage = "https://github.com/brimworks/lua-zlib",
16 license = "MIT"
17}
18dependencies = {
19 "lua >= 5.1, <= 5.3"
20}
21external_dependencies = {
22 ZLIB = {
23 header = "zlib.h"
24 }
25}
26
27build = {
28 type = "builtin",
29 modules = {
30 zlib = {
31 sources = { "lua_zlib.c" },
32 libraries = { "z" },
33 defines = { "LZLIB_COMPAT" },
34 incdirs = { "$(ZLIB_INCDIR)" },
35 }
36 },
37 platforms = {
38 windows = { modules = { zlib = { libraries = {
39 "$(ZLIB_LIBDIR)/zlib" -- Must full path to `"zlib"`, or else will cause the `LINK : fatal error LNK1149`
40 } } } }
41 }
42}
diff --git a/vendor/lua-zlib/lua_zlib.c b/vendor/lua-zlib/lua_zlib.c
new file mode 100644
index 00000000..da57e91a
--- /dev/null
+++ b/vendor/lua-zlib/lua_zlib.c
@@ -0,0 +1,1295 @@
1#include <ctype.h>
2#include <lauxlib.h>
3#include <lua.h>
4#include <stdlib.h>
5#include <string.h>
6#include <zlib.h>
7
8/*
9 * ** compatibility with Lua 5.2
10 * */
11#if (LUA_VERSION_NUM >= 502)
12#undef luaL_register
13#define luaL_register(L,n,f) \
14 { if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); }
15
16#endif
17
18#if (LUA_VERSION_NUM >= 503)
19#undef luaL_optint
20#define luaL_optint(L,n,d) ((int)luaL_optinteger(L,(n),(d)))
21#endif
22
23#ifdef LZLIB_COMPAT
24/**************** lzlib compatibilty **********************************/
25/* Taken from https://raw.githubusercontent.com/LuaDist/lzlib/93b88e931ffa7cd0a52a972b6b26d37628f479f3/lzlib.c */
26
27/************************************************************************
28* Author : Tiago Dionizio <tiago.dionizio@gmail.com> *
29* Library : lzlib - Lua 5 interface to access zlib library functions *
30* *
31* Permission is hereby granted, free of charge, to any person obtaining *
32* a copy of this software and associated documentation files (the *
33* "Software"), to deal in the Software without restriction, including *
34* without limitation the rights to use, copy, modify, merge, publish, *
35* distribute, sublicense, and/or sell copies of the Software, and to *
36* permit persons to whom the Software is furnished to do so, subject to *
37* the following conditions: *
38* *
39* The above copyright notice and this permission notice shall be *
40* included in all copies or substantial portions of the Software. *
41* *
42* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
43* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
44* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
45* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY *
46* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, *
47* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE *
48* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
49************************************************************************/
50
51
52/*
53** =========================================================================
54** compile time options wich determine available functionality
55** =========================================================================
56*/
57
58/* TODO
59
60- also call flush on table/userdata when flush function is detected
61- remove io_cb check inflate_block if condition
62- only set eos when ZSTREAM_END is reached
63- check for stream errors to close stream when really needed
64
65*/
66
67
68/*
69** =========================================================================
70** zlib stream metamethods
71** =========================================================================
72*/
73#define ZSTREAMMETA "zlib:zstream"
74
75#define LZ_ANY -1
76#define LZ_NONE 0
77#define LZ_DEFLATE 1
78#define LZ_INFLATE 2
79
80#if 0
81 #define LZ_BUFFER_SIZE LUAL_BUFFERSIZE
82#else
83 #define LZ_BUFFER_SIZE 8192
84#endif
85
86typedef struct {
87 /* zlib structures */
88 z_stream zstream;
89 /* stream state. LZ_DEFLATE | LZ_INFLATE */
90 int state;
91 int error;
92 int peek;
93 int eos;
94 /* user callback source for reading/writing */
95 int io_cb;
96 /* input buffer */
97 int i_buffer_ref;
98 size_t i_buffer_pos;
99 size_t i_buffer_len;
100 const char *i_buffer;
101 /* output buffer */
102 size_t o_buffer_len;
103 size_t o_buffer_max;
104 char o_buffer[LZ_BUFFER_SIZE];
105 /* dictionary */
106 const Bytef *dictionary;
107 size_t dictionary_len;
108} lz_stream;
109
110
111/* forward declarations */
112static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush);
113
114
115static lz_stream *lzstream_new(lua_State *L, int src) {
116 lz_stream *s = (lz_stream*)lua_newuserdata(L, sizeof(lz_stream));
117
118 luaL_getmetatable(L, ZSTREAMMETA);
119 lua_setmetatable(L, -2); /* set metatable */
120
121 s->state = LZ_NONE;
122 s->error = Z_OK;
123 s->eos = 0;
124 s->io_cb = LUA_REFNIL;
125
126 s->i_buffer = NULL;
127 s->i_buffer_ref = LUA_REFNIL;
128 s->i_buffer_pos = 0;
129 s->i_buffer_len = 0;
130
131 s->peek = 0;
132 s->o_buffer_len = 0;
133 s->o_buffer_max = sizeof(s->o_buffer) / sizeof(s->o_buffer[0]);
134
135 s->zstream.zalloc = Z_NULL;
136 s->zstream.zfree = Z_NULL;
137
138 /* prepare source */
139 if (lua_isstring(L, src)) {
140 lua_pushvalue(L, src);
141 s->i_buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX);
142 s->i_buffer = lua_tolstring(L, src, &s->i_buffer_len);
143 } else {
144 /* table | function | userdata */
145 lua_pushvalue(L, src);
146 s->io_cb = luaL_ref(L, LUA_REGISTRYINDEX);
147 }
148 return s;
149}
150
151static void lzstream_cleanup(lua_State *L, lz_stream *s) {
152 if (s && s->state != LZ_NONE) {
153 if (s->state == LZ_INFLATE) {
154 inflateEnd(&s->zstream);
155 }
156 if (s->state == LZ_DEFLATE) {
157 deflateEnd(&s->zstream);
158 }
159
160 luaL_unref(L, LUA_REGISTRYINDEX, s->io_cb);
161 luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref);
162 s->state = LZ_NONE;
163 }
164}
165
166/* ====================================================================== */
167
168static lz_stream *lzstream_get(lua_State *L, int index) {
169 lz_stream *s = (lz_stream*)luaL_checkudata(L, index, ZSTREAMMETA);
170 if (s == NULL) luaL_argerror(L, index, "bad zlib stream");
171 return s;
172}
173
174static lz_stream *lzstream_check(lua_State *L, int index, int state) {
175 lz_stream *s = lzstream_get(L, index);
176 if ((state != LZ_ANY && s->state != state) || s->state == LZ_NONE) {
177 luaL_argerror(L, index, "attempt to use invalid zlib stream");
178 }
179 return s;
180}
181
182/* ====================================================================== */
183
184static int lzstream_tostring(lua_State *L) {
185 lz_stream *s = (lz_stream*)luaL_checkudata(L, 1, ZSTREAMMETA);
186 if (s == NULL) luaL_argerror(L, 1, "bad zlib stream");
187
188 if (s->state == LZ_NONE) {
189 lua_pushstring(L, "zlib stream (closed)");
190 } else if (s->state == LZ_DEFLATE) {
191 lua_pushfstring(L, "zlib deflate stream (%p)", (void*)s);
192 } else if (s->state == LZ_INFLATE) {
193 lua_pushfstring(L, "zlib inflate stream (%p)", (void*)s);
194 } else {
195 lua_pushfstring(L, "%p", (void*)s);
196 }
197
198 return 1;
199}
200
201/* ====================================================================== */
202
203static int lzstream_gc(lua_State *L) {
204 lz_stream *s = lzstream_get(L, 1);
205 lzstream_cleanup(L, s);
206 return 0;
207}
208
209/* ====================================================================== */
210
211static int lzstream_close(lua_State *L) {
212 lz_stream *s = lzstream_get(L, 1);
213
214 if (s->state == LZ_DEFLATE) {
215 lua_settop(L, 0);
216 lua_pushliteral(L, "");
217 return lzstream_docompress(L, s, 1, 1, Z_FINISH);
218 }
219
220 lzstream_cleanup(L, s);
221 lua_pushboolean(L, 1);
222 return 1;
223}
224
225/* ====================================================================== */
226
227static int lzstream_adler(lua_State *L) {
228 lz_stream *s = lzstream_check(L, 1, LZ_ANY);
229 lua_pushnumber(L, s->zstream.adler);
230 return 1;
231}
232
233/* ====================================================================== */
234
235/*
236 zlib.deflate(
237 sink: function | { write: function [, close: function, flush: function] },
238 compression level, [Z_DEFAILT_COMPRESSION]
239 method, [Z_DEFLATED]
240 windowBits, [15]
241 memLevel, [8]
242 strategy, [Z_DEFAULT_STRATEGY]
243 dictionary: [""]
244 )
245*/
246static int lzlib_deflate(lua_State *L) {
247 int level, method, windowBits, memLevel, strategy;
248 lz_stream *s;
249 const char *dictionary;
250 size_t dictionary_len;
251
252 if (lua_istable(L, 1) || lua_isuserdata(L, 1)) {
253 /* is there a :write function? */
254 lua_getfield(L, 1, "write");
255 if (!lua_isfunction(L, -1)) {
256 luaL_argerror(L, 1, "output parameter does not provide :write function");
257 }
258 lua_pop(L, 1);
259 }
260 else if (!lua_isfunction(L, 1)) {
261 luaL_argerror(L, 1, "output parameter must be a function, table or userdata value");
262 }
263
264 level = (int) luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION);
265 method = (int) luaL_optinteger(L, 3, Z_DEFLATED);
266 windowBits = (int) luaL_optinteger(L, 4, 15);
267 memLevel = (int) luaL_optinteger(L, 5, 8);
268 strategy = (int) luaL_optinteger(L, 6, Z_DEFAULT_STRATEGY);
269 dictionary = luaL_optlstring(L, 7, NULL, &dictionary_len);
270
271 s = lzstream_new(L, 1);
272
273 if (deflateInit2(&s->zstream, level, method, windowBits, memLevel, strategy) != Z_OK) {
274 lua_pushliteral(L, "call to deflateInit2 failed");
275 lua_error(L);
276 }
277
278 if (dictionary) {
279 if (deflateSetDictionary(&s->zstream, (const Bytef *) dictionary, dictionary_len) != Z_OK) {
280 lua_pushliteral(L, "call to deflateSetDictionnary failed");
281 lua_error(L);
282 }
283 }
284
285 s->state = LZ_DEFLATE;
286 return 1;
287}
288
289/*
290 zlib.inflate(
291 source: string | function | { read: function, close: function },
292 windowBits: number, [15]
293 dictionary: [""]
294 )
295*/
296static int lzlib_inflate(lua_State *L)
297{
298 int windowBits;
299 lz_stream *s;
300 int have_peek = 0;
301 const char *dictionary;
302 size_t dictionary_len;
303
304 if (lua_istable(L, 1) || lua_isuserdata(L, 1)) {
305 /* is there a :read function? */
306 lua_getfield(L, 1, "read");
307 if (!lua_isfunction(L, -1)) {
308 luaL_argerror(L, 1, "input parameter does not provide :read function");
309 }
310 lua_pop(L, 1);
311 /* check for peek function */
312 lua_getfield(L, 1, "peek");
313 have_peek = lua_isfunction(L, -1);
314 lua_pop(L, 1);
315 }
316 else if (!lua_isstring(L, 1) && !lua_isfunction(L, 1)) {
317 luaL_argerror(L, 1, "input parameter must be a string, function, table or userdata value");
318 }
319
320 windowBits = (int) luaL_optinteger(L, 2, 15);
321 dictionary = luaL_optlstring(L, 3, NULL, &dictionary_len);
322
323 s = lzstream_new(L, 1);
324
325 if (windowBits > 0 && windowBits < 16) {
326 windowBits |= 32;
327 }
328
329 if (inflateInit2(&s->zstream, windowBits) != Z_OK) {
330 lua_pushliteral(L, "call to inflateInit2 failed");
331 lua_error(L);
332 }
333
334 if (dictionary) {
335 s->dictionary = (const Bytef *) dictionary;
336 s->dictionary_len = dictionary_len;
337 }
338
339 s->peek = have_peek;
340 s->state = LZ_INFLATE;
341 return 1;
342}
343
344/* ====================================================================== */
345
346static int lz_pushresult (lua_State *L, lz_stream *s) {
347 if (s->error == Z_OK) {
348 lua_pushboolean(L, 1);
349 return 1;
350 } else {
351 lua_pushnil(L);
352 lua_pushstring(L, zError(s->error));
353 lua_pushinteger(L, s->error);
354 return 3;
355 }
356}
357
358/*
359 Get block to process:
360 - top of stack gets
361*/
362static const char* lzstream_fetch_block(lua_State *L, lz_stream *s, int hint) {
363 if (s->i_buffer_pos >= s->i_buffer_len) {
364 luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref);
365 s->i_buffer_ref = LUA_NOREF;
366 s->i_buffer = NULL;
367
368 lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb);
369 if (!lua_isnil(L, -1)) {
370 if (lua_isfunction(L, -1)) {
371 lua_pushinteger(L, hint);
372 lua_call(L, 1, 1);
373 } else {
374 lua_getfield(L, -1, (s->peek ? "peek" : "read"));
375 lua_insert(L, -2);
376 lua_pushinteger(L, hint);
377 lua_call(L, 2, 1);
378 }
379
380 if (lua_isstring(L, -1)) {
381 s->i_buffer_pos = 0;
382 s->i_buffer = lua_tolstring(L, -1, &s->i_buffer_len);
383 if (s->i_buffer_len > 0) {
384 s->i_buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX);
385 } else {
386 lua_pop(L, 1);
387 }
388 } else if (lua_isnil(L, -1)) {
389 lua_pop(L, 1);
390 } else {
391 lua_pushliteral(L, "deflate callback must return string or nil");
392 lua_error(L);
393 }
394 } else {
395 lua_pop(L, 1);
396 }
397 }
398
399 return s->i_buffer;
400}
401
402static int lzstream_inflate_block(lua_State *L, lz_stream *s) {
403 if (lzstream_fetch_block(L, s, LZ_BUFFER_SIZE) || !s->eos) {
404 int r;
405
406 if (s->i_buffer_len == s->i_buffer_pos) {
407 s->zstream.next_in = NULL;
408 s->zstream.avail_in = 0;
409 } else {
410 s->zstream.next_in = (unsigned char*)(s->i_buffer + s->i_buffer_pos);
411 s->zstream.avail_in = s->i_buffer_len - s->i_buffer_pos;
412 }
413
414 s->zstream.next_out = (unsigned char*)s->o_buffer + s->o_buffer_len;
415 s->zstream.avail_out = s->o_buffer_max - s->o_buffer_len;
416
417 /* munch some more */
418 r = inflate(&s->zstream, Z_SYNC_FLUSH);
419
420 if (r == Z_NEED_DICT) {
421 if (s->dictionary == NULL) {
422 lua_pushliteral(L, "no inflate dictionary provided");
423 lua_error(L);
424 }
425
426 if (inflateSetDictionary(&s->zstream, s->dictionary, s->dictionary_len) != Z_OK) {
427 lua_pushliteral(L, "call to inflateSetDictionnary failed");
428 lua_error(L);
429 }
430
431 r = inflate(&s->zstream, Z_SYNC_FLUSH);
432 }
433
434 if (r != Z_OK && r != Z_STREAM_END && r != Z_BUF_ERROR) {
435 lzstream_cleanup(L, s);
436 s->error = r;
437 #if 1
438 lua_pushfstring(L, "failed to decompress [%d]", r);
439 lua_error(L);
440 #endif
441 }
442
443 if (r == Z_STREAM_END) {
444 luaL_unref(L, LUA_REGISTRYINDEX, s->i_buffer_ref);
445 s->i_buffer_ref = LUA_NOREF;
446 s->i_buffer = NULL;
447
448 s->eos = 1;
449 }
450
451 /* number of processed bytes */
452 if (s->peek) {
453 size_t processed = s->i_buffer_len - s->i_buffer_pos - s->zstream.avail_in;
454
455 lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb);
456 lua_getfield(L, -1, "read");
457 lua_insert(L, -2);
458 lua_pushinteger(L, processed);
459 lua_call(L, 2, 0);
460 }
461
462 s->i_buffer_pos = s->i_buffer_len - s->zstream.avail_in;
463 s->o_buffer_len = s->o_buffer_max - s->zstream.avail_out;
464 }
465
466 return s->o_buffer_len;
467}
468
469/*
470** Remove n bytes from the output buffer.
471*/
472static void lzstream_remove(lz_stream *s, size_t n) {
473 memmove(s->o_buffer, s->o_buffer + n, s->o_buffer_len - n);
474 s->o_buffer_len -= n;
475}
476
477/*
478** Copy at most n bytes to buffer b and remove them from the
479** output stream buffer.
480*/
481static int lzstream_flush_buffer(lua_State *L, lz_stream *s, size_t n, luaL_Buffer *b) {
482 /* check output */
483 if (n > s->o_buffer_len) {
484 n = s->o_buffer_len;
485 }
486
487 if (n > 0) {
488 lua_pushlstring(L, s->o_buffer, n);
489 luaL_addvalue(b);
490
491 lzstream_remove(s, n);
492 }
493
494 return n;
495}
496
497/*
498 z:read(
499 {number | '*l' | '*a'}*
500 )
501*/
502static int lz_test_eof(lua_State *L, lz_stream *s) {
503 lua_pushlstring(L, NULL, 0);
504 if (s->o_buffer_len > 0) {
505 return 1;
506 } else if (s->eos) {
507 return 0;
508 } else {
509 return lzstream_inflate_block(L, s);
510 }
511}
512
513static int lz_read_line(lua_State *L, lz_stream *s) {
514 luaL_Buffer b;
515 size_t l = 0, n;
516
517 luaL_buffinit(L, &b);
518
519 if (s->o_buffer_len > 0 || !s->eos) do {
520 char *p = s->o_buffer;
521 size_t len = s->o_buffer_len;
522
523 /* find newline in output buffer */
524 for (n = 0; n < len; ++n, ++p) {
525 if (*p == '\n' || *p == '\r') {
526 int eat_nl = *p == '\r';
527 luaL_addlstring(&b, s->o_buffer, n);
528 lzstream_remove(s, n+1);
529 l += n;
530
531 if (eat_nl && lzstream_inflate_block(L, s)) {
532 if (s->o_buffer_len > 0 && *s->o_buffer == '\n') {
533 lzstream_remove(s, 1);
534 }
535 }
536
537 luaL_pushresult(&b);
538 return 1;
539 }
540 }
541
542 if (len > 0) {
543 luaL_addlstring(&b, s->o_buffer, len);
544 lzstream_remove(s, len);
545 l += len;
546 }
547 } while (lzstream_inflate_block(L, s));
548
549 luaL_pushresult(&b);
550 return l > 0 || !s->eos || s->o_buffer_len > 0;
551}
552
553
554static int lz_read_chars(lua_State *L, lz_stream *s, size_t n) {
555 size_t len;
556 luaL_Buffer b;
557 luaL_buffinit(L, &b);
558
559 if (s->o_buffer_len > 0 || !s->eos) do {
560 size_t rlen = lzstream_flush_buffer(L, s, n, &b);
561 n -= rlen;
562 } while (n > 0 && lzstream_inflate_block(L, s));
563
564 luaL_pushresult(&b);
565 lua_tolstring(L, -1, &len);
566 return n == 0 || len > 0;
567}
568
569static int lzstream_decompress(lua_State *L) {
570 lz_stream *s = lzstream_check(L, 1, LZ_INFLATE);
571 int nargs = lua_gettop(L) - 1;
572 int success;
573 int n;
574 if (nargs == 0) { /* no arguments? */
575 success = lz_read_line(L, s);
576 n = 3; /* to return 1 result */
577 }
578 else { /* ensure stack space for all results and for auxlib's buffer */
579 luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
580 success = 1;
581 for (n = 2; nargs-- && success; n++) {
582 if (lua_type(L, n) == LUA_TNUMBER) {
583 size_t l = (size_t)lua_tointeger(L, n);
584 success = (l == 0) ? lz_test_eof(L, s) : lz_read_chars(L, s, l);
585 }
586 else {
587 const char *p = lua_tostring(L, n);
588 luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
589 switch (p[1]) {
590 case 'l': /* line */
591 success = lz_read_line(L, s);
592 break;
593 case 'a': /* file */
594 lz_read_chars(L, s, ~((size_t)0)); /* read MAX_SIZE_T chars */
595 success = 1; /* always success */
596 break;
597 default:
598 return luaL_argerror(L, n, "invalid format");
599 }
600 }
601 }
602 }
603 if (s->error != Z_OK) {
604 return lz_pushresult(L, s);
605 }
606 if (!success) {
607 lua_pop(L, 1); /* remove last result */
608 lua_pushnil(L); /* push nil instead */
609 }
610 return n - 2;
611}
612
613
614static int lzstream_readline(lua_State *L) {
615 lz_stream *s;
616 int sucess;
617
618 s = lzstream_check(L, lua_upvalueindex(1), LZ_INFLATE);
619 sucess = lz_read_line(L, s);
620
621 if (s->error != Z_OK) {
622 return lz_pushresult(L, s);
623 }
624
625 if (sucess) {
626 return 1;
627 } else {
628 /* EOF */
629 return 0;
630 }
631}
632
633static int lzstream_lines(lua_State *L) {
634 lzstream_check(L, 1, LZ_INFLATE);
635 lua_settop(L, 1);
636 lua_pushcclosure(L, lzstream_readline, 1);
637 return 1;
638}
639
640/* ====================================================================== */
641
642static int lzstream_docompress(lua_State *L, lz_stream *s, int from, int to, int flush) {
643 int r, arg;
644 int self = 0;
645 size_t b_size = s->o_buffer_max;
646 unsigned char *b = (unsigned char *)s->o_buffer;
647
648 /* number of processed bytes */
649 lua_rawgeti(L, LUA_REGISTRYINDEX, s->io_cb);
650 if (!lua_isfunction(L, -1)) {
651 self = 1;
652 lua_getfield(L, -1, "write");
653 }
654
655 for (arg = from; arg <= to; arg++) {
656 s->zstream.next_in = (unsigned char*)luaL_checklstring(L, arg, (size_t*)&s->zstream.avail_in);
657
658 do {
659 s->zstream.next_out = b;
660 s->zstream.avail_out = b_size;
661
662 /* bake some more */
663 r = deflate(&s->zstream, flush);
664 if (r != Z_OK && r != Z_STREAM_END && r != Z_BUF_ERROR) {
665 lzstream_cleanup(L, s);
666 lua_pushboolean(L, 0);
667 lua_pushfstring(L, "failed to compress [%d]", r);
668 return 2;
669 }
670
671 if (s->zstream.avail_out != b_size) {
672 /* write output */
673 lua_pushvalue(L, -1); /* function */
674 if (self) lua_pushvalue(L, -3); /* self */
675 lua_pushlstring(L, (char*)b, b_size - s->zstream.avail_out); /* data */
676 lua_call(L, (self ? 2 : 1), 0);
677 }
678
679 if (r == Z_STREAM_END) {
680 lzstream_cleanup(L, s);
681 break;
682 }
683
684 /* process all input */
685 } while (s->zstream.avail_in > 0 || s->zstream.avail_out == 0);
686 }
687
688 lua_pushboolean(L, 1);
689 return 1;
690}
691
692static int lzstream_compress(lua_State *L) {
693 lz_stream *s = lzstream_check(L, 1, LZ_DEFLATE);
694 return lzstream_docompress(L, s, 2, lua_gettop(L), Z_NO_FLUSH);
695}
696
697
698/* ====================================================================== */
699
700static int lzstream_flush(lua_State *L) {
701 static int flush_values[] = { Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH };
702 static const char *const flush_opts[] = { "sync", "full", "finish" };
703
704 lz_stream *s = lzstream_check(L, 1, LZ_DEFLATE);
705 int flush = luaL_checkoption(L, 2, flush_opts[0], flush_opts);
706
707 lua_settop(L, 0);
708 lua_pushliteral(L, "");
709 return lzstream_docompress(L, s, 1, 1, flush_values[flush]);
710}
711
712/* ====================================================================== */
713
714static int lzlib_compress(lua_State *L) {
715 size_t avail_in;
716 const char *next_in = luaL_checklstring(L, 1, &avail_in);
717 int level = (int) luaL_optinteger(L, 2, Z_DEFAULT_COMPRESSION);
718 int method = (int) luaL_optinteger(L, 3, Z_DEFLATED);
719 int windowBits = (int) luaL_optinteger(L, 4, 15);
720 int memLevel = (int) luaL_optinteger(L, 5, 8);
721 int strategy = (int) luaL_optinteger(L, 6, Z_DEFAULT_STRATEGY);
722
723 int ret;
724 luaL_Buffer b;
725 z_stream zs;
726
727 luaL_buffinit(L, &b);
728
729 zs.zalloc = Z_NULL;
730 zs.zfree = Z_NULL;
731
732 zs.next_out = Z_NULL;
733 zs.avail_out = 0;
734 zs.next_in = Z_NULL;
735 zs.avail_in = 0;
736
737 ret = deflateInit2(&zs, level, method, windowBits, memLevel, strategy);
738
739 if (ret != Z_OK)
740 {
741 lua_pushnil(L);
742 lua_pushnumber(L, ret);
743 return 2;
744 }
745
746 zs.next_in = (unsigned char*)next_in;
747 zs.avail_in = avail_in;
748
749 for(;;)
750 {
751 zs.next_out = (unsigned char*)luaL_prepbuffer(&b);
752 zs.avail_out = LUAL_BUFFERSIZE;
753
754 /* munch some more */
755 ret = deflate(&zs, Z_FINISH);
756
757 /* push gathered data */
758 luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
759
760 /* done processing? */
761 if (ret == Z_STREAM_END)
762 break;
763
764 /* error condition? */
765 if (ret != Z_OK)
766 break;
767 }
768
769 /* cleanup */
770 deflateEnd(&zs);
771
772 luaL_pushresult(&b);
773 lua_pushnumber(L, ret);
774 return 2;
775}
776
777/* ====================================================================== */
778
779static int lzlib_decompress(lua_State *L)
780{
781 size_t avail_in;
782 const char *next_in = luaL_checklstring(L, 1, &avail_in);
783 int windowBits = (int) luaL_optinteger(L, 2, 15);
784
785 int ret;
786 luaL_Buffer b;
787 z_stream zs;
788
789 luaL_buffinit(L, &b);
790
791 zs.zalloc = Z_NULL;
792 zs.zfree = Z_NULL;
793
794 zs.next_out = Z_NULL;
795 zs.avail_out = 0;
796 zs.next_in = Z_NULL;
797 zs.avail_in = 0;
798
799 ret = inflateInit2(&zs, windowBits);
800
801 if (ret != Z_OK) {
802 lua_pushliteral(L, "failed to initialize zstream structures");
803 lua_error(L);
804 }
805
806 zs.next_in = (unsigned char*)next_in;
807 zs.avail_in = avail_in;
808
809 for (;;) {
810 zs.next_out = (unsigned char*)luaL_prepbuffer(&b);
811 zs.avail_out = LUAL_BUFFERSIZE;
812
813 /* bake some more */
814 ret = inflate(&zs, Z_FINISH);
815
816 /* push gathered data */
817 luaL_addsize(&b, LUAL_BUFFERSIZE - zs.avail_out);
818
819 /* done processing? */
820 if (ret == Z_STREAM_END)
821 break;
822
823 if (ret != Z_OK && ret != Z_BUF_ERROR) {
824 /* cleanup */
825 inflateEnd(&zs);
826
827 lua_pushliteral(L, "failed to process zlib stream");
828 lua_error(L);
829 }
830 }
831
832 /* cleanup */
833 inflateEnd(&zs);
834
835 luaL_pushresult(&b);
836 return 1;
837}
838
839#endif
840/**********************************************************************/
841
842#define DEF_MEM_LEVEL 8
843
844typedef uLong (*checksum_t) (uLong crc, const Bytef *buf, uInt len);
845typedef uLong (*checksum_combine_t)(uLong crc1, uLong crc2, z_off_t len2);
846
847
848static int lz_deflate(lua_State *L);
849static int lz_deflate_delete(lua_State *L);
850static int lz_inflate_delete(lua_State *L);
851static int lz_inflate(lua_State *L);
852static int lz_checksum(lua_State *L);
853static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine);
854static int lz_adler32(lua_State *L);
855static int lz_crc32(lua_State *L);
856
857static int lz_version(lua_State *L) {
858 const char* version = zlibVersion();
859 int count = strlen(version) + 1;
860 char* cur = (char*)memcpy(lua_newuserdata(L, count),
861 version, count);
862
863 count = 0;
864 while ( *cur ) {
865 char* begin = cur;
866 /* Find all digits: */
867 while ( isdigit(*cur) ) cur++;
868 if ( begin != cur ) {
869 int is_end = *cur == '\0';
870 *cur = '\0';
871 lua_pushnumber(L, atoi(begin));
872 count++;
873 if ( is_end ) break;
874 cur++;
875 }
876 while ( *cur && ! isdigit(*cur) ) cur++;
877 }
878
879 return count;
880}
881
882static int lz_assert(lua_State *L, int result, const z_stream* stream, const char* file, int line) {
883 /* Both of these are "normal" return codes: */
884 if ( result == Z_OK || result == Z_STREAM_END ) return result;
885 switch ( result ) {
886 case Z_NEED_DICT:
887 lua_pushfstring(L, "RequiresDictionary: input stream requires a dictionary to be deflated (%s) at %s line %d",
888 stream->msg, file, line);
889 break;
890 case Z_STREAM_ERROR:
891 lua_pushfstring(L, "InternalError: inconsistent internal zlib stream (%s) at %s line %d",
892 stream->msg, file, line);
893 break;
894 case Z_DATA_ERROR:
895 lua_pushfstring(L, "InvalidInput: input string does not conform to zlib format or checksum failed at %s line %d",
896 file, line);
897 break;
898 case Z_MEM_ERROR:
899 lua_pushfstring(L, "OutOfMemory: not enough memory (%s) at %s line %d",
900 stream->msg, file, line);
901 break;
902 case Z_BUF_ERROR:
903 lua_pushfstring(L, "InternalError: no progress possible (%s) at %s line %d",
904 stream->msg, file, line);
905 break;
906 case Z_VERSION_ERROR:
907 lua_pushfstring(L, "IncompatibleLibrary: built with version %s, but dynamically linked with version %s (%s) at %s line %d",
908 ZLIB_VERSION, zlibVersion(), stream->msg, file, line);
909 break;
910 default:
911 lua_pushfstring(L, "ZLibError: unknown code %d (%s) at %s line %d",
912 result, stream->msg, file, line);
913 }
914 lua_error(L);
915 return result;
916}
917
918/**
919 * @upvalue z_stream - Memory for the z_stream.
920 * @upvalue remainder - Any remainder from the last deflate call.
921 *
922 * @param string - "print" to deflate stream.
923 * @param int - flush output buffer? Z_SYNC_FLUSH, Z_FULL_FLUSH, or Z_FINISH.
924 *
925 * if no params, terminates the stream (as if we got empty string and Z_FINISH).
926 */
927static int lz_filter_impl(lua_State *L, int (*filter)(z_streamp, int), int (*end)(z_streamp), char* name) {
928 int flush = Z_NO_FLUSH, result;
929 z_stream* stream;
930 luaL_Buffer buff;
931 size_t avail_in;
932
933 if ( filter == deflate ) {
934 const char *const opts[] = { "none", "sync", "full", "finish", NULL };
935 flush = luaL_checkoption(L, 2, opts[0], opts);
936 if ( flush ) flush++;
937 /* Z_NO_FLUSH(0) Z_SYNC_FLUSH(2), Z_FULL_FLUSH(3), Z_FINISH (4) */
938
939 /* No arguments or nil, we are terminating the stream: */
940 if ( lua_gettop(L) == 0 || lua_isnil(L, 1) ) {
941 flush = Z_FINISH;
942 }
943 }
944
945 stream = (z_stream*)lua_touserdata(L, lua_upvalueindex(1));
946 if ( stream == NULL ) {
947 if ( lua_gettop(L) >= 1 && lua_isstring(L, 1) ) {
948 lua_pushfstring(L, "IllegalState: calling %s function when stream was previously closed", name);
949 lua_error(L);
950 }
951 lua_pushstring(L, "");
952 lua_pushboolean(L, 1);
953 return 2; /* Ignore duplicate calls to "close". */
954 }
955
956 luaL_buffinit(L, &buff);
957
958 if ( lua_gettop(L) > 1 ) lua_pushvalue(L, 1);
959
960 if ( lua_isstring(L, lua_upvalueindex(2)) ) {
961 lua_pushvalue(L, lua_upvalueindex(2));
962 if ( lua_gettop(L) > 1 && lua_isstring(L, -2) ) {
963 lua_concat(L, 2);
964 }
965 }
966
967 /* Do the actual deflate'ing: */
968 if (lua_gettop(L) > 0) {
969 stream->next_in = (unsigned char*)lua_tolstring(L, -1, &avail_in);
970 } else {
971 stream->next_in = NULL;
972 avail_in = 0;
973 }
974 stream->avail_in = avail_in;
975
976 if ( ! stream->avail_in && ! flush ) {
977 /* Passed empty string, make it a noop instead of erroring out. */
978 lua_pushstring(L, "");
979 lua_pushboolean(L, 0);
980 lua_pushinteger(L, stream->total_in);
981 lua_pushinteger(L, stream->total_out);
982 return 4;
983 }
984
985 do {
986 stream->next_out = (unsigned char*)luaL_prepbuffer(&buff);
987 stream->avail_out = LUAL_BUFFERSIZE;
988 result = filter(stream, flush);
989 if ( Z_BUF_ERROR != result ) {
990 /* Ignore Z_BUF_ERROR since that just indicates that we
991 * need a larger buffer in order to proceed. Thanks to
992 * Tobias Markmann for finding this bug!
993 */
994 lz_assert(L, result, stream, __FILE__, __LINE__);
995 }
996 luaL_addsize(&buff, LUAL_BUFFERSIZE - stream->avail_out);
997 } while ( stream->avail_out == 0 );
998
999 /* Need to do this before we alter the stack: */
1000 luaL_pushresult(&buff);
1001
1002 /* Save remainder in lua_upvalueindex(2): */
1003 if ( NULL != stream->next_in ) {
1004 lua_pushlstring(L, (char*)stream->next_in, stream->avail_in);
1005 lua_replace(L, lua_upvalueindex(2));
1006 }
1007
1008 /* "close" the stream/remove finalizer: */
1009 if ( result == Z_STREAM_END ) {
1010 /* Clear-out the metatable so end is not called twice: */
1011 lua_pushnil(L);
1012 lua_setmetatable(L, lua_upvalueindex(1));
1013
1014 /* nil the upvalue: */
1015 lua_pushnil(L);
1016 lua_replace(L, lua_upvalueindex(1));
1017
1018 /* Close the stream: */
1019 lz_assert(L, end(stream), stream, __FILE__, __LINE__);
1020
1021 lua_pushboolean(L, 1);
1022 } else {
1023 lua_pushboolean(L, 0);
1024 }
1025 lua_pushinteger(L, stream->total_in);
1026 lua_pushinteger(L, stream->total_out);
1027 return 4;
1028}
1029
1030static void lz_create_deflate_mt(lua_State *L) {
1031 luaL_newmetatable(L, "lz.deflate.meta"); /* {} */
1032
1033 lua_pushcfunction(L, lz_deflate_delete);
1034 lua_setfield(L, -2, "__gc");
1035
1036 lua_pop(L, 1); /* <empty> */
1037}
1038
1039static int lz_deflate_new(lua_State *L) {
1040 int level;
1041 int window_size;
1042 int result;
1043
1044#ifdef LZLIB_COMPAT
1045 if ( lua_istable(L, 1) || lua_isuserdata(L, 1) || lua_isfunction(L, 1) ) {
1046 return lzlib_deflate(L);
1047 }
1048#endif
1049
1050 level = luaL_optint(L, 1, Z_DEFAULT_COMPRESSION);
1051 window_size = luaL_optint(L, 2, MAX_WBITS);
1052
1053 /* Allocate the stream: */
1054 z_stream* stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream));
1055
1056 stream->zalloc = Z_NULL;
1057 stream->zfree = Z_NULL;
1058
1059 result = deflateInit2(stream, level, Z_DEFLATED, window_size,
1060 DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
1061
1062 lz_assert(L, result, stream, __FILE__, __LINE__);
1063
1064 /* Don't allow destructor to execute unless deflateInit2 was successful: */
1065 luaL_getmetatable(L, "lz.deflate.meta");
1066 lua_setmetatable(L, -2);
1067
1068 lua_pushnil(L);
1069 lua_pushcclosure(L, lz_deflate, 2);
1070 return 1;
1071}
1072
1073static int lz_deflate(lua_State *L) {
1074 return lz_filter_impl(L, deflate, deflateEnd, "deflate");
1075}
1076
1077static int lz_deflate_delete(lua_State *L) {
1078 z_stream* stream = (z_stream*)lua_touserdata(L, 1);
1079
1080 /* Ignore errors. */
1081 deflateEnd(stream);
1082
1083 return 0;
1084}
1085
1086
1087static void lz_create_inflate_mt(lua_State *L) {
1088 luaL_newmetatable(L, "lz.inflate.meta"); /* {} */
1089
1090 lua_pushcfunction(L, lz_inflate_delete);
1091 lua_setfield(L, -2, "__gc");
1092
1093 lua_pop(L, 1); /* <empty> */
1094}
1095
1096static int lz_inflate_new(lua_State *L) {
1097 /* Allocate the stream */
1098 z_stream* stream;
1099
1100#ifdef LZLIB_COMPAT
1101 int type = lua_type(L, 1);
1102 if ( type == LUA_TTABLE || type == LUA_TUSERDATA || type == LUA_TFUNCTION || type == LUA_TSTRING ) {
1103 return lzlib_inflate(L);
1104 }
1105#endif
1106
1107 stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream));
1108
1109 /* By default, we will do gzip header detection w/ max window size */
1110 int window_size = lua_isnumber(L, 1) ? lua_tointeger(L, 1) : MAX_WBITS + 32;
1111
1112 stream->zalloc = Z_NULL;
1113 stream->zfree = Z_NULL;
1114 stream->next_in = Z_NULL;
1115 stream->avail_in = 0;
1116
1117 lz_assert(L, inflateInit2(stream, window_size), stream, __FILE__, __LINE__);
1118
1119 /* Don't allow destructor to execute unless deflateInit was successful: */
1120 luaL_getmetatable(L, "lz.inflate.meta");
1121 lua_setmetatable(L, -2);
1122
1123 lua_pushnil(L);
1124 lua_pushcclosure(L, lz_inflate, 2);
1125 return 1;
1126}
1127
1128static int lz_inflate(lua_State *L) {
1129 return lz_filter_impl(L, inflate, inflateEnd, "inflate");
1130}
1131
1132static int lz_inflate_delete(lua_State *L) {
1133 z_stream* stream = (z_stream*)lua_touserdata(L, 1);
1134
1135 /* Ignore errors: */
1136 inflateEnd(stream);
1137
1138 return 0;
1139}
1140
1141static int lz_checksum(lua_State *L) {
1142 if ( lua_gettop(L) <= 0 ) {
1143 lua_pushvalue(L, lua_upvalueindex(3));
1144 lua_pushvalue(L, lua_upvalueindex(4));
1145 } else if ( lua_isfunction(L, 1) ) {
1146 checksum_combine_t combine = (checksum_combine_t)
1147 lua_touserdata(L, lua_upvalueindex(2));
1148
1149 lua_pushvalue(L, 1);
1150 lua_call(L, 0, 2);
1151 if ( ! lua_isnumber(L, -2) || ! lua_isnumber(L, -1) ) {
1152 luaL_argerror(L, 1, "expected function to return two numbers");
1153 }
1154
1155 /* Calculate and replace the checksum */
1156 lua_pushnumber(L,
1157 combine((uLong)lua_tonumber(L, lua_upvalueindex(3)),
1158 (uLong)lua_tonumber(L, -2),
1159 (z_off_t)lua_tonumber(L, -1)));
1160 lua_pushvalue(L, -1);
1161 lua_replace(L, lua_upvalueindex(3));
1162
1163 /* Calculate and replace the length */
1164 lua_pushnumber(L,
1165 lua_tonumber(L, lua_upvalueindex(4)) + lua_tonumber(L, -2));
1166 lua_pushvalue(L, -1);
1167 lua_replace(L, lua_upvalueindex(4));
1168 } else {
1169 const Bytef* str;
1170 size_t len;
1171
1172 checksum_t checksum = (checksum_t)
1173 lua_touserdata(L, lua_upvalueindex(1));
1174 str = (const Bytef*)luaL_checklstring(L, 1, &len);
1175
1176 /* Calculate and replace the checksum */
1177 lua_pushnumber(L,
1178 checksum((uLong)lua_tonumber(L, lua_upvalueindex(3)),
1179 str,
1180 len));
1181 lua_pushvalue(L, -1);
1182 lua_replace(L, lua_upvalueindex(3));
1183
1184 /* Calculate and replace the length */
1185 lua_pushnumber(L,
1186 lua_tonumber(L, lua_upvalueindex(4)) + len);
1187 lua_pushvalue(L, -1);
1188 lua_replace(L, lua_upvalueindex(4));
1189 }
1190 return 2;
1191}
1192
1193static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine) {
1194 lua_pushlightuserdata(L, checksum);
1195 lua_pushlightuserdata(L, combine);
1196 lua_pushnumber(L, checksum(0L, Z_NULL, 0));
1197 lua_pushnumber(L, 0);
1198 lua_pushcclosure(L, lz_checksum, 4);
1199 return 1;
1200}
1201
1202static int lz_adler32(lua_State *L) {
1203#ifdef LZLIB_COMPAT
1204 /* lzlib compat*/
1205 if ( lua_gettop(L) != 0 ) {
1206 size_t len;
1207 int adler;
1208 const unsigned char* buf;
1209 if ( lua_isfunction(L, 1) ) {
1210 adler = adler32(0L, Z_NULL, 0);
1211 } else {
1212 adler = (int)luaL_checkinteger(L, 1);
1213 }
1214 buf = (unsigned char*)luaL_checklstring(L, 2, &len);
1215 lua_pushnumber(L, adler32(adler, buf, len));
1216 return 1;
1217 }
1218#endif
1219 return lz_checksum_new(L, adler32, adler32_combine);
1220}
1221
1222static int lz_crc32(lua_State *L) {
1223#ifdef LZLIB_COMPAT
1224 /* lzlib compat*/
1225 if ( lua_gettop(L) != 0 ) {
1226 size_t len;
1227 int crc;
1228 const unsigned char* buf;
1229 if ( lua_isfunction(L, 1) ) {
1230 crc = crc32(0L, Z_NULL, 0);
1231 } else {
1232 crc = (int)luaL_checkinteger(L, 1);
1233 }
1234 buf = (unsigned char*)luaL_checklstring(L, 2, &len);
1235 lua_pushnumber(L, crc32(crc, buf, len));
1236 return 1;
1237 }
1238#endif
1239 return lz_checksum_new(L, crc32, crc32_combine);
1240}
1241
1242
1243static const luaL_Reg zlib_functions[] = {
1244 { "deflate", lz_deflate_new },
1245 { "inflate", lz_inflate_new },
1246 { "adler32", lz_adler32 },
1247 { "crc32", lz_crc32 },
1248#ifdef LZLIB_COMPAT
1249 { "compress", lzlib_compress },
1250 { "decompress", lzlib_decompress },
1251#endif
1252 { "version", lz_version },
1253 { NULL, NULL }
1254};
1255
1256#define SETLITERAL(n,v) (lua_pushliteral(L, n), lua_pushliteral(L, v), lua_settable(L, -3))
1257#define SETINT(n,v) (lua_pushliteral(L, n), lua_pushinteger(L, v), lua_settable(L, -3))
1258
1259LUALIB_API int luaopen_zlib(lua_State * const L) {
1260 lz_create_deflate_mt(L);
1261 lz_create_inflate_mt(L);
1262
1263 luaL_register(L, "zlib", zlib_functions);
1264
1265 SETINT("BEST_SPEED", Z_BEST_SPEED);
1266 SETINT("BEST_COMPRESSION", Z_BEST_COMPRESSION);
1267
1268 SETLITERAL("_COPYRIGHT", "Copyright (c) 2009-2016 Brian Maher");
1269 SETLITERAL("_DESCRIPTION", "Simple streaming interface to the zlib library");
1270 SETLITERAL("_VERSION", "lua-zlib $Id$ $Format:%d$");
1271
1272 /* Expose this to lua so we can do a test: */
1273 SETINT("_TEST_BUFSIZ", LUAL_BUFFERSIZE);
1274
1275 /* lzlib compatibility */
1276#ifdef LZLIB_COMPAT
1277 SETINT("NO_COMPRESSION", Z_NO_COMPRESSION);
1278 SETINT("DEFAULT_COMPRESSION", Z_DEFAULT_COMPRESSION);
1279 SETINT("FILTERED", Z_FILTERED);
1280 SETINT("HUFFMAN_ONLY", Z_HUFFMAN_ONLY);
1281 SETINT("RLE", Z_RLE);
1282 SETINT("FIXED", Z_FIXED);
1283 SETINT("DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY);
1284 SETINT("MINIMUM_MEMLEVEL", 1);
1285 SETINT("MAXIMUM_MEMLEVEL", 9);
1286 SETINT("DEFAULT_MEMLEVEL", 8);
1287 SETINT("DEFAULT_WINDOWBITS", 15);
1288 SETINT("MINIMUM_WINDOWBITS", 8);
1289 SETINT("MAXIMUM_WINDOWBITS", 15);
1290 SETINT("GZIP_WINDOWBITS", 16);
1291 SETINT("RAW_WINDOWBITS", -1);
1292#endif
1293
1294 return 1;
1295}
diff --git a/vendor/luafilesystem/.gitignore b/vendor/luafilesystem/.gitignore
new file mode 100644
index 00000000..ddaacd81
--- /dev/null
+++ b/vendor/luafilesystem/.gitignore
@@ -0,0 +1,2 @@
1*.so
2
diff --git a/vendor/luafilesystem/.travis.yml b/vendor/luafilesystem/.travis.yml
new file mode 100644
index 00000000..618e48e1
--- /dev/null
+++ b/vendor/luafilesystem/.travis.yml
@@ -0,0 +1,34 @@
1language: c
2
3sudo: false
4
5env:
6 - LUA="lua 5.1"
7 - LUA="lua 5.2"
8 - LUA="lua 5.3"
9 - LUA="luajit 2.1"
10
11before_install:
12 - pip install --user cpp-coveralls hererocks
13 - hererocks env --$LUA --luarocks latest
14 - export PATH="$PWD/env/bin:$PATH"
15 - luarocks install lua-path
16 - luarocks install dkjson
17 - luarocks install luacov
18 # install luacov-coveralls, but avoid installing luafilesystem
19 - luarocks install luacov-coveralls --server=https://luarocks.org/dev --deps-mode=none
20
21install:
22 - luarocks make CFLAGS="-O2 -fPIC -ftest-coverage -fprofile-arcs" LIBFLAG="-shared --coverage"
23
24script:
25 - lua -lluacov tests/test.lua
26
27after_success:
28 - coveralls -b . -i src --dump c.report.json
29 - luacov-coveralls -j c.report.json -v
30
31notifications:
32 email:
33 on_success: change
34 on_failure: always
diff --git a/vendor/luafilesystem/LICENSE b/vendor/luafilesystem/LICENSE
new file mode 100644
index 00000000..8475345a
--- /dev/null
+++ b/vendor/luafilesystem/LICENSE
@@ -0,0 +1,21 @@
1Copyright © 2003-2014 Kepler Project.
2
3Permission is hereby granted, free of charge, to any person
4obtaining a copy of this software and associated documentation
5files (the "Software"), to deal in the Software without
6restriction, including without limitation the rights to use, copy,
7modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be
12included in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
18BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
19ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
diff --git a/vendor/luafilesystem/README.md b/vendor/luafilesystem/README.md
new file mode 100644
index 00000000..d0fd3f29
--- /dev/null
+++ b/vendor/luafilesystem/README.md
@@ -0,0 +1,28 @@
1[![License](http://img.shields.io/badge/Licence-MIT-brightgreen.svg)](LICENSE)
2[![Build Status](https://travis-ci.org/keplerproject/luafilesystem.svg?branch=master)](https://travis-ci.org/keplerproject/luafilesystem)
3[![Build status](https://ci.appveyor.com/api/projects/status/y04s4ms7u16trw8e?svg=true)](https://ci.appveyor.com/project/ignacio/luafilesystem)
4[![Coverage Status](https://coveralls.io/repos/keplerproject/luafilesystem/badge.png)](https://coveralls.io/r/keplerproject/luafilesystem)
5
6# LuaFileSystem - File System Library for Lua
7
8Copyright 2003-2020 Kepler Project
9
10https://keplerproject.github.io/luafilesystem
11
12# Description
13
14LuaFileSystem is a Lua library developed to complement the set of functions
15related to file systems offered by the standard Lua distribution.
16
17LuaFileSystem offers a portable way to access the underlying directory structure and file attributes.
18LuaFileSystem is free software and uses the same license as Lua 5.x (MIT).
19
20# LuaRocks Installation
21
22```
23luarocks install luafilesystem
24```
25
26# Documentation
27
28Please check the documentation at doc/us/ for more information.
diff --git a/vendor/luafilesystem/luafilesystem-scm-1.rockspec b/vendor/luafilesystem/luafilesystem-scm-1.rockspec
new file mode 100644
index 00000000..71cf19b4
--- /dev/null
+++ b/vendor/luafilesystem/luafilesystem-scm-1.rockspec
@@ -0,0 +1,28 @@
1package = "luafilesystem"
2version = "scm-1"
3source = {
4 url = "git://github.com/keplerproject/luafilesystem"
5}
6description = {
7 summary = "File System Library for the Lua Programming Language",
8 detailed = [[
9 LuaFileSystem is a Lua library developed to complement the set of
10 functions related to file systems offered by the standard Lua
11 distribution. LuaFileSystem offers a portable way to access the
12 underlying directory structure and file attributes.
13 ]],
14 license = "MIT/X11"
15}
16dependencies = {
17 "lua >= 5.1"
18}
19build = {
20 type = "builtin",
21 modules = {
22 lfs = "src/lfs.c"
23 },
24 copy_directories = {
25 "doc",
26 "tests"
27 }
28}
diff --git a/vendor/luafilesystem/src/.gitignore b/vendor/luafilesystem/src/.gitignore
new file mode 100644
index 00000000..9d22eb46
--- /dev/null
+++ b/vendor/luafilesystem/src/.gitignore
@@ -0,0 +1,2 @@
1*.o
2*.so
diff --git a/vendor/luafilesystem/src/lfs.c b/vendor/luafilesystem/src/lfs.c
new file mode 100644
index 00000000..95ab63b4
--- /dev/null
+++ b/vendor/luafilesystem/src/lfs.c
@@ -0,0 +1,1182 @@
1/*
2** LuaFileSystem
3** Copyright Kepler Project 2003 - 2020
4** (http://keplerproject.github.io/luafilesystem)
5**
6** File system manipulation library.
7** This library offers these functions:
8** lfs.attributes (filepath [, attributename | attributetable])
9** lfs.chdir (path)
10** lfs.currentdir ()
11** lfs.dir (path)
12** lfs.link (old, new[, symlink])
13** lfs.lock (fh, mode)
14** lfs.lock_dir (path)
15** lfs.mkdir (path)
16** lfs.rmdir (path)
17** lfs.setmode (filepath, mode)
18** lfs.symlinkattributes (filepath [, attributename])
19** lfs.touch (filepath [, atime [, mtime]])
20** lfs.unlock (fh)
21*/
22
23#ifndef LFS_DO_NOT_USE_LARGE_FILE
24#ifndef _WIN32
25#ifndef _AIX
26#define _FILE_OFFSET_BITS 64 /* Linux, Solaris and HP-UX */
27#else
28#define _LARGE_FILES 1 /* AIX */
29#endif
30#endif
31#endif
32
33#ifdef _WIN32
34#define _WIN32_WINNT 0x600
35#endif
36
37#ifndef LFS_DO_NOT_USE_LARGE_FILE
38#define _LARGEFILE64_SOURCE
39#endif
40
41#include <errno.h>
42#include <stdio.h>
43#include <string.h>
44#include <stdlib.h>
45#include <time.h>
46#include <sys/stat.h>
47
48#ifdef _WIN32
49
50#include <direct.h>
51#include <windows.h>
52#include <io.h>
53#include <sys/locking.h>
54
55#ifdef __BORLANDC__
56#include <utime.h>
57#else
58#include <sys/utime.h>
59#endif
60
61#include <fcntl.h>
62
63/* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */
64#define LFS_MAXPATHLEN MAX_PATH
65
66#else
67
68#include <unistd.h>
69#include <dirent.h>
70#include <fcntl.h>
71#include <sys/types.h>
72#include <utime.h>
73#include <sys/param.h> /* for MAXPATHLEN */
74
75#ifdef MAXPATHLEN
76#define LFS_MAXPATHLEN MAXPATHLEN
77#else
78#include <limits.h> /* for _POSIX_PATH_MAX */
79#define LFS_MAXPATHLEN _POSIX_PATH_MAX
80#endif
81
82#endif
83
84#include <lua.h>
85#include <lauxlib.h>
86#include <lualib.h>
87
88#include "lfs.h"
89
90#define LFS_VERSION "1.8.0"
91#define LFS_LIBNAME "lfs"
92
93#if LUA_VERSION_NUM >= 503 /* Lua 5.3+ */
94
95#ifndef luaL_optlong
96#define luaL_optlong luaL_optinteger
97#endif
98
99#endif
100
101#if LUA_VERSION_NUM >= 502
102#define new_lib(L, l) (luaL_newlib(L, l))
103#else
104#define new_lib(L, l) (lua_newtable(L), luaL_register(L, NULL, l))
105#endif
106
107/* Define 'strerror' for systems that do not implement it */
108#ifdef NO_STRERROR
109#define strerror(_) "System unable to describe the error"
110#endif
111
112#define DIR_METATABLE "directory metatable"
113typedef struct dir_data {
114 int closed;
115#ifdef _WIN32
116 intptr_t hFile;
117 char pattern[MAX_PATH + 1];
118#else
119 DIR *dir;
120#endif
121} dir_data;
122
123#define LOCK_METATABLE "lock metatable"
124
125#ifdef _WIN32
126
127#ifdef __BORLANDC__
128#define lfs_setmode(file, m) (setmode(_fileno(file), m))
129#define STAT_STRUCT struct stati64
130#else
131#define lfs_setmode(file, m) (_setmode(_fileno(file), m))
132#define STAT_STRUCT struct _stati64
133#endif
134
135#ifndef _S_IFLNK
136#define _S_IFLNK 0x400
137#endif
138
139#ifndef S_ISDIR
140#define S_ISDIR(mode) (mode&_S_IFDIR)
141#endif
142#ifndef S_ISREG
143#define S_ISREG(mode) (mode&_S_IFREG)
144#endif
145#ifndef S_ISLNK
146#define S_ISLNK(mode) (mode&_S_IFLNK)
147#endif
148#ifndef S_ISSOCK
149#define S_ISSOCK(mode) (0)
150#endif
151#ifndef S_ISFIFO
152#define S_ISFIFO(mode) (0)
153#endif
154#ifndef S_ISCHR
155#define S_ISCHR(mode) (mode&_S_IFCHR)
156#endif
157#ifndef S_ISBLK
158#define S_ISBLK(mode) (0)
159#endif
160
161#define STAT_FUNC _stati64
162#define LSTAT_FUNC lfs_win32_lstat
163
164#else
165
166#define _O_TEXT 0
167#define _O_BINARY 0
168#define lfs_setmode(file, m) ((void)file, (void)m, 0)
169#define STAT_STRUCT struct stat
170#define STAT_FUNC stat
171#define LSTAT_FUNC lstat
172
173#endif
174
175#ifdef _WIN32
176#define lfs_mkdir _mkdir
177#else
178#define lfs_mkdir(path) (mkdir((path), \
179 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH))
180#endif
181
182#ifdef _WIN32
183
184int lfs_win32_pusherror(lua_State * L)
185{
186 int en = GetLastError();
187 lua_pushnil(L);
188 if (en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION)
189 lua_pushstring(L, "File exists");
190 else
191 lua_pushstring(L, strerror(en));
192 return 2;
193}
194
195#define TICKS_PER_SECOND 10000000
196#define EPOCH_DIFFERENCE 11644473600LL
197time_t windowsToUnixTime(FILETIME ft)
198{
199 ULARGE_INTEGER uli;
200 uli.LowPart = ft.dwLowDateTime;
201 uli.HighPart = ft.dwHighDateTime;
202 return (time_t) (uli.QuadPart / TICKS_PER_SECOND - EPOCH_DIFFERENCE);
203}
204
205int lfs_win32_lstat(const char *path, STAT_STRUCT * buffer)
206{
207 WIN32_FILE_ATTRIBUTE_DATA win32buffer;
208 if (GetFileAttributesEx(path, GetFileExInfoStandard, &win32buffer)) {
209 if (!(win32buffer.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
210 return STAT_FUNC(path, buffer);
211 }
212 buffer->st_mode = _S_IFLNK;
213 buffer->st_dev = 0;
214 buffer->st_ino = 0;
215 buffer->st_nlink = 0;
216 buffer->st_uid = 0;
217 buffer->st_gid = 0;
218 buffer->st_rdev = 0;
219 buffer->st_atime = windowsToUnixTime(win32buffer.ftLastAccessTime);
220 buffer->st_mtime = windowsToUnixTime(win32buffer.ftLastWriteTime);
221 buffer->st_ctime = windowsToUnixTime(win32buffer.ftCreationTime);
222 buffer->st_size = 0;
223 return 0;
224 } else {
225 return 1;
226 }
227}
228
229#endif
230
231/*
232** Utility functions
233*/
234static int pusherror(lua_State * L, const char *info)
235{
236 lua_pushnil(L);
237 if (info == NULL)
238 lua_pushstring(L, strerror(errno));
239 else
240 lua_pushfstring(L, "%s: %s", info, strerror(errno));
241 lua_pushinteger(L, errno);
242 return 3;
243}
244
245static int pushresult(lua_State * L, int res, const char *info)
246{
247 if (res == -1) {
248 return pusherror(L, info);
249 } else {
250 lua_pushboolean(L, 1);
251 return 1;
252 }
253}
254
255
256/*
257** This function changes the working (current) directory
258*/
259static int change_dir(lua_State * L)
260{
261 const char *path = luaL_checkstring(L, 1);
262 if (chdir(path)) {
263 lua_pushnil(L);
264 lua_pushfstring(L, "Unable to change working directory to '%s'\n%s\n",
265 path, chdir_error);
266 return 2;
267 } else {
268 lua_pushboolean(L, 1);
269 return 1;
270 }
271}
272
273/*
274** This function returns the current directory
275** If unable to get the current directory, it returns nil
276** and a string describing the error
277*/
278static int get_dir(lua_State * L)
279{
280#ifdef NO_GETCWD
281 lua_pushnil(L);
282 lua_pushstring(L, "Function 'getcwd' not provided by system");
283 return 2;
284#else
285 char *path = NULL;
286 /* Passing (NULL, 0) is not guaranteed to work.
287 Use a temp buffer and size instead. */
288 size_t size = LFS_MAXPATHLEN; /* initial buffer size */
289 int result;
290 while (1) {
291 char *path2 = realloc(path, size);
292 if (!path2) { /* failed to allocate */
293 result = pusherror(L, "get_dir realloc() failed");
294 break;
295 }
296 path = path2;
297 if (getcwd(path, size) != NULL) {
298 /* success, push the path to the Lua stack */
299 lua_pushstring(L, path);
300 result = 1;
301 break;
302 }
303 if (errno != ERANGE) { /* unexpected error */
304 result = pusherror(L, "get_dir getcwd() failed");
305 break;
306 }
307 /* ERANGE = insufficient buffer capacity, double size and retry */
308 size *= 2;
309 }
310 free(path);
311 return result;
312#endif
313}
314
315/*
316** Check if the given element on the stack is a file and returns it.
317*/
318static FILE *check_file(lua_State * L, int idx, const char *funcname)
319{
320#if LUA_VERSION_NUM == 501
321 FILE **fh = (FILE **) luaL_checkudata(L, idx, "FILE*");
322 if (*fh == NULL) {
323 luaL_error(L, "%s: closed file", funcname);
324 return 0;
325 } else
326 return *fh;
327#elif LUA_VERSION_NUM >= 502 && LUA_VERSION_NUM <= 504
328 luaL_Stream *fh = (luaL_Stream *) luaL_checkudata(L, idx, "FILE*");
329 if (fh->closef == 0 || fh->f == NULL) {
330 luaL_error(L, "%s: closed file", funcname);
331 return 0;
332 } else
333 return fh->f;
334#else
335#error unsupported Lua version
336#endif
337}
338
339
340/*
341**
342*/
343static int _file_lock(lua_State * L, FILE * fh, const char *mode,
344 const long start, long len, const char *funcname)
345{
346 int code;
347#ifdef _WIN32
348 /* lkmode valid values are:
349 LK_LOCK Locks the specified bytes. If the bytes cannot be locked,
350 the program immediately tries again after 1 second.
351 If, after 10 attempts, the bytes cannot be locked,
352 the constant returns an error.
353 LK_NBLCK Locks the specified bytes. If the bytes cannot be locked,
354 the constant returns an error.
355 LK_NBRLCK Same as _LK_NBLCK.
356 LK_RLCK Same as _LK_LOCK.
357 LK_UNLCK Unlocks the specified bytes, which must have been
358 previously locked.
359
360 Regions should be locked only briefly and should be unlocked
361 before closing a file or exiting the program.
362
363 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp
364 */
365 int lkmode;
366 switch (*mode) {
367 case 'r':
368 lkmode = LK_NBLCK;
369 break;
370 case 'w':
371 lkmode = LK_NBLCK;
372 break;
373 case 'u':
374 lkmode = LK_UNLCK;
375 break;
376 default:
377 return luaL_error(L, "%s: invalid mode", funcname);
378 }
379 if (!len) {
380 fseek(fh, 0L, SEEK_END);
381 len = ftell(fh);
382 }
383 fseek(fh, start, SEEK_SET);
384#ifdef __BORLANDC__
385 code = locking(fileno(fh), lkmode, len);
386#else
387 code = _locking(fileno(fh), lkmode, len);
388#endif
389#else
390 struct flock f;
391 switch (*mode) {
392 case 'w':
393 f.l_type = F_WRLCK;
394 break;
395 case 'r':
396 f.l_type = F_RDLCK;
397 break;
398 case 'u':
399 f.l_type = F_UNLCK;
400 break;
401 default:
402 return luaL_error(L, "%s: invalid mode", funcname);
403 }
404 f.l_whence = SEEK_SET;
405 f.l_start = (off_t) start;
406 f.l_len = (off_t) len;
407 code = fcntl(fileno(fh), F_SETLK, &f);
408#endif
409 return (code != -1);
410}
411
412#ifdef _WIN32
413typedef struct lfs_Lock {
414 HANDLE fd;
415} lfs_Lock;
416static int lfs_lock_dir(lua_State * L)
417{
418 size_t pathl;
419 HANDLE fd;
420 lfs_Lock *lock;
421 char *ln;
422 const char *lockfile = "/lockfile.lfs";
423 const char *path = luaL_checklstring(L, 1, &pathl);
424 ln = (char *) malloc(pathl + strlen(lockfile) + 1);
425 if (!ln) {
426 lua_pushnil(L);
427 lua_pushstring(L, strerror(errno));
428 return 2;
429 }
430 strcpy(ln, path);
431 strcat(ln, lockfile);
432 fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
433 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL);
434 free(ln);
435 if (fd == INVALID_HANDLE_VALUE) {
436 return lfs_win32_pusherror(L);
437 }
438 lock = (lfs_Lock *) lua_newuserdata(L, sizeof(lfs_Lock));
439 lock->fd = fd;
440 luaL_getmetatable(L, LOCK_METATABLE);
441 lua_setmetatable(L, -2);
442 return 1;
443}
444
445static int lfs_unlock_dir(lua_State * L)
446{
447 lfs_Lock *lock = (lfs_Lock *) luaL_checkudata(L, 1, LOCK_METATABLE);
448 if (lock->fd != INVALID_HANDLE_VALUE) {
449 CloseHandle(lock->fd);
450 lock->fd = INVALID_HANDLE_VALUE;
451 }
452 return 0;
453}
454#else
455typedef struct lfs_Lock {
456 char *ln;
457} lfs_Lock;
458static int lfs_lock_dir(lua_State * L)
459{
460 lfs_Lock *lock;
461 size_t pathl;
462 char *ln;
463 const char *lockfile = "/lockfile.lfs";
464 const char *path = luaL_checklstring(L, 1, &pathl);
465 lock = (lfs_Lock *) lua_newuserdata(L, sizeof(lfs_Lock));
466 ln = (char *) malloc(pathl + strlen(lockfile) + 1);
467 if (!ln) {
468 lua_pushnil(L);
469 lua_pushstring(L, strerror(errno));
470 return 2;
471 }
472 strcpy(ln, path);
473 strcat(ln, lockfile);
474 if (symlink("lock", ln) == -1) {
475 free(ln);
476 lua_pushnil(L);
477 lua_pushstring(L, strerror(errno));
478 return 2;
479 }
480 lock->ln = ln;
481 luaL_getmetatable(L, LOCK_METATABLE);
482 lua_setmetatable(L, -2);
483 return 1;
484}
485
486static int lfs_unlock_dir(lua_State * L)
487{
488 lfs_Lock *lock = (lfs_Lock *) luaL_checkudata(L, 1, LOCK_METATABLE);
489 if (lock->ln) {
490 unlink(lock->ln);
491 free(lock->ln);
492 lock->ln = NULL;
493 }
494 return 0;
495}
496#endif
497
498static int lfs_g_setmode(lua_State * L, FILE * f, int arg)
499{
500 static const int mode[] = { _O_BINARY, _O_TEXT };
501 static const char *const modenames[] = { "binary", "text", NULL };
502 int op = luaL_checkoption(L, arg, NULL, modenames);
503 int res = lfs_setmode(f, mode[op]);
504 if (res != -1) {
505 int i;
506 lua_pushboolean(L, 1);
507 for (i = 0; modenames[i] != NULL; i++) {
508 if (mode[i] == res) {
509 lua_pushstring(L, modenames[i]);
510 return 2;
511 }
512 }
513 lua_pushnil(L);
514 return 2;
515 } else {
516 return pusherror(L, NULL);
517 }
518}
519
520static int lfs_f_setmode(lua_State * L)
521{
522 return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2);
523}
524
525/*
526** Locks a file.
527** @param #1 File handle.
528** @param #2 String with lock mode ('w'rite, 'r'ead).
529** @param #3 Number with start position (optional).
530** @param #4 Number with length (optional).
531*/
532static int file_lock(lua_State * L)
533{
534 FILE *fh = check_file(L, 1, "lock");
535 const char *mode = luaL_checkstring(L, 2);
536 const long start = (long) luaL_optinteger(L, 3, 0);
537 long len = (long) luaL_optinteger(L, 4, 0);
538 if (_file_lock(L, fh, mode, start, len, "lock")) {
539 lua_pushboolean(L, 1);
540 return 1;
541 } else {
542 lua_pushnil(L);
543 lua_pushfstring(L, "%s", strerror(errno));
544 return 2;
545 }
546}
547
548
549/*
550** Unlocks a file.
551** @param #1 File handle.
552** @param #2 Number with start position (optional).
553** @param #3 Number with length (optional).
554*/
555static int file_unlock(lua_State * L)
556{
557 FILE *fh = check_file(L, 1, "unlock");
558 const long start = (long) luaL_optinteger(L, 2, 0);
559 long len = (long) luaL_optinteger(L, 3, 0);
560 if (_file_lock(L, fh, "u", start, len, "unlock")) {
561 lua_pushboolean(L, 1);
562 return 1;
563 } else {
564 lua_pushnil(L);
565 lua_pushfstring(L, "%s", strerror(errno));
566 return 2;
567 }
568}
569
570
571/*
572** Creates a link.
573** @param #1 Object to link to.
574** @param #2 Name of link.
575** @param #3 True if link is symbolic (optional).
576*/
577static int make_link(lua_State * L)
578{
579 const char *oldpath = luaL_checkstring(L, 1);
580 const char *newpath = luaL_checkstring(L, 2);
581#ifndef _WIN32
582 return pushresult(L,
583 (lua_toboolean(L, 3) ? symlink : link) (oldpath,
584 newpath),
585 NULL);
586#else
587 int symbolic = lua_toboolean(L, 3);
588 STAT_STRUCT oldpathinfo;
589 int is_dir = 0;
590 if (STAT_FUNC(oldpath, &oldpathinfo) == 0) {
591 is_dir = S_ISDIR(oldpathinfo.st_mode) != 0;
592 }
593 if (!symbolic && is_dir) {
594 lua_pushnil(L);
595 lua_pushstring(L,
596 "hard links to directories are not supported on Windows");
597 return 2;
598 }
599
600 int result = symbolic ? CreateSymbolicLink(newpath, oldpath, is_dir)
601 : CreateHardLink(newpath, oldpath, NULL);
602
603 if (result) {
604 return pushresult(L, result, NULL);
605 } else {
606 lua_pushnil(L);
607 lua_pushstring(L, symbolic ? "make_link CreateSymbolicLink() failed"
608 : "make_link CreateHardLink() failed");
609 return 2;
610 }
611#endif
612}
613
614
615/*
616** Creates a directory.
617** @param #1 Directory path.
618*/
619static int make_dir(lua_State * L)
620{
621 const char *path = luaL_checkstring(L, 1);
622 return pushresult(L, lfs_mkdir(path), NULL);
623}
624
625
626/*
627** Removes a directory.
628** @param #1 Directory path.
629*/
630static int remove_dir(lua_State * L)
631{
632 const char *path = luaL_checkstring(L, 1);
633 return pushresult(L, rmdir(path), NULL);
634}
635
636
637/*
638** Directory iterator
639*/
640static int dir_iter(lua_State * L)
641{
642#ifdef _WIN32
643 struct _finddata_t c_file;
644#else
645 struct dirent *entry;
646#endif
647 dir_data *d = (dir_data *) luaL_checkudata(L, 1, DIR_METATABLE);
648 luaL_argcheck(L, d->closed == 0, 1, "closed directory");
649#ifdef _WIN32
650 if (d->hFile == 0L) { /* first entry */
651 if ((d->hFile = _findfirst(d->pattern, &c_file)) == -1L) {
652 lua_pushnil(L);
653 lua_pushstring(L, strerror(errno));
654 d->closed = 1;
655 return 2;
656 } else {
657 lua_pushstring(L, c_file.name);
658 return 1;
659 }
660 } else { /* next entry */
661 if (_findnext(d->hFile, &c_file) == -1L) {
662 /* no more entries => close directory */
663 _findclose(d->hFile);
664 d->closed = 1;
665 return 0;
666 } else {
667 lua_pushstring(L, c_file.name);
668 return 1;
669 }
670 }
671#else
672 if ((entry = readdir(d->dir)) != NULL) {
673 lua_pushstring(L, entry->d_name);
674 return 1;
675 } else {
676 /* no more entries => close directory */
677 closedir(d->dir);
678 d->closed = 1;
679 return 0;
680 }
681#endif
682}
683
684
685/*
686** Closes directory iterators
687*/
688static int dir_close(lua_State * L)
689{
690 dir_data *d = (dir_data *) lua_touserdata(L, 1);
691#ifdef _WIN32
692 if (!d->closed && d->hFile) {
693 _findclose(d->hFile);
694 }
695#else
696 if (!d->closed && d->dir) {
697 closedir(d->dir);
698 }
699#endif
700 d->closed = 1;
701 return 0;
702}
703
704
705/*
706** Factory of directory iterators
707*/
708static int dir_iter_factory(lua_State * L)
709{
710 const char *path = luaL_checkstring(L, 1);
711 dir_data *d;
712 lua_pushcfunction(L, dir_iter);
713 d = (dir_data *) lua_newuserdata(L, sizeof(dir_data));
714 luaL_getmetatable(L, DIR_METATABLE);
715 lua_setmetatable(L, -2);
716 d->closed = 0;
717#ifdef _WIN32
718 d->hFile = 0L;
719 if (strlen(path) > MAX_PATH - 2)
720 luaL_error(L, "path too long: %s", path);
721 else
722 sprintf(d->pattern, "%s/*", path);
723#else
724 d->dir = opendir(path);
725 if (d->dir == NULL)
726 luaL_error(L, "cannot open %s: %s", path, strerror(errno));
727#endif
728#if LUA_VERSION_NUM >= 504
729 lua_pushnil(L);
730 lua_pushvalue(L, -2);
731 return 4;
732#else
733 return 2;
734#endif
735}
736
737
738/*
739** Creates directory metatable.
740*/
741static int dir_create_meta(lua_State * L)
742{
743 luaL_newmetatable(L, DIR_METATABLE);
744
745 /* Method table */
746 lua_newtable(L);
747 lua_pushcfunction(L, dir_iter);
748 lua_setfield(L, -2, "next");
749 lua_pushcfunction(L, dir_close);
750 lua_setfield(L, -2, "close");
751
752 /* Metamethods */
753 lua_setfield(L, -2, "__index");
754 lua_pushcfunction(L, dir_close);
755 lua_setfield(L, -2, "__gc");
756
757#if LUA_VERSION_NUM >= 504
758 lua_pushcfunction(L, dir_close);
759 lua_setfield(L, -2, "__close");
760#endif
761 return 1;
762}
763
764
765/*
766** Creates lock metatable.
767*/
768static int lock_create_meta(lua_State * L)
769{
770 luaL_newmetatable(L, LOCK_METATABLE);
771
772 /* Method table */
773 lua_newtable(L);
774 lua_pushcfunction(L, lfs_unlock_dir);
775 lua_setfield(L, -2, "free");
776
777 /* Metamethods */
778 lua_setfield(L, -2, "__index");
779 lua_pushcfunction(L, lfs_unlock_dir);
780 lua_setfield(L, -2, "__gc");
781 return 1;
782}
783
784
785/*
786** Convert the inode protection mode to a string.
787*/
788#ifdef _WIN32
789static const char *mode2string(unsigned short mode)
790{
791#else
792static const char *mode2string(mode_t mode)
793{
794#endif
795 if (S_ISREG(mode))
796 return "file";
797 else if (S_ISDIR(mode))
798 return "directory";
799 else if (S_ISLNK(mode))
800 return "link";
801 else if (S_ISSOCK(mode))
802 return "socket";
803 else if (S_ISFIFO(mode))
804 return "named pipe";
805 else if (S_ISCHR(mode))
806 return "char device";
807 else if (S_ISBLK(mode))
808 return "block device";
809 else
810 return "other";
811}
812
813
814/*
815** Set access time and modification values for a file.
816** @param #1 File path.
817** @param #2 Access time in seconds, current time is used if missing.
818** @param #3 Modification time in seconds, access time is used if missing.
819*/
820static int file_utime(lua_State * L)
821{
822 const char *file = luaL_checkstring(L, 1);
823 struct utimbuf utb, *buf;
824
825 if (lua_gettop(L) == 1) /* set to current date/time */
826 buf = NULL;
827 else {
828 utb.actime = (time_t) luaL_optnumber(L, 2, 0);
829 utb.modtime = (time_t) luaL_optinteger(L, 3, utb.actime);
830 buf = &utb;
831 }
832
833 return pushresult(L, utime(file, buf), NULL);
834}
835
836
837/* inode protection mode */
838static void push_st_mode(lua_State * L, STAT_STRUCT * info)
839{
840 lua_pushstring(L, mode2string(info->st_mode));
841}
842
843/* device inode resides on */
844static void push_st_dev(lua_State * L, STAT_STRUCT * info)
845{
846 lua_pushinteger(L, (lua_Integer) info->st_dev);
847}
848
849/* inode's number */
850static void push_st_ino(lua_State * L, STAT_STRUCT * info)
851{
852 lua_pushinteger(L, (lua_Integer) info->st_ino);
853}
854
855/* number of hard links to the file */
856static void push_st_nlink(lua_State * L, STAT_STRUCT * info)
857{
858 lua_pushinteger(L, (lua_Integer) info->st_nlink);
859}
860
861/* user-id of owner */
862static void push_st_uid(lua_State * L, STAT_STRUCT * info)
863{
864 lua_pushinteger(L, (lua_Integer) info->st_uid);
865}
866
867/* group-id of owner */
868static void push_st_gid(lua_State * L, STAT_STRUCT * info)
869{
870 lua_pushinteger(L, (lua_Integer) info->st_gid);
871}
872
873/* device type, for special file inode */
874static void push_st_rdev(lua_State * L, STAT_STRUCT * info)
875{
876 lua_pushinteger(L, (lua_Integer) info->st_rdev);
877}
878
879/* time of last access */
880static void push_st_atime(lua_State * L, STAT_STRUCT * info)
881{
882 lua_pushinteger(L, (lua_Integer) info->st_atime);
883}
884
885/* time of last data modification */
886static void push_st_mtime(lua_State * L, STAT_STRUCT * info)
887{
888 lua_pushinteger(L, (lua_Integer) info->st_mtime);
889}
890
891/* time of last file status change */
892static void push_st_ctime(lua_State * L, STAT_STRUCT * info)
893{
894 lua_pushinteger(L, (lua_Integer) info->st_ctime);
895}
896
897/* file size, in bytes */
898static void push_st_size(lua_State * L, STAT_STRUCT * info)
899{
900 lua_pushinteger(L, (lua_Integer) info->st_size);
901}
902
903#ifndef _WIN32
904/* blocks allocated for file */
905static void push_st_blocks(lua_State * L, STAT_STRUCT * info)
906{
907 lua_pushinteger(L, (lua_Integer) info->st_blocks);
908}
909
910/* optimal file system I/O blocksize */
911static void push_st_blksize(lua_State * L, STAT_STRUCT * info)
912{
913 lua_pushinteger(L, (lua_Integer) info->st_blksize);
914}
915#endif
916
917 /*
918 ** Convert the inode protection mode to a permission list.
919 */
920
921#ifdef _WIN32
922static const char *perm2string(unsigned short mode)
923{
924 static char perms[10] = "---------";
925 int i;
926 for (i = 0; i < 9; i++)
927 perms[i] = '-';
928 if (mode & _S_IREAD) {
929 perms[0] = 'r';
930 perms[3] = 'r';
931 perms[6] = 'r';
932 }
933 if (mode & _S_IWRITE) {
934 perms[1] = 'w';
935 perms[4] = 'w';
936 perms[7] = 'w';
937 }
938 if (mode & _S_IEXEC) {
939 perms[2] = 'x';
940 perms[5] = 'x';
941 perms[8] = 'x';
942 }
943 return perms;
944}
945#else
946static const char *perm2string(mode_t mode)
947{
948 static char perms[10] = "---------";
949 int i;
950 for (i = 0; i < 9; i++)
951 perms[i] = '-';
952 if (mode & S_IRUSR)
953 perms[0] = 'r';
954 if (mode & S_IWUSR)
955 perms[1] = 'w';
956 if (mode & S_IXUSR)
957 perms[2] = 'x';
958 if (mode & S_IRGRP)
959 perms[3] = 'r';
960 if (mode & S_IWGRP)
961 perms[4] = 'w';
962 if (mode & S_IXGRP)
963 perms[5] = 'x';
964 if (mode & S_IROTH)
965 perms[6] = 'r';
966 if (mode & S_IWOTH)
967 perms[7] = 'w';
968 if (mode & S_IXOTH)
969 perms[8] = 'x';
970 return perms;
971}
972#endif
973
974/* permssions string */
975static void push_st_perm(lua_State * L, STAT_STRUCT * info)
976{
977 lua_pushstring(L, perm2string(info->st_mode));
978}
979
980typedef void (*_push_function)(lua_State * L, STAT_STRUCT * info);
981
982struct _stat_members {
983 const char *name;
984 _push_function push;
985};
986
987struct _stat_members members[] = {
988 { "mode", push_st_mode },
989 { "dev", push_st_dev },
990 { "ino", push_st_ino },
991 { "nlink", push_st_nlink },
992 { "uid", push_st_uid },
993 { "gid", push_st_gid },
994 { "rdev", push_st_rdev },
995 { "access", push_st_atime },
996 { "modification", push_st_mtime },
997 { "change", push_st_ctime },
998 { "size", push_st_size },
999 { "permissions", push_st_perm },
1000#ifndef _WIN32
1001 { "blocks", push_st_blocks },
1002 { "blksize", push_st_blksize },
1003#endif
1004 { NULL, NULL }
1005};
1006
1007/*
1008** Get file or symbolic link information
1009*/
1010static int _file_info_(lua_State * L,
1011 int (*st)(const char *, STAT_STRUCT *))
1012{
1013 STAT_STRUCT info;
1014 const char *file = luaL_checkstring(L, 1);
1015 int i;
1016
1017 if (st(file, &info)) {
1018 lua_pushnil(L);
1019 lua_pushfstring(L, "cannot obtain information from file '%s': %s",
1020 file, strerror(errno));
1021 lua_pushinteger(L, errno);
1022 return 3;
1023 }
1024 if (lua_isstring(L, 2)) {
1025 const char *member = lua_tostring(L, 2);
1026 for (i = 0; members[i].name; i++) {
1027 if (strcmp(members[i].name, member) == 0) {
1028 /* push member value and return */
1029 members[i].push(L, &info);
1030 return 1;
1031 }
1032 }
1033 /* member not found */
1034 return luaL_error(L, "invalid attribute name '%s'", member);
1035 }
1036 /* creates a table if none is given, removes extra arguments */
1037 lua_settop(L, 2);
1038 if (!lua_istable(L, 2)) {
1039 lua_newtable(L);
1040 }
1041 /* stores all members in table on top of the stack */
1042 for (i = 0; members[i].name; i++) {
1043 lua_pushstring(L, members[i].name);
1044 members[i].push(L, &info);
1045 lua_rawset(L, -3);
1046 }
1047 return 1;
1048}
1049
1050
1051/*
1052** Get file information using stat.
1053*/
1054static int file_info(lua_State * L)
1055{
1056 return _file_info_(L, STAT_FUNC);
1057}
1058
1059
1060/*
1061** Push the symlink target to the top of the stack.
1062** Assumes the file name is at position 1 of the stack.
1063** Returns 1 if successful (with the target on top of the stack),
1064** 0 on failure (with stack unchanged, and errno set).
1065*/
1066static int push_link_target(lua_State * L)
1067{
1068 const char *file = luaL_checkstring(L, 1);
1069#ifdef _WIN32
1070 HANDLE h = CreateFile(file, GENERIC_READ,
1071 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
1072 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1073 if (h == INVALID_HANDLE_VALUE) {
1074 return lfs_win32_pusherror(L);
1075 }
1076#endif
1077 char *target = NULL;
1078 int tsize, size = 256; /* size = initial buffer capacity */
1079 int ok = 0;
1080 while (!ok) {
1081 char *target2 = realloc(target, size);
1082 if (!target2) { /* failed to allocate */
1083 break;
1084 }
1085 target = target2;
1086#ifdef _WIN32
1087 tsize = GetFinalPathNameByHandle(h, target, size, FILE_NAME_OPENED);
1088#else
1089 tsize = readlink(file, target, size);
1090#endif
1091 if (tsize < 0) { /* a readlink() error occurred */
1092 break;
1093 }
1094 if (tsize < size) {
1095#ifdef _WIN32
1096 if (tsize > 4 && strncmp(target, "\\\\?\\", 4) == 0) {
1097 memmove_s(target, tsize - 3, target + 4, tsize - 3);
1098 tsize -= 4;
1099 }
1100#endif
1101 ok = 1;
1102 break;
1103 }
1104 /* possibly truncated readlink() result, double size and retry */
1105 size *= 2;
1106 }
1107 if (ok) {
1108 target[tsize] = '\0';
1109 lua_pushlstring(L, target, tsize);
1110 }
1111#ifdef _WIN32
1112 CloseHandle(h);
1113#endif
1114 free(target);
1115 return ok;
1116}
1117
1118/*
1119** Get symbolic link information using lstat.
1120*/
1121static int link_info(lua_State * L)
1122{
1123 int ret;
1124 if (lua_isstring(L, 2) && (strcmp(lua_tostring(L, 2), "target") == 0)) {
1125 int ok = push_link_target(L);
1126 return ok ? 1 : pusherror(L, "could not obtain link target");
1127 }
1128 ret = _file_info_(L, LSTAT_FUNC);
1129 if (ret == 1 && lua_type(L, -1) == LUA_TTABLE) {
1130 int ok = push_link_target(L);
1131 if (ok) {
1132 lua_setfield(L, -2, "target");
1133 }
1134 }
1135 return ret;
1136}
1137
1138
1139/*
1140** Assumes the table is on top of the stack.
1141*/
1142static void set_info(lua_State * L)
1143{
1144 lua_pushliteral(L, "Copyright (C) 2003-2017 Kepler Project");
1145 lua_setfield(L, -2, "_COPYRIGHT");
1146 lua_pushliteral(L,
1147 "LuaFileSystem is a Lua library developed to complement "
1148 "the set of functions related to file systems offered by "
1149 "the standard Lua distribution");
1150 lua_setfield(L, -2, "_DESCRIPTION");
1151 lua_pushliteral(L, "LuaFileSystem " LFS_VERSION);
1152 lua_setfield(L, -2, "_VERSION");
1153}
1154
1155
1156static const struct luaL_Reg fslib[] = {
1157 { "attributes", file_info },
1158 { "chdir", change_dir },
1159 { "currentdir", get_dir },
1160 { "dir", dir_iter_factory },
1161 { "link", make_link },
1162 { "lock", file_lock },
1163 { "mkdir", make_dir },
1164 { "rmdir", remove_dir },
1165 { "symlinkattributes", link_info },
1166 { "setmode", lfs_f_setmode },
1167 { "touch", file_utime },
1168 { "unlock", file_unlock },
1169 { "lock_dir", lfs_lock_dir },
1170 { NULL, NULL },
1171};
1172
1173LFS_EXPORT int luaopen_lfs(lua_State * L)
1174{
1175 dir_create_meta(L);
1176 lock_create_meta(L);
1177 new_lib(L, fslib);
1178 lua_pushvalue(L, -1);
1179 lua_setglobal(L, LFS_LIBNAME);
1180 set_info(L);
1181 return 1;
1182}
diff --git a/vendor/luafilesystem/src/lfs.def b/vendor/luafilesystem/src/lfs.def
new file mode 100644
index 00000000..bd8c847a
--- /dev/null
+++ b/vendor/luafilesystem/src/lfs.def
@@ -0,0 +1,4 @@
1LIBRARY lfs.dll
2VERSION 1.8
3EXPORTS
4luaopen_lfs
diff --git a/vendor/luafilesystem/src/lfs.h b/vendor/luafilesystem/src/lfs.h
new file mode 100644
index 00000000..13b60a91
--- /dev/null
+++ b/vendor/luafilesystem/src/lfs.h
@@ -0,0 +1,35 @@
1/*
2** LuaFileSystem
3** Copyright Kepler Project 2003 - 2020
4** (http://keplerproject.github.io/luafilesystem)
5*/
6
7/* Define 'chdir' for systems that do not implement it */
8#ifdef NO_CHDIR
9#define chdir(p) (-1)
10#define chdir_error "Function 'chdir' not provided by system"
11#else
12#define chdir_error strerror(errno)
13#endif
14
15#ifdef _WIN32
16#define chdir(p) (_chdir(p))
17#define getcwd(d, s) (_getcwd(d, s))
18#define rmdir(p) (_rmdir(p))
19#define LFS_EXPORT __declspec (dllexport)
20#ifndef fileno
21#define fileno(f) (_fileno(f))
22#endif
23#else
24#define LFS_EXPORT
25#endif
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31 LFS_EXPORT int luaopen_lfs(lua_State * L);
32
33#ifdef __cplusplus
34}
35#endif
diff --git a/vendor/luasec/.gitignore b/vendor/luasec/.gitignore
new file mode 100644
index 00000000..355518b2
--- /dev/null
+++ b/vendor/luasec/.gitignore
@@ -0,0 +1,3 @@
1/src/*.o
2/src/luasocket/*.o
3/*.dll
diff --git a/vendor/luasec/CHANGELOG b/vendor/luasec/CHANGELOG
new file mode 100644
index 00000000..f7c0a780
--- /dev/null
+++ b/vendor/luasec/CHANGELOG
@@ -0,0 +1,257 @@
1--------------------------------------------------------------------------------
2LuaSec 1.3.2
3---------------
4This version includes:
5
6* Fix: place EAI_OVERFLOW inside macro, unbreak build on <10.7 (Sergey Fedorov)
7* Fix: Expand workaround for zero errno to OpenSSL 3.0.x (Kim Alvefur)
8* Fix: reset block timeout at send or receive (MartinDahlberg)
9
10--------------------------------------------------------------------------------
11LuaSec 1.3.1
12---------------
13This version includes:
14
15* Fix: check if PSK is available
16
17--------------------------------------------------------------------------------
18LuaSec 1.3.0
19---------------
20This version includes:
21
22* Add :getlocalchain() + :getlocalcertificate() to mirror the peer methods (@mwild1)
23* Add Pre-Shared Key (PSK) support (@jclab-joseph)
24
25--------------------------------------------------------------------------------
26LuaSec 1.2.0
27---------------
28This version includes:
29
30* Add key material export method
31* Backguard compat for openssl on providers, like LTS linuxes
32
33--------------------------------------------------------------------------------
34LuaSec 1.1.0
35---------------
36This version includes:
37
38* Fix missing DANE flag
39* Remove unused parameter in https.lua
40
41--------------------------------------------------------------------------------
42LuaSec 1.0.2
43---------------
44This version includes:
45
46* Fix handle SSL_send SYSCALL error without errno
47* Fix off by one in cert:validat(notafter)
48* Fix meth_get_{sinagure => signature}_name function name
49* Fix update the Lua state reference on the selected SSL context after SNI
50* Fix ignore SSL_OP_BIT(n) macro and update option.c
51
52--------------------------------------------------------------------------------
53LuaSec 1.0.1
54---------------
55This version includes:
56
57
58* Fix luaL_buffinit() can use the stack and broke buffer_meth_receive()
59
60--------------------------------------------------------------------------------
61LuaSec 1.0
62---------------
63This version includes:
64
65
66* Add cert:getsignaturename()
67
68--------------------------------------------------------------------------------
69LuaSec 0.9
70---------------
71This version includes:
72
73
74* Add DNS-based Authentication of Named Entities (DANE) support
75* Add __close() metamethod
76* Fix deprecation warnings with OpenSSL 1.1
77* Fix special case listing of TLS 1.3 EC curves
78* Fix general_name leak in cert:extensions()
79* Fix unexported 'ssl.config' table
80* Replace $(LD) with $(CCLD) variable
81* Remove multiple definitions of 'ssl_options' variable
82* Use tag in git format: v0.9
83
84--------------------------------------------------------------------------------
85LuaSec 0.8.2
86---------------
87This version includes:
88
89* Fix unexported 'ssl.config' table (backported)
90
91--------------------------------------------------------------------------------
92LuaSec 0.8.1
93---------------
94This version includes:
95
96* Fix general_name leak in cert:extensions() (backported)
97
98--------------------------------------------------------------------------------
99LuaSec 0.8
100---------------
101This version includes:
102
103* Add support to ALPN
104* Add support to TLS 1.3
105* Add support to multiple certificates
106* Add timeout to https module (https.TIMEOUT)
107* Drop support to SSL 3.0
108* Drop support to TLS 1.0 from https module
109* Fix invalid reference to Lua state
110* Fix memory leak when get certficate extensions
111
112--------------------------------------------------------------------------------
113LuaSec 0.7.2
114---------------
115This version includes:
116
117* Fix unexported 'ssl.config' table (backported)
118
119--------------------------------------------------------------------------------
120LuaSec 0.7.1
121---------------
122This version includes:
123
124* Fix general_name leak in cert:extensions() (backported)
125
126--------------------------------------------------------------------------------
127LuaSec 0.7
128---------------
129LuaSec depends on OpenSSL, and integrates with LuaSocket to make it
130easy to add secure connections to any Lua applications or scripts.
131
132Documentation: https://github.com/brunoos/luasec/wiki
133
134This version includes:
135
136* Add support to OpenSSL 1.1.0
137* Add support to elliptic curves list
138* Add ssl.config that exports some OpenSSL information
139* Add integration with luaossl
140
141--------------------------------------------------------------------------------
142LuaSec 0.6
143------------
144LuaSec depends on OpenSSL, and integrates with LuaSocket to make it
145easy to add secure connections to any Lua applications or scripts.
146
147Documentation: https://github.com/brunoos/luasec/wiki
148
149This version includes:
150
151* Lua 5.2 and 5.3 compatibility
152
153* Context module:
154 - Add ctx:checkkey()
155
156* SSL module:
157 - Add conn:sni() and conn:getsniname()
158
159* Context options:
160 - Add "any" protocol ("sslv23" is deprecated)
161
162* HTTPS module:
163 - Using "any" protocol without SSLv2/SSLv3, by default
164
165* X509 module:
166 - Human readable IP address
167 - Add cert:issued()
168 - Add cert:pubkey()
169
170* Some bug fixes
171
172
173=> Thanks to everyone who collaborate with LuaSec <=
174
175--------------------------------------------------------------------------------
176LuaSec 0.5
177------------
178LuaSec depends on OpenSSL, and integrates with LuaSocket to make it
179easy to add secure connections to any Lua applications or scripts.
180
181This version includes:
182
183 * A new certificate (X509) API, which supports:
184 - Reading the subject (identity) and issuer of the certificate.
185 - Reading various X509 extensions, including email and dnsName.
186 - Converting certificates to and from the standard ASCII PEM
187 format.
188 - Generating the fingerprint/digest of a certificate (using SHA1,
189 SHA256 or SHA512).
190 - Reading the certificate's expiration, serial number, and other
191 info.
192
193 * The ability to get more detailed information from OpenSSL about
194 why a certificate failed verification, for each certificate in the
195 chain.
196
197 * Flags to force acceptance of invalid certificates, e.g. to allow
198 the use of self-signed certificates in a Trust On First Use model.
199
200 * Flags to control checking CRLs for certificate revocation status.
201
202 * Support for ECDH cipher suites.
203
204 * An API to get the TLS 'finished' messages used for SASL channel
205 binding (e.g. the SCRAM PLUS mechanisms).
206
207The work in this release was undertaken by Kim Alvefur, Paul Aurich,
208Tobias Markmann, Bruno Silvestre and Matthew Wild.
209
210--------------------------------------------------------------------------------
211LuaSec 0.4.1
212------------
213- SSL options updated --- based on OpenSSL 1.0.0d.
214- Activate SSL_MODE_RELEASE_BUFFERS by default if it is available.
215 (thanks Prosody project)
216
217---------------------------------------------------------------------------------
218LuaSec 0.4
219------------
220- Add option 'no_ticket' (included in OpenSSL 0.9.8f).
221- Add HTTPS module. (thanks Tomas Guisasola and Pablo Musa)
222
223--------------------------------------------------------------------------------
224LuaSec 0.3.3
225------------
226- BUG: Clear the error queue before call I/O functions (see SSL_get_error
227 manual).
228 (thanks Matthew Wild)
229
230--------------------------------------------------------------------------------
231LuaSec 0.3.2
232------------
233- BUG: Windows uses a different way to report socket error.
234 (thanks Sebastien Perin)
235
236--------------------------------------------------------------------------------
237LuaSec 0.3.1
238------------
239- BUG: receive("a") returns 'closed' error instead of the content when the
240 SSL/TLS connection is shut down cleanly. (thanks Matthias Diener)
241
242--------------------------------------------------------------------------------
243LuaSec 0.3
244----------
245- Add functions ssl.rawcontext() and ssl.rawconnection()
246- Add support to encrypted key password. (thanks Norbert Kiesel)
247
248--------------------------------------------------------------------------------
249LuaSec 0.2.1
250------------
251- 'key' and 'certificate' configurations become optional. (thanks René Rebe)
252- Add '_VERSION' variable to module.
253
254--------------------------------------------------------------------------------
255LuaSec 0.2
256----------
257Initial version
diff --git a/vendor/luasec/INSTALL b/vendor/luasec/INSTALL
new file mode 100644
index 00000000..07b94df8
--- /dev/null
+++ b/vendor/luasec/INSTALL
@@ -0,0 +1,39 @@
1LuaSec 1.3.2
2------------
3
4* OpenSSL options:
5
6 By default, this version includes options for OpenSSL 3.0.8
7
8 If you need to generate the options for a different version of OpenSSL:
9
10 $ cd src
11 $ lua options.lua -g /usr/include/openssl/ssl.h > options.c
12
13--------------------------------------------------------------------------------
14
15* On Linux, BSD, and Mac OS X:
16
17 - Edit 'Makefile'
18 * Inform the path to where install the Lua modules (LUAPATH) and binaries
19 modules (LUACPATH)
20 * If Lua or OpenSSL are not in the default path, set the
21 variables INCDIR and LIBDIR.
22 * For Mac OS X, set the variable MACOSX_VERSION.
23
24 - Use 'make <platform>' to compile
25 * Platforms: linux, bsd, or macosx
26
27 - Use 'make install' to install the modules.
28
29--------------------------------------------------------------------------------
30
31* On Windows:
32
33 - Use the Visual C++ project to compile the library.
34
35 - Copy the 'ssl.lua' file to some place in your LUA_PATH.
36
37 - Copy the 'ssl.dll' file to some place in your LUA_CPATH.
38
39 - Create a directory 'ssl' in your LUA_PATH and copy 'https.lua' to it.
diff --git a/vendor/luasec/LICENSE b/vendor/luasec/LICENSE
new file mode 100644
index 00000000..09df9964
--- /dev/null
+++ b/vendor/luasec/LICENSE
@@ -0,0 +1,21 @@
1LuaSec 1.3.2 license
2Copyright (C) 2006-2023 Bruno Silvestre, UFG
3
4Permission is hereby granted, free of charge, to any person obtaining
5a copy of this software and associated documentation files (the
6"Software"), to deal in the Software without restriction, including
7without limitation the rights to use, copy, modify, merge, publish,
8distribute, sublicense, and/or sell copies of the Software, and to
9permit persons to whom the Software is furnished to do so, subject to
10the following conditions:
11
12The above copyright notice and this permission notice shall be
13included in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/luasec/README.md b/vendor/luasec/README.md
new file mode 100644
index 00000000..afdce4ee
--- /dev/null
+++ b/vendor/luasec/README.md
@@ -0,0 +1,6 @@
1LuaSec 1.3.2
2===============
3LuaSec depends on OpenSSL, and integrates with LuaSocket to make it
4easy to add secure connections to any Lua applications or scripts.
5
6Documentation: https://github.com/brunoos/luasec/wiki
diff --git a/vendor/luasec/luasec-1.3.2-1.rockspec b/vendor/luasec/luasec-1.3.2-1.rockspec
new file mode 100644
index 00000000..a6a36d78
--- /dev/null
+++ b/vendor/luasec/luasec-1.3.2-1.rockspec
@@ -0,0 +1,105 @@
1package = "LuaSec"
2version = "1.3.2-1"
3source = {
4 url = "git+https://github.com/brunoos/luasec",
5 tag = "v1.3.2",
6}
7description = {
8 summary = "A binding for OpenSSL library to provide TLS/SSL communication over LuaSocket.",
9 detailed = "This version delegates to LuaSocket the TCP connection establishment between the client and server. Then LuaSec uses this connection to start a secure TLS/SSL session.",
10 homepage = "https://github.com/brunoos/luasec/wiki",
11 license = "MIT"
12}
13dependencies = {
14 "lua >= 5.1", "luasocket"
15}
16external_dependencies = {
17 platforms = {
18 unix = {
19 OPENSSL = {
20 header = "openssl/ssl.h",
21 library = "ssl"
22 }
23 },
24 windows = {
25 OPENSSL = {
26 header = "openssl/ssl.h",
27 }
28 },
29 }
30}
31build = {
32 type = "builtin",
33 copy_directories = {
34 "samples"
35 },
36 platforms = {
37 unix = {
38 install = {
39 lib = {
40 "ssl.so"
41 },
42 lua = {
43 "src/ssl.lua", ['ssl.https'] = "src/https.lua"
44 }
45 },
46 modules = {
47 ssl = {
48 defines = {
49 "WITH_LUASOCKET", "LUASOCKET_DEBUG",
50 },
51 incdirs = {
52 "$(OPENSSL_INCDIR)", "src/", "src/luasocket",
53 },
54 libdirs = {
55 "$(OPENSSL_LIBDIR)"
56 },
57 libraries = {
58 "ssl", "crypto"
59 },
60 sources = {
61 "src/options.c", "src/config.c", "src/ec.c",
62 "src/x509.c", "src/context.c", "src/ssl.c",
63 "src/luasocket/buffer.c", "src/luasocket/io.c",
64 "src/luasocket/timeout.c", "src/luasocket/usocket.c"
65 }
66 }
67 }
68 },
69 windows = {
70 install = {
71 lib = {
72 "ssl.dll"
73 },
74 lua = {
75 "src/ssl.lua", ['ssl.https'] = "src/https.lua"
76 }
77 },
78 modules = {
79 ssl = {
80 defines = {
81 "WIN32", "NDEBUG", "_WINDOWS", "_USRDLL", "LSEC_EXPORTS", "BUFFER_DEBUG", "LSEC_API=__declspec(dllexport)",
82 "WITH_LUASOCKET", "LUASOCKET_DEBUG",
83 "LUASEC_INET_NTOP", "WINVER=0x0501", "_WIN32_WINNT=0x0501", "NTDDI_VERSION=0x05010300"
84 },
85 libdirs = {
86 "$(OPENSSL_LIBDIR)",
87 "$(OPENSSL_BINDIR)",
88 },
89 libraries = {
90 "libssl", "libcrypto", "ws2_32"
91 },
92 incdirs = {
93 "$(OPENSSL_INCDIR)", "src/", "src/luasocket"
94 },
95 sources = {
96 "src/options.c", "src/config.c", "src/ec.c",
97 "src/x509.c", "src/context.c", "src/ssl.c",
98 "src/luasocket/buffer.c", "src/luasocket/io.c",
99 "src/luasocket/timeout.c", "src/luasocket/wsocket.c"
100 }
101 }
102 }
103 }
104 }
105}
diff --git a/vendor/luasec/src/Makefile b/vendor/luasec/src/Makefile
new file mode 100644
index 00000000..9b06a038
--- /dev/null
+++ b/vendor/luasec/src/Makefile
@@ -0,0 +1,66 @@
1CMOD=ssl.so
2LMOD=ssl.lua
3
4OBJS= \
5 options.o \
6 x509.o \
7 context.o \
8 ssl.o \
9 config.o \
10 ec.o
11
12LIBS=-lssl -lcrypto -lluasocket
13
14WARN=-Wall -pedantic
15
16BSD_CFLAGS=-O2 -fPIC $(WARN) $(INCDIR) $(DEFS)
17BSD_LDFLAGS=-O -fPIC -shared $(LIBDIR)
18
19LNX_CFLAGS=-O2 -fPIC $(WARN) $(INCDIR) $(DEFS)
20LNX_LDFLAGS=-O -fPIC -shared $(LIBDIR)
21
22MAC_ENV=env MACOSX_DEPLOYMENT_TARGET='$(MACVER)'
23MAC_CFLAGS=-O2 -fno-common $(WARN) $(INCDIR) $(DEFS)
24MAC_LDFLAGS=-bundle -undefined dynamic_lookup $(LIBDIR)
25
26INSTALL = install
27CC ?= cc
28CCLD ?= $(MYENV) $(CC)
29CFLAGS += $(MYCFLAGS)
30LDFLAGS += $(MYLDFLAGS)
31
32.PHONY: all clean install none linux bsd macosx luasocket
33
34all:
35
36install: $(CMOD) $(LMOD)
37 $(INSTALL) -d $(DESTDIR)$(LUAPATH)/ssl $(DESTDIR)$(LUACPATH)
38 $(INSTALL) $(CMOD) $(DESTDIR)$(LUACPATH)
39 $(INSTALL) -m644 $(LMOD) $(DESTDIR)$(LUAPATH)
40 $(INSTALL) -m644 https.lua $(DESTDIR)$(LUAPATH)/ssl
41
42linux:
43 @$(MAKE) $(CMOD) MYCFLAGS="$(LNX_CFLAGS)" MYLDFLAGS="$(LNX_LDFLAGS)" EXTRA="$(EXTRA)"
44
45bsd:
46 @$(MAKE) $(CMOD) MYCFLAGS="$(BSD_CFLAGS)" MYLDFLAGS="$(BSD_LDFLAGS)" EXTRA="$(EXTRA)"
47
48macosx:
49 @$(MAKE) $(CMOD) MYCFLAGS="$(MAC_CFLAGS)" MYLDFLAGS="$(MAC_LDFLAGS)" MYENV="$(MAC_ENV)" EXTRA="$(EXTRA)"
50
51luasocket:
52 @cd luasocket && $(MAKE)
53
54$(CMOD): $(EXTRA) $(OBJS)
55 $(CCLD) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
56
57clean:
58 cd luasocket && $(MAKE) clean
59 rm -f $(OBJS) $(CMOD)
60
61options.o: options.h options.c
62ec.o: ec.c ec.h
63x509.o: x509.c x509.h compat.h
64context.o: context.c context.h ec.h compat.h options.h
65ssl.o: ssl.c ssl.h context.h x509.h compat.h
66config.o: config.c ec.h options.h compat.h
diff --git a/vendor/luasec/src/compat.h b/vendor/luasec/src/compat.h
new file mode 100644
index 00000000..9f97e2a6
--- /dev/null
+++ b/vendor/luasec/src/compat.h
@@ -0,0 +1,63 @@
1/*--------------------------------------------------------------------------
2 * LuaSec 1.3.2
3 *
4 * Copyright (C) 2006-2023 Bruno Silvestre
5 *
6 *--------------------------------------------------------------------------*/
7
8#ifndef LSEC_COMPAT_H
9#define LSEC_COMPAT_H
10
11#include <openssl/ssl.h>
12
13//------------------------------------------------------------------------------
14
15#if defined(_WIN32)
16#define LSEC_API __declspec(dllexport)
17#else
18#define LSEC_API extern
19#endif
20
21//------------------------------------------------------------------------------
22
23#if (LUA_VERSION_NUM == 501)
24
25#define luaL_testudata(L, ud, tname) lsec_testudata(L, ud, tname)
26#define setfuncs(L, R) luaL_register(L, NULL, R)
27#define lua_rawlen(L, i) lua_objlen(L, i)
28
29#ifndef luaL_newlib
30#define luaL_newlib(L, R) do { lua_newtable(L); luaL_register(L, NULL, R); } while(0)
31#endif
32
33#else
34#define setfuncs(L, R) luaL_setfuncs(L, R, 0)
35#endif
36
37//------------------------------------------------------------------------------
38
39#if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x1010000fL))
40#define LSEC_ENABLE_DANE
41#endif
42
43//------------------------------------------------------------------------------
44
45#if !((defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2070000fL)) || (OPENSSL_VERSION_NUMBER < 0x1010000fL))
46#define LSEC_API_OPENSSL_1_1_0
47#endif
48
49//------------------------------------------------------------------------------
50
51#if !defined(LIBRESSL_VERSION_NUMBER) && ((OPENSSL_VERSION_NUMBER & 0xFFFFF000L) == 0x10101000L || (OPENSSL_VERSION_NUMBER & 0xFFFFF000L) == 0x30000000L)
52#define LSEC_OPENSSL_ERRNO_BUG
53#endif
54
55//------------------------------------------------------------------------------
56
57#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_NO_PSK)
58#define LSEC_ENABLE_PSK
59#endif
60
61//------------------------------------------------------------------------------
62
63#endif
diff --git a/vendor/luasec/src/config.c b/vendor/luasec/src/config.c
new file mode 100644
index 00000000..5f0e2c60
--- /dev/null
+++ b/vendor/luasec/src/config.c
@@ -0,0 +1,108 @@
1/*--------------------------------------------------------------------------
2 * LuaSec 1.3.2
3 *
4 * Copyright (C) 2006-2023 Bruno Silvestre
5 *
6 *--------------------------------------------------------------------------*/
7
8#include "compat.h"
9#include "options.h"
10#include "ec.h"
11
12/**
13 * Registre the module.
14 */
15LSEC_API int luaopen_ssl_config(lua_State *L)
16{
17 lsec_ssl_option_t *opt;
18
19 lua_newtable(L);
20
21 // Options
22 lua_pushstring(L, "options");
23 lua_newtable(L);
24 for (opt = lsec_get_ssl_options(); opt->name; opt++) {
25 lua_pushstring(L, opt->name);
26 lua_pushboolean(L, 1);
27 lua_rawset(L, -3);
28 }
29 lua_rawset(L, -3);
30
31 // Protocols
32 lua_pushstring(L, "protocols");
33 lua_newtable(L);
34
35 lua_pushstring(L, "tlsv1");
36 lua_pushboolean(L, 1);
37 lua_rawset(L, -3);
38 lua_pushstring(L, "tlsv1_1");
39 lua_pushboolean(L, 1);
40 lua_rawset(L, -3);
41 lua_pushstring(L, "tlsv1_2");
42 lua_pushboolean(L, 1);
43 lua_rawset(L, -3);
44#ifdef TLS1_3_VERSION
45 lua_pushstring(L, "tlsv1_3");
46 lua_pushboolean(L, 1);
47 lua_rawset(L, -3);
48#endif
49
50 lua_rawset(L, -3);
51
52 // Algorithms
53 lua_pushstring(L, "algorithms");
54 lua_newtable(L);
55
56#ifndef OPENSSL_NO_EC
57 lua_pushstring(L, "ec");
58 lua_pushboolean(L, 1);
59 lua_rawset(L, -3);
60#endif
61 lua_rawset(L, -3);
62
63 // Curves
64 lua_pushstring(L, "curves");
65 lsec_get_curves(L);
66 lua_rawset(L, -3);
67
68 // Capabilities
69 lua_pushstring(L, "capabilities");
70 lua_newtable(L);
71
72 // ALPN
73 lua_pushstring(L, "alpn");
74 lua_pushboolean(L, 1);
75 lua_rawset(L, -3);
76
77#ifdef LSEC_ENABLE_PSK
78 lua_pushstring(L, "psk");
79 lua_pushboolean(L, 1);
80 lua_rawset(L, -3);
81#endif
82
83#ifdef LSEC_ENABLE_DANE
84 // DANE
85 lua_pushstring(L, "dane");
86#ifdef DANE_FLAG_NO_DANE_EE_NAMECHECKS
87 lua_createtable(L, 0, 1);
88 lua_pushstring(L, "no_ee_namechecks");
89 lua_pushboolean(L, 1);
90 lua_rawset(L, -3);
91#else
92 lua_pushboolean(L, 1);
93#endif
94 lua_rawset(L, -3);
95#endif
96
97#ifndef OPENSSL_NO_EC
98 lua_pushstring(L, "curves_list");
99 lua_pushboolean(L, 1);
100 lua_rawset(L, -3);
101 lua_pushstring(L, "ecdh_auto");
102 lua_pushboolean(L, 1);
103 lua_rawset(L, -3);
104#endif
105 lua_rawset(L, -3);
106
107 return 1;
108}
diff --git a/vendor/luasec/src/context.c b/vendor/luasec/src/context.c
new file mode 100644
index 00000000..881ebb90
--- /dev/null
+++ b/vendor/luasec/src/context.c
@@ -0,0 +1,1099 @@
1/*--------------------------------------------------------------------------
2 * LuaSec 1.3.2
3 *
4 * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild
5 * Copyright (C) 2006-2023 Bruno Silvestre
6 *
7 *--------------------------------------------------------------------------*/
8
9#include <string.h>
10
11#if defined(WIN32)
12#include <windows.h>
13#endif
14
15#include <openssl/ssl.h>
16#include <openssl/err.h>
17#include <openssl/x509.h>
18#include <openssl/x509v3.h>
19#include <openssl/x509_vfy.h>
20#include <openssl/dh.h>
21
22#include <lua.h>
23#include <lauxlib.h>
24
25#include "compat.h"
26#include "context.h"
27#include "options.h"
28
29#ifndef OPENSSL_NO_EC
30#include <openssl/ec.h>
31#include "ec.h"
32#endif
33
34/*--------------------------- Auxiliary Functions ----------------------------*/
35
36/**
37 * Return the context.
38 */
39static p_context checkctx(lua_State *L, int idx)
40{
41 return (p_context)luaL_checkudata(L, idx, "SSL:Context");
42}
43
44static p_context testctx(lua_State *L, int idx)
45{
46 return (p_context)luaL_testudata(L, idx, "SSL:Context");
47}
48
49/**
50 * Prepare the SSL options flag.
51 */
52static int set_option_flag(const char *opt, unsigned long *flag)
53{
54 lsec_ssl_option_t *p;
55 for (p = lsec_get_ssl_options(); p->name; p++) {
56 if (!strcmp(opt, p->name)) {
57 *flag |= p->code;
58 return 1;
59 }
60 }
61 return 0;
62}
63
64#ifndef LSEC_API_OPENSSL_1_1_0
65/**
66 * Find the protocol.
67 */
68static const SSL_METHOD* str2method(const char *method, int *vmin, int *vmax)
69{
70 (void)vmin;
71 (void)vmax;
72 if (!strcmp(method, "any")) return SSLv23_method();
73 if (!strcmp(method, "sslv23")) return SSLv23_method(); // deprecated
74 if (!strcmp(method, "tlsv1")) return TLSv1_method();
75 if (!strcmp(method, "tlsv1_1")) return TLSv1_1_method();
76 if (!strcmp(method, "tlsv1_2")) return TLSv1_2_method();
77 return NULL;
78}
79
80#else
81
82/**
83 * Find the protocol.
84 */
85static const SSL_METHOD* str2method(const char *method, int *vmin, int *vmax)
86{
87 if (!strcmp(method, "any") || !strcmp(method, "sslv23")) { // 'sslv23' is deprecated
88 *vmin = 0;
89 *vmax = 0;
90 return TLS_method();
91 }
92 else if (!strcmp(method, "tlsv1")) {
93 *vmin = TLS1_VERSION;
94 *vmax = TLS1_VERSION;
95 return TLS_method();
96 }
97 else if (!strcmp(method, "tlsv1_1")) {
98 *vmin = TLS1_1_VERSION;
99 *vmax = TLS1_1_VERSION;
100 return TLS_method();
101 }
102 else if (!strcmp(method, "tlsv1_2")) {
103 *vmin = TLS1_2_VERSION;
104 *vmax = TLS1_2_VERSION;
105 return TLS_method();
106 }
107#if defined(TLS1_3_VERSION)
108 else if (!strcmp(method, "tlsv1_3")) {
109 *vmin = TLS1_3_VERSION;
110 *vmax = TLS1_3_VERSION;
111 return TLS_method();
112 }
113#endif
114 return NULL;
115}
116#endif
117
118/**
119 * Prepare the SSL handshake verify flag.
120 */
121static int set_verify_flag(const char *str, int *flag)
122{
123 if (!strcmp(str, "none")) {
124 *flag |= SSL_VERIFY_NONE;
125 return 1;
126 }
127 if (!strcmp(str, "peer")) {
128 *flag |= SSL_VERIFY_PEER;
129 return 1;
130 }
131 if (!strcmp(str, "client_once")) {
132 *flag |= SSL_VERIFY_CLIENT_ONCE;
133 return 1;
134 }
135 if (!strcmp(str, "fail_if_no_peer_cert")) {
136 *flag |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
137 return 1;
138 }
139 return 0;
140}
141
142/**
143 * Password callback for reading the private key.
144 */
145static int passwd_cb(char *buf, int size, int flag, void *udata)
146{
147 lua_State *L = (lua_State*)udata;
148 switch (lua_type(L, 3)) {
149 case LUA_TFUNCTION:
150 lua_pushvalue(L, 3);
151 lua_call(L, 0, 1);
152 if (lua_type(L, -1) != LUA_TSTRING) {
153 lua_pop(L, 1); /* Remove the result from the stack */
154 return 0;
155 }
156 /* fallback */
157 case LUA_TSTRING:
158 strncpy(buf, lua_tostring(L, -1), size);
159 lua_pop(L, 1); /* Remove the result from the stack */
160 buf[size-1] = '\0';
161 return (int)strlen(buf);
162 }
163 return 0;
164}
165
166/**
167 * Add an error related to a depth certificate of the chain.
168 */
169static void add_cert_error(lua_State *L, SSL *ssl, int err, int depth)
170{
171 luaL_getmetatable(L, "SSL:Verify:Registry");
172 lua_pushlightuserdata(L, (void*)ssl);
173 lua_gettable(L, -2);
174 if (lua_isnil(L, -1)) {
175 lua_pop(L, 1);
176 /* Create an error table for this connection */
177 lua_newtable(L);
178 lua_pushlightuserdata(L, (void*)ssl);
179 lua_pushvalue(L, -2); /* keep the table on stack */
180 lua_settable(L, -4);
181 }
182 lua_rawgeti(L, -1, depth+1);
183 /* If the table doesn't exist, create it */
184 if (lua_isnil(L, -1)) {
185 lua_pop(L, 1); /* remove 'nil' from stack */
186 lua_newtable(L);
187 lua_pushvalue(L, -1); /* keep the table on stack */
188 lua_rawseti(L, -3, depth+1);
189 }
190 lua_pushstring(L, X509_verify_cert_error_string(err));
191 lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
192 /* Clear the stack */
193 lua_pop(L, 3);
194}
195
196/**
197 * Call Lua user function to get the DH key.
198 */
199static DH *dhparam_cb(SSL *ssl, int is_export, int keylength)
200{
201 BIO *bio;
202 lua_State *L;
203 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
204 p_context pctx = (p_context)SSL_CTX_get_app_data(ctx);
205
206 L = pctx->L;
207
208 /* Get the callback */
209 luaL_getmetatable(L, "SSL:DH:Registry");
210 lua_pushlightuserdata(L, (void*)ctx);
211 lua_gettable(L, -2);
212
213 /* Invoke the callback */
214 lua_pushboolean(L, is_export);
215 lua_pushnumber(L, keylength);
216 lua_call(L, 2, 1);
217
218 /* Load parameters from returned value */
219 if (lua_type(L, -1) != LUA_TSTRING) {
220 lua_pop(L, 2); /* Remove values from stack */
221 return NULL;
222 }
223
224 bio = BIO_new_mem_buf((void*)lua_tostring(L, -1), lua_rawlen(L, -1));
225 if (bio) {
226 pctx->dh_param = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
227 BIO_free(bio);
228 }
229
230 lua_pop(L, 2); /* Remove values from stack */
231 return pctx->dh_param;
232}
233
234/**
235 * Set the "ignore purpose" before to start verifing the certificate chain.
236 */
237static int cert_verify_cb(X509_STORE_CTX *x509_ctx, void *ptr)
238{
239 int verify;
240 lua_State *L;
241 SSL_CTX *ctx = (SSL_CTX*)ptr;
242 p_context pctx = (p_context)SSL_CTX_get_app_data(ctx);
243
244 L = pctx->L;
245
246 /* Get verify flags */
247 luaL_getmetatable(L, "SSL:Verify:Registry");
248 lua_pushlightuserdata(L, (void*)ctx);
249 lua_gettable(L, -2);
250 verify = (int)lua_tonumber(L, -1);
251
252 lua_pop(L, 2); /* Remove values from stack */
253
254 if (verify & LSEC_VERIFY_IGNORE_PURPOSE) {
255 /* Set parameters to ignore the server purpose */
256 X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(x509_ctx);
257 if (param) {
258 X509_VERIFY_PARAM_set_purpose(param, X509_PURPOSE_SSL_SERVER);
259 X509_VERIFY_PARAM_set_trust(param, X509_TRUST_SSL_SERVER);
260 }
261 }
262 /* Call OpenSSL standard verification function */
263 return X509_verify_cert(x509_ctx);
264}
265
266/**
267 * This callback implements the "continue on error" flag and log the errors.
268 */
269static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
270{
271 int err;
272 int verify;
273 SSL *ssl;
274 SSL_CTX *ctx;
275 p_context pctx;
276 lua_State *L;
277
278 /* Short-circuit optimization */
279 if (preverify_ok)
280 return 1;
281
282 ssl = X509_STORE_CTX_get_ex_data(x509_ctx,
283 SSL_get_ex_data_X509_STORE_CTX_idx());
284 ctx = SSL_get_SSL_CTX(ssl);
285 pctx = (p_context)SSL_CTX_get_app_data(ctx);
286 L = pctx->L;
287
288 /* Get verify flags */
289 luaL_getmetatable(L, "SSL:Verify:Registry");
290 lua_pushlightuserdata(L, (void*)ctx);
291 lua_gettable(L, -2);
292 verify = (int)lua_tonumber(L, -1);
293
294 lua_pop(L, 2); /* Remove values from stack */
295
296 err = X509_STORE_CTX_get_error(x509_ctx);
297 if (err != X509_V_OK)
298 add_cert_error(L, ssl, err, X509_STORE_CTX_get_error_depth(x509_ctx));
299
300 return (verify & LSEC_VERIFY_CONTINUE ? 1 : preverify_ok);
301}
302
303/*------------------------------ Lua Functions -------------------------------*/
304
305/**
306 * Create a SSL context.
307 */
308static int create(lua_State *L)
309{
310 p_context ctx;
311 const char *str_method;
312 const SSL_METHOD *method;
313 int vmin, vmax;
314
315 str_method = luaL_checkstring(L, 1);
316 method = str2method(str_method, &vmin, &vmax);
317 if (!method) {
318 lua_pushnil(L);
319 lua_pushfstring(L, "invalid protocol (%s)", str_method);
320 return 2;
321 }
322 ctx = (p_context) lua_newuserdata(L, sizeof(t_context));
323 if (!ctx) {
324 lua_pushnil(L);
325 lua_pushstring(L, "error creating context");
326 return 2;
327 }
328 memset(ctx, 0, sizeof(t_context));
329 ctx->context = SSL_CTX_new(method);
330 if (!ctx->context) {
331 lua_pushnil(L);
332 lua_pushfstring(L, "error creating context (%s)",
333 ERR_reason_error_string(ERR_get_error()));
334 return 2;
335 }
336#ifdef LSEC_API_OPENSSL_1_1_0
337 SSL_CTX_set_min_proto_version(ctx->context, vmin);
338 SSL_CTX_set_max_proto_version(ctx->context, vmax);
339#endif
340 ctx->mode = LSEC_MODE_INVALID;
341 ctx->L = L;
342 luaL_getmetatable(L, "SSL:Context");
343 lua_setmetatable(L, -2);
344
345 /* No session support */
346 SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF);
347 /* Link LuaSec context with the OpenSSL context */
348 SSL_CTX_set_app_data(ctx->context, ctx);
349
350 return 1;
351}
352
353/**
354 * Load the trusting certificates.
355 */
356static int load_locations(lua_State *L)
357{
358 SSL_CTX *ctx = lsec_checkcontext(L, 1);
359 const char *cafile = luaL_optstring(L, 2, NULL);
360 const char *capath = luaL_optstring(L, 3, NULL);
361 if (SSL_CTX_load_verify_locations(ctx, cafile, capath) != 1) {
362 lua_pushboolean(L, 0);
363 lua_pushfstring(L, "error loading CA locations (%s)",
364 ERR_reason_error_string(ERR_get_error()));
365 return 2;
366 }
367 lua_pushboolean(L, 1);
368 return 1;
369}
370
371/**
372 * Load the certificate file.
373 */
374static int load_cert(lua_State *L)
375{
376 SSL_CTX *ctx = lsec_checkcontext(L, 1);
377 const char *filename = luaL_checkstring(L, 2);
378 if (SSL_CTX_use_certificate_chain_file(ctx, filename) != 1) {
379 lua_pushboolean(L, 0);
380 lua_pushfstring(L, "error loading certificate (%s)",
381 ERR_reason_error_string(ERR_get_error()));
382 return 2;
383 }
384 lua_pushboolean(L, 1);
385 return 1;
386}
387
388/**
389 * Load the key file -- only in PEM format.
390 */
391static int load_key(lua_State *L)
392{
393 int ret = 1;
394 SSL_CTX *ctx = lsec_checkcontext(L, 1);
395 const char *filename = luaL_checkstring(L, 2);
396 switch (lua_type(L, 3)) {
397 case LUA_TSTRING:
398 case LUA_TFUNCTION:
399 SSL_CTX_set_default_passwd_cb(ctx, passwd_cb);
400 SSL_CTX_set_default_passwd_cb_userdata(ctx, L);
401 /* fallback */
402 case LUA_TNIL:
403 if (SSL_CTX_use_PrivateKey_file(ctx, filename, SSL_FILETYPE_PEM) == 1)
404 lua_pushboolean(L, 1);
405 else {
406 ret = 2;
407 lua_pushboolean(L, 0);
408 lua_pushfstring(L, "error loading private key (%s)",
409 ERR_reason_error_string(ERR_get_error()));
410 }
411 SSL_CTX_set_default_passwd_cb(ctx, NULL);
412 SSL_CTX_set_default_passwd_cb_userdata(ctx, NULL);
413 break;
414 default:
415 lua_pushstring(L, "invalid callback value");
416 lua_error(L);
417 }
418 return ret;
419}
420
421/**
422 * Check that the certificate public key matches the private key
423 */
424
425static int check_key(lua_State *L)
426{
427 SSL_CTX *ctx = lsec_checkcontext(L, 1);
428 lua_pushboolean(L, SSL_CTX_check_private_key(ctx));
429 return 1;
430}
431
432/**
433 * Set the cipher list.
434 */
435static int set_cipher(lua_State *L)
436{
437 SSL_CTX *ctx = lsec_checkcontext(L, 1);
438 const char *list = luaL_checkstring(L, 2);
439 if (SSL_CTX_set_cipher_list(ctx, list) != 1) {
440 lua_pushboolean(L, 0);
441 lua_pushfstring(L, "error setting cipher list (%s)", ERR_reason_error_string(ERR_get_error()));
442 return 2;
443 }
444 lua_pushboolean(L, 1);
445 return 1;
446}
447
448/**
449 * Set the cipher suites.
450 */
451static int set_ciphersuites(lua_State *L)
452{
453#if defined(TLS1_3_VERSION)
454 SSL_CTX *ctx = lsec_checkcontext(L, 1);
455 const char *list = luaL_checkstring(L, 2);
456 if (SSL_CTX_set_ciphersuites(ctx, list) != 1) {
457 lua_pushboolean(L, 0);
458 lua_pushfstring(L, "error setting cipher list (%s)", ERR_reason_error_string(ERR_get_error()));
459 return 2;
460 }
461#endif
462 lua_pushboolean(L, 1);
463 return 1;
464}
465
466/**
467 * Set the depth for certificate checking.
468 */
469static int set_depth(lua_State *L)
470{
471 SSL_CTX *ctx = lsec_checkcontext(L, 1);
472 SSL_CTX_set_verify_depth(ctx, (int)luaL_checkinteger(L, 2));
473 lua_pushboolean(L, 1);
474 return 1;
475}
476
477/**
478 * Set the handshake verify options.
479 */
480static int set_verify(lua_State *L)
481{
482 int i;
483 const char *str;
484 int flag = 0;
485 SSL_CTX *ctx = lsec_checkcontext(L, 1);
486 int max = lua_gettop(L);
487 for (i = 2; i <= max; i++) {
488 str = luaL_checkstring(L, i);
489 if (!set_verify_flag(str, &flag)) {
490 lua_pushboolean(L, 0);
491 lua_pushfstring(L, "invalid verify option (%s)", str);
492 return 2;
493 }
494 }
495 if (flag) SSL_CTX_set_verify(ctx, flag, NULL);
496 lua_pushboolean(L, 1);
497 return 1;
498}
499
500/**
501 * Set the protocol options.
502 */
503static int set_options(lua_State *L)
504{
505 int i;
506 const char *str;
507 unsigned long flag = 0L;
508 SSL_CTX *ctx = lsec_checkcontext(L, 1);
509 int max = lua_gettop(L);
510 /* any option? */
511 if (max > 1) {
512 for (i = 2; i <= max; i++) {
513 str = luaL_checkstring(L, i);
514 if (!set_option_flag(str, &flag)) {
515 lua_pushboolean(L, 0);
516 lua_pushfstring(L, "invalid option (%s)", str);
517 return 2;
518 }
519 }
520 SSL_CTX_set_options(ctx, flag);
521 }
522 lua_pushboolean(L, 1);
523 return 1;
524}
525
526/**
527 * Set the context mode.
528 */
529static int set_mode(lua_State *L)
530{
531 p_context ctx = checkctx(L, 1);
532 const char *str = luaL_checkstring(L, 2);
533 if (!strcmp("server", str)) {
534 ctx->mode = LSEC_MODE_SERVER;
535 lua_pushboolean(L, 1);
536 return 1;
537 }
538 if (!strcmp("client", str)) {
539 ctx->mode = LSEC_MODE_CLIENT;
540 lua_pushboolean(L, 1);
541 return 1;
542 }
543 lua_pushboolean(L, 0);
544 lua_pushfstring(L, "invalid mode (%s)", str);
545 return 1;
546}
547
548/**
549 * Configure DH parameters.
550 */
551static int set_dhparam(lua_State *L)
552{
553 SSL_CTX *ctx = lsec_checkcontext(L, 1);
554 SSL_CTX_set_tmp_dh_callback(ctx, dhparam_cb);
555
556 /* Save callback */
557 luaL_getmetatable(L, "SSL:DH:Registry");
558 lua_pushlightuserdata(L, (void*)ctx);
559 lua_pushvalue(L, 2);
560 lua_settable(L, -3);
561
562 return 0;
563}
564
565#if !defined(OPENSSL_NO_EC)
566/**
567 * Set elliptic curve.
568 */
569static int set_curve(lua_State *L)
570{
571 long ret;
572 EC_KEY *key = NULL;
573 SSL_CTX *ctx = lsec_checkcontext(L, 1);
574 const char *str = luaL_checkstring(L, 2);
575
576 SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
577
578 key = lsec_find_ec_key(L, str);
579
580 if (!key) {
581 lua_pushboolean(L, 0);
582 lua_pushfstring(L, "elliptic curve '%s' not supported", str);
583 return 2;
584 }
585
586 ret = SSL_CTX_set_tmp_ecdh(ctx, key);
587 /* SSL_CTX_set_tmp_ecdh takes its own reference */
588 EC_KEY_free(key);
589
590 if (!ret) {
591 lua_pushboolean(L, 0);
592 lua_pushfstring(L, "error setting elliptic curve (%s)",
593 ERR_reason_error_string(ERR_get_error()));
594 return 2;
595 }
596
597 lua_pushboolean(L, 1);
598 return 1;
599}
600
601/**
602 * Set elliptic curves list.
603 */
604static int set_curves_list(lua_State *L)
605{
606 SSL_CTX *ctx = lsec_checkcontext(L, 1);
607 const char *str = luaL_checkstring(L, 2);
608
609 SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
610
611 if (SSL_CTX_set1_curves_list(ctx, str) != 1) {
612 lua_pushboolean(L, 0);
613 lua_pushfstring(L, "unknown elliptic curve in \"%s\"", str);
614 return 2;
615 }
616
617#if defined(LIBRESSL_VERSION_NUMBER) || !defined(LSEC_API_OPENSSL_1_1_0)
618 (void)SSL_CTX_set_ecdh_auto(ctx, 1);
619#endif
620
621 lua_pushboolean(L, 1);
622 return 1;
623}
624#endif
625
626/**
627 * Set the protocols a client should send for ALPN.
628 */
629static int set_alpn(lua_State *L)
630{
631 long ret;
632 size_t len;
633 p_context ctx = checkctx(L, 1);
634 const char *str = luaL_checklstring(L, 2, &len);
635
636 ret = SSL_CTX_set_alpn_protos(ctx->context, (const unsigned char*)str, len);
637 if (ret) {
638 lua_pushboolean(L, 0);
639 lua_pushfstring(L, "error setting ALPN (%s)", ERR_reason_error_string(ERR_get_error()));
640 return 2;
641 }
642 lua_pushboolean(L, 1);
643 return 1;
644}
645
646/**
647 * This standard callback calls the server's callback in Lua sapce.
648 * The server has to return a list in wire-format strings.
649 * This function uses a helper function to match server and client lists.
650 */
651static int alpn_cb(SSL *s, const unsigned char **out, unsigned char *outlen,
652 const unsigned char *in, unsigned int inlen, void *arg)
653{
654 int ret;
655 size_t server_len;
656 const char *server;
657 p_context ctx = (p_context)arg;
658 lua_State *L = ctx->L;
659
660 luaL_getmetatable(L, "SSL:ALPN:Registry");
661 lua_pushlightuserdata(L, (void*)ctx->context);
662 lua_gettable(L, -2);
663
664 lua_pushlstring(L, (const char*)in, inlen);
665
666 lua_call(L, 1, 1);
667
668 if (!lua_isstring(L, -1)) {
669 lua_pop(L, 2);
670 return SSL_TLSEXT_ERR_NOACK;
671 }
672
673 // Protocol list from server in wire-format string
674 server = luaL_checklstring(L, -1, &server_len);
675 ret = SSL_select_next_proto((unsigned char**)out, outlen, (const unsigned char*)server,
676 server_len, in, inlen);
677 if (ret != OPENSSL_NPN_NEGOTIATED) {
678 lua_pop(L, 2);
679 return SSL_TLSEXT_ERR_NOACK;
680 }
681
682 // Copy the result because lua_pop() can collect the pointer
683 ctx->alpn = malloc(*outlen);
684 memcpy(ctx->alpn, (void*)*out, *outlen);
685 *out = (const unsigned char*)ctx->alpn;
686
687 lua_pop(L, 2);
688
689 return SSL_TLSEXT_ERR_OK;
690}
691
692/**
693 * Set a callback a server can use to select the next protocol with ALPN.
694 */
695static int set_alpn_cb(lua_State *L)
696{
697 p_context ctx = checkctx(L, 1);
698
699 luaL_getmetatable(L, "SSL:ALPN:Registry");
700 lua_pushlightuserdata(L, (void*)ctx->context);
701 lua_pushvalue(L, 2);
702 lua_settable(L, -3);
703
704 SSL_CTX_set_alpn_select_cb(ctx->context, alpn_cb, ctx);
705
706 lua_pushboolean(L, 1);
707 return 1;
708}
709
710#if defined(LSEC_ENABLE_PSK)
711/**
712 * Callback to select the PSK.
713 */
714static unsigned int server_psk_cb(SSL *ssl, const char *identity, unsigned char *psk,
715 unsigned int max_psk_len)
716{
717 size_t psk_len;
718 const char *ret_psk;
719 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
720 p_context pctx = (p_context)SSL_CTX_get_app_data(ctx);
721 lua_State *L = pctx->L;
722
723 luaL_getmetatable(L, "SSL:PSK:Registry");
724 lua_pushlightuserdata(L, (void*)pctx->context);
725 lua_gettable(L, -2);
726
727 lua_pushstring(L, identity);
728 lua_pushinteger(L, max_psk_len);
729
730 lua_call(L, 2, 1);
731
732 if (!lua_isstring(L, -1)) {
733 lua_pop(L, 2);
734 return 0;
735 }
736
737 ret_psk = lua_tolstring(L, -1, &psk_len);
738
739 if (psk_len == 0 || psk_len > max_psk_len)
740 psk_len = 0;
741 else
742 memcpy(psk, ret_psk, psk_len);
743
744 lua_pop(L, 2);
745
746 return psk_len;
747}
748
749/**
750 * Set a PSK callback for server.
751 */
752static int set_server_psk_cb(lua_State *L)
753{
754 p_context ctx = checkctx(L, 1);
755
756 luaL_getmetatable(L, "SSL:PSK:Registry");
757 lua_pushlightuserdata(L, (void*)ctx->context);
758 lua_pushvalue(L, 2);
759 lua_settable(L, -3);
760
761 SSL_CTX_set_psk_server_callback(ctx->context, server_psk_cb);
762
763 lua_pushboolean(L, 1);
764 return 1;
765}
766
767/*
768 * Set the PSK indentity hint.
769 */
770static int set_psk_identity_hint(lua_State *L)
771{
772 p_context ctx = checkctx(L, 1);
773 const char *hint = luaL_checkstring(L, 2);
774 int ret = SSL_CTX_use_psk_identity_hint(ctx->context, hint);
775 lua_pushboolean(L, ret);
776 return 1;
777}
778
779/*
780 * Client callback to PSK.
781 */
782static unsigned int client_psk_cb(SSL *ssl, const char *hint, char *identity,
783 unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len)
784{
785 size_t psk_len;
786 size_t identity_len;
787 const char *ret_psk;
788 const char *ret_identity;
789 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
790 p_context pctx = (p_context)SSL_CTX_get_app_data(ctx);
791 lua_State *L = pctx->L;
792
793 luaL_getmetatable(L, "SSL:PSK:Registry");
794 lua_pushlightuserdata(L, (void*)pctx->context);
795 lua_gettable(L, -2);
796
797 if (hint)
798 lua_pushstring(L, hint);
799 else
800 lua_pushnil(L);
801
802 // Leave space to '\0'
803 lua_pushinteger(L, max_identity_len-1);
804 lua_pushinteger(L, max_psk_len);
805
806 lua_call(L, 3, 2);
807
808 if (!lua_isstring(L, -1) || !lua_isstring(L, -2)) {
809 lua_pop(L, 3);
810 return 0;
811 }
812
813 ret_identity = lua_tolstring(L, -2, &identity_len);
814 ret_psk = lua_tolstring(L, -1, &psk_len);
815
816 if (identity_len >= max_identity_len || psk_len > max_psk_len)
817 psk_len = 0;
818 else {
819 memcpy(identity, ret_identity, identity_len);
820 identity[identity_len] = 0;
821 memcpy(psk, ret_psk, psk_len);
822 }
823
824 lua_pop(L, 3);
825
826 return psk_len;
827}
828
829/**
830 * Set a PSK callback for client.
831 */
832static int set_client_psk_cb(lua_State *L) {
833 p_context ctx = checkctx(L, 1);
834
835 luaL_getmetatable(L, "SSL:PSK:Registry");
836 lua_pushlightuserdata(L, (void*)ctx->context);
837 lua_pushvalue(L, 2);
838 lua_settable(L, -3);
839
840 SSL_CTX_set_psk_client_callback(ctx->context, client_psk_cb);
841
842 lua_pushboolean(L, 1);
843 return 1;
844}
845#endif
846
847#if defined(LSEC_ENABLE_DANE)
848/*
849 * DANE
850 */
851static int dane_options[] = {
852 /* TODO move into options.c
853 * however this symbol is not from openssl/ssl.h but rather from
854 * openssl/x509_vfy.h
855 * */
856#ifdef DANE_FLAG_NO_DANE_EE_NAMECHECKS
857 DANE_FLAG_NO_DANE_EE_NAMECHECKS,
858#endif
859 0
860};
861static const char *dane_option_names[] = {
862#ifdef DANE_FLAG_NO_DANE_EE_NAMECHECKS
863 "no_ee_namechecks",
864#endif
865 NULL
866};
867
868static int set_dane(lua_State *L)
869{
870 int ret, i;
871 SSL_CTX *ctx = lsec_checkcontext(L, 1);
872 ret = SSL_CTX_dane_enable(ctx);
873 for (i = 2; ret > 0 && i <= lua_gettop(L); i++) {
874 ret = SSL_CTX_dane_set_flags(ctx, dane_options[luaL_checkoption(L, i, NULL, dane_option_names)]);
875 }
876 lua_pushboolean(L, (ret > 0));
877 return 1;
878}
879#endif
880
881/**
882 * Package functions
883 */
884static luaL_Reg funcs[] = {
885 {"create", create},
886 {"locations", load_locations},
887 {"loadcert", load_cert},
888 {"loadkey", load_key},
889 {"checkkey", check_key},
890 {"setalpn", set_alpn},
891 {"setalpncb", set_alpn_cb},
892 {"setcipher", set_cipher},
893 {"setciphersuites", set_ciphersuites},
894 {"setdepth", set_depth},
895 {"setdhparam", set_dhparam},
896 {"setverify", set_verify},
897 {"setoptions", set_options},
898#if defined(LSEC_ENABLE_PSK)
899 {"setpskhint", set_psk_identity_hint},
900 {"setserverpskcb", set_server_psk_cb},
901 {"setclientpskcb", set_client_psk_cb},
902#endif
903 {"setmode", set_mode},
904#if !defined(OPENSSL_NO_EC)
905 {"setcurve", set_curve},
906 {"setcurveslist", set_curves_list},
907#endif
908#if defined(LSEC_ENABLE_DANE)
909 {"setdane", set_dane},
910#endif
911 {NULL, NULL}
912};
913
914/*-------------------------------- Metamethods -------------------------------*/
915
916/**
917 * Collect SSL context -- GC metamethod.
918 */
919static int meth_destroy(lua_State *L)
920{
921 p_context ctx = checkctx(L, 1);
922 if (ctx->context) {
923 /* Clear registries */
924 luaL_getmetatable(L, "SSL:DH:Registry");
925 lua_pushlightuserdata(L, (void*)ctx->context);
926 lua_pushnil(L);
927 lua_settable(L, -3);
928 luaL_getmetatable(L, "SSL:Verify:Registry");
929 lua_pushlightuserdata(L, (void*)ctx->context);
930 lua_pushnil(L);
931 lua_settable(L, -3);
932 luaL_getmetatable(L, "SSL:ALPN:Registry");
933 lua_pushlightuserdata(L, (void*)ctx->context);
934 lua_pushnil(L);
935 lua_settable(L, -3);
936 luaL_getmetatable(L, "SSL:PSK:Registry");
937 lua_pushlightuserdata(L, (void*)ctx->context);
938 lua_pushnil(L);
939 lua_settable(L, -3);
940
941 SSL_CTX_free(ctx->context);
942 ctx->context = NULL;
943 }
944 return 0;
945}
946
947/**
948 * Object information -- tostring metamethod.
949 */
950static int meth_tostring(lua_State *L)
951{
952 p_context ctx = checkctx(L, 1);
953 lua_pushfstring(L, "SSL context: %p", ctx);
954 return 1;
955}
956
957/**
958 * Set extra flags for handshake verification.
959 */
960static int meth_set_verify_ext(lua_State *L)
961{
962 int i;
963 const char *str;
964 int crl_flag = 0;
965 int lsec_flag = 0;
966 SSL_CTX *ctx = lsec_checkcontext(L, 1);
967 int max = lua_gettop(L);
968 for (i = 2; i <= max; i++) {
969 str = luaL_checkstring(L, i);
970 if (!strcmp(str, "lsec_continue")) {
971 lsec_flag |= LSEC_VERIFY_CONTINUE;
972 } else if (!strcmp(str, "lsec_ignore_purpose")) {
973 lsec_flag |= LSEC_VERIFY_IGNORE_PURPOSE;
974 } else if (!strcmp(str, "crl_check")) {
975 crl_flag |= X509_V_FLAG_CRL_CHECK;
976 } else if (!strcmp(str, "crl_check_chain")) {
977 crl_flag |= X509_V_FLAG_CRL_CHECK_ALL;
978 } else {
979 lua_pushboolean(L, 0);
980 lua_pushfstring(L, "invalid verify option (%s)", str);
981 return 2;
982 }
983 }
984 /* Set callback? */
985 if (lsec_flag) {
986 SSL_CTX_set_verify(ctx, SSL_CTX_get_verify_mode(ctx), verify_cb);
987 SSL_CTX_set_cert_verify_callback(ctx, cert_verify_cb, (void*)ctx);
988 /* Save flag */
989 luaL_getmetatable(L, "SSL:Verify:Registry");
990 lua_pushlightuserdata(L, (void*)ctx);
991 lua_pushnumber(L, lsec_flag);
992 lua_settable(L, -3);
993 } else {
994 SSL_CTX_set_verify(ctx, SSL_CTX_get_verify_mode(ctx), NULL);
995 SSL_CTX_set_cert_verify_callback(ctx, NULL, NULL);
996 /* Remove flag */
997 luaL_getmetatable(L, "SSL:Verify:Registry");
998 lua_pushlightuserdata(L, (void*)ctx);
999 lua_pushnil(L);
1000 lua_settable(L, -3);
1001 }
1002
1003 /* X509 flag */
1004 X509_STORE_set_flags(SSL_CTX_get_cert_store(ctx), crl_flag);
1005
1006 /* Ok */
1007 lua_pushboolean(L, 1);
1008 return 1;
1009}
1010
1011/**
1012 * Context metamethods.
1013 */
1014static luaL_Reg meta[] = {
1015 {"__close", meth_destroy},
1016 {"__gc", meth_destroy},
1017 {"__tostring", meth_tostring},
1018 {NULL, NULL}
1019};
1020
1021/**
1022 * Index metamethods.
1023 */
1024static luaL_Reg meta_index[] = {
1025 {"setverifyext", meth_set_verify_ext},
1026 {NULL, NULL}
1027};
1028
1029
1030/*----------------------------- Public Functions ---------------------------*/
1031
1032/**
1033 * Retrieve the SSL context from the Lua stack.
1034 */
1035SSL_CTX* lsec_checkcontext(lua_State *L, int idx)
1036{
1037 p_context ctx = checkctx(L, idx);
1038 return ctx->context;
1039}
1040
1041SSL_CTX* lsec_testcontext(lua_State *L, int idx)
1042{
1043 p_context ctx = testctx(L, idx);
1044 return (ctx) ? ctx->context : NULL;
1045}
1046
1047/**
1048 * Retrieve the mode from the context in the Lua stack.
1049 */
1050int lsec_getmode(lua_State *L, int idx)
1051{
1052 p_context ctx = checkctx(L, idx);
1053 return ctx->mode;
1054}
1055
1056/*-- Compat - Lua 5.1 --*/
1057#if (LUA_VERSION_NUM == 501)
1058
1059void *lsec_testudata (lua_State *L, int ud, const char *tname) {
1060 void *p = lua_touserdata(L, ud);
1061 if (p != NULL) { /* value is a userdata? */
1062 if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
1063 luaL_getmetatable(L, tname); /* get correct metatable */
1064 if (!lua_rawequal(L, -1, -2)) /* not the same? */
1065 p = NULL; /* value is a userdata with wrong metatable */
1066 lua_pop(L, 2); /* remove both metatables */
1067 return p;
1068 }
1069 }
1070 return NULL; /* value is not a userdata with a metatable */
1071}
1072
1073#endif
1074
1075/*------------------------------ Initialization ------------------------------*/
1076
1077/**
1078 * Registre the module.
1079 */
1080LSEC_API int luaopen_ssl_context(lua_State *L)
1081{
1082 luaL_newmetatable(L, "SSL:DH:Registry"); /* Keep all DH callbacks */
1083 luaL_newmetatable(L, "SSL:ALPN:Registry"); /* Keep all ALPN callbacks */
1084 luaL_newmetatable(L, "SSL:PSK:Registry"); /* Keep all PSK callbacks */
1085 luaL_newmetatable(L, "SSL:Verify:Registry"); /* Keep all verify flags */
1086 luaL_newmetatable(L, "SSL:Context");
1087 setfuncs(L, meta);
1088
1089 /* Create __index metamethods for context */
1090 luaL_newlib(L, meta_index);
1091 lua_setfield(L, -2, "__index");
1092
1093 lsec_load_curves(L);
1094
1095 /* Return the module */
1096 luaL_newlib(L, funcs);
1097
1098 return 1;
1099}
diff --git a/vendor/luasec/src/context.h b/vendor/luasec/src/context.h
new file mode 100644
index 00000000..dd6bd098
--- /dev/null
+++ b/vendor/luasec/src/context.h
@@ -0,0 +1,47 @@
1#ifndef LSEC_CONTEXT_H
2#define LSEC_CONTEXT_H
3
4/*--------------------------------------------------------------------------
5 * LuaSec 1.3.2
6 *
7 * Copyright (C) 2006-2023 Bruno Silvestre
8 *
9 *--------------------------------------------------------------------------*/
10
11#include <lua.h>
12#include <openssl/ssl.h>
13
14#include "compat.h"
15
16#define LSEC_MODE_INVALID 0
17#define LSEC_MODE_SERVER 1
18#define LSEC_MODE_CLIENT 2
19
20#define LSEC_VERIFY_CONTINUE 1
21#define LSEC_VERIFY_IGNORE_PURPOSE 2
22
23typedef struct t_context_ {
24 SSL_CTX *context;
25 lua_State *L;
26 DH *dh_param;
27 void *alpn;
28 int mode;
29} t_context;
30typedef t_context* p_context;
31
32/* Retrieve the SSL context from the Lua stack */
33SSL_CTX *lsec_checkcontext(lua_State *L, int idx);
34SSL_CTX *lsec_testcontext(lua_State *L, int idx);
35
36/* Retrieve the mode from the context in the Lua stack */
37int lsec_getmode(lua_State *L, int idx);
38
39/* Registre the module. */
40LSEC_API int luaopen_ssl_context(lua_State *L);
41
42/* Compat - Lua 5.1 */
43#if (LUA_VERSION_NUM == 501)
44void *lsec_testudata (lua_State *L, int ud, const char *tname);
45#endif
46
47#endif
diff --git a/vendor/luasec/src/ec.c b/vendor/luasec/src/ec.c
new file mode 100644
index 00000000..c7025a55
--- /dev/null
+++ b/vendor/luasec/src/ec.c
@@ -0,0 +1,116 @@
1/*--------------------------------------------------------------------------
2 * LuaSec 1.3.2
3 *
4 * Copyright (C) 2006-2023 Bruno Silvestre
5 *
6 *--------------------------------------------------------------------------*/
7
8#include <openssl/objects.h>
9
10#include "ec.h"
11
12#ifndef OPENSSL_NO_EC
13
14EC_KEY *lsec_find_ec_key(lua_State *L, const char *str)
15{
16 int nid;
17 lua_pushstring(L, "SSL:EC:CURVES");
18 lua_rawget(L, LUA_REGISTRYINDEX);
19 lua_pushstring(L, str);
20 lua_rawget(L, -2);
21
22 if (!lua_isnumber(L, -1))
23 return NULL;
24
25 nid = (int)lua_tonumber(L, -1);
26 return EC_KEY_new_by_curve_name(nid);
27}
28
29void lsec_load_curves(lua_State *L)
30{
31 size_t i;
32 size_t size;
33 const char *name;
34 EC_builtin_curve *curves = NULL;
35
36 lua_pushstring(L, "SSL:EC:CURVES");
37 lua_newtable(L);
38
39 size = EC_get_builtin_curves(NULL, 0);
40 if (size > 0) {
41 curves = (EC_builtin_curve*)malloc(sizeof(EC_builtin_curve) * size);
42 EC_get_builtin_curves(curves, size);
43 for (i = 0; i < size; i++) {
44 name = OBJ_nid2sn(curves[i].nid);
45 if (name != NULL) {
46 lua_pushstring(L, name);
47 lua_pushnumber(L, curves[i].nid);
48 lua_rawset(L, -3);
49 }
50 switch (curves[i].nid) {
51 case NID_X9_62_prime256v1:
52 lua_pushstring(L, "P-256");
53 lua_pushnumber(L, curves[i].nid);
54 lua_rawset(L, -3);
55 break;
56 case NID_secp384r1:
57 lua_pushstring(L, "P-384");
58 lua_pushnumber(L, curves[i].nid);
59 lua_rawset(L, -3);
60 break;
61 case NID_secp521r1:
62 lua_pushstring(L, "P-521");
63 lua_pushnumber(L, curves[i].nid);
64 lua_rawset(L, -3);
65 break;
66 }
67 }
68 free(curves);
69 }
70
71 /* These are special so are manually added here */
72#ifdef NID_X25519
73 lua_pushstring(L, "X25519");
74 lua_pushnumber(L, NID_X25519);
75 lua_rawset(L, -3);
76#endif
77
78#ifdef NID_X448
79 lua_pushstring(L, "X448");
80 lua_pushnumber(L, NID_X448);
81 lua_rawset(L, -3);
82#endif
83
84 lua_rawset(L, LUA_REGISTRYINDEX);
85}
86
87void lsec_get_curves(lua_State *L)
88{
89 lua_newtable(L);
90
91 lua_pushstring(L, "SSL:EC:CURVES");
92 lua_rawget(L, LUA_REGISTRYINDEX);
93
94 lua_pushnil(L);
95 while (lua_next(L, -2) != 0) {
96 lua_pop(L, 1);
97 lua_pushvalue(L, -1);
98 lua_pushboolean(L, 1);
99 lua_rawset(L, -5);
100 }
101 lua_pop(L, 1);
102}
103
104#else
105
106void lsec_load_curves(lua_State *L)
107{
108 // do nothing
109}
110
111void lsec_get_curves(lua_State *L)
112{
113 lua_newtable(L);
114}
115
116#endif
diff --git a/vendor/luasec/src/ec.h b/vendor/luasec/src/ec.h
new file mode 100644
index 00000000..16d29360
--- /dev/null
+++ b/vendor/luasec/src/ec.h
@@ -0,0 +1,22 @@
1/*--------------------------------------------------------------------------
2 * LuaSec 1.3.2
3 *
4 * Copyright (C) 2006-2023 Bruno Silvestre
5 *
6 *--------------------------------------------------------------------------*/
7
8#ifndef LSEC_EC_H
9#define LSEC_EC_H
10
11#include <lua.h>
12
13#ifndef OPENSSL_NO_EC
14#include <openssl/ec.h>
15
16EC_KEY *lsec_find_ec_key(lua_State *L, const char *str);
17#endif
18
19void lsec_get_curves(lua_State *L);
20void lsec_load_curves(lua_State *L);
21
22#endif
diff --git a/vendor/luasec/src/https.lua b/vendor/luasec/src/https.lua
new file mode 100644
index 00000000..85cef361
--- /dev/null
+++ b/vendor/luasec/src/https.lua
@@ -0,0 +1,147 @@
1----------------------------------------------------------------------------
2-- LuaSec 1.3.2
3--
4-- Copyright (C) 2009-2023 PUC-Rio
5--
6-- Author: Pablo Musa
7-- Author: Tomas Guisasola
8---------------------------------------------------------------------------
9
10local socket = require("socket")
11local ssl = require("ssl")
12local ltn12 = require("ltn12")
13local http = require("socket.http")
14local url = require("socket.url")
15
16local try = socket.try
17
18--
19-- Module
20--
21local _M = {
22 _VERSION = "1.3.2",
23 _COPYRIGHT = "LuaSec 1.3.2 - Copyright (C) 2009-2023 PUC-Rio",
24 PORT = 443,
25 TIMEOUT = 60
26}
27
28-- TLS configuration
29local cfg = {
30 protocol = "any",
31 options = {"all", "no_sslv2", "no_sslv3", "no_tlsv1"},
32 verify = "none",
33}
34
35--------------------------------------------------------------------
36-- Auxiliar Functions
37--------------------------------------------------------------------
38
39-- Insert default HTTPS port.
40local function default_https_port(u)
41 return url.build(url.parse(u, {port = _M.PORT}))
42end
43
44-- Convert an URL to a table according to Luasocket needs.
45local function urlstring_totable(url, body, result_table)
46 url = {
47 url = default_https_port(url),
48 method = body and "POST" or "GET",
49 sink = ltn12.sink.table(result_table)
50 }
51 if body then
52 url.source = ltn12.source.string(body)
53 url.headers = {
54 ["content-length"] = #body,
55 ["content-type"] = "application/x-www-form-urlencoded",
56 }
57 end
58 return url
59end
60
61-- Forward calls to the real connection object.
62local function reg(conn)
63 local mt = getmetatable(conn.sock).__index
64 for name, method in pairs(mt) do
65 if type(method) == "function" then
66 conn[name] = function (self, ...)
67 return method(self.sock, ...)
68 end
69 end
70 end
71end
72
73-- Return a function which performs the SSL/TLS connection.
74local function tcp(params)
75 params = params or {}
76 -- Default settings
77 for k, v in pairs(cfg) do
78 params[k] = params[k] or v
79 end
80 -- Force client mode
81 params.mode = "client"
82 -- 'create' function for LuaSocket
83 return function ()
84 local conn = {}
85 conn.sock = try(socket.tcp())
86 local st = getmetatable(conn.sock).__index.settimeout
87 function conn:settimeout(...)
88 return st(self.sock, _M.TIMEOUT)
89 end
90 -- Replace TCP's connection function
91 function conn:connect(host, port)
92 try(self.sock:connect(host, port))
93 self.sock = try(ssl.wrap(self.sock, params))
94 self.sock:sni(host)
95 self.sock:settimeout(_M.TIMEOUT)
96 try(self.sock:dohandshake())
97 reg(self)
98 return 1
99 end
100 return conn
101 end
102end
103
104--------------------------------------------------------------------
105-- Main Function
106--------------------------------------------------------------------
107
108-- Make a HTTP request over secure connection. This function receives
109-- the same parameters of LuaSocket's HTTP module (except 'proxy' and
110-- 'redirect') plus LuaSec parameters.
111--
112-- @param url mandatory (string or table)
113-- @param body optional (string)
114-- @return (string if url == string or 1), code, headers, status
115--
116local function request(url, body)
117 local result_table = {}
118 local stringrequest = type(url) == "string"
119 if stringrequest then
120 url = urlstring_totable(url, body, result_table)
121 else
122 url.url = default_https_port(url.url)
123 end
124 if http.PROXY or url.proxy then
125 return nil, "proxy not supported"
126 elseif url.redirect then
127 return nil, "redirect not supported"
128 elseif url.create then
129 return nil, "create function not permitted"
130 end
131 -- New 'create' function to establish a secure connection
132 url.create = tcp(url)
133 local res, code, headers, status = http.request(url)
134 if res and stringrequest then
135 return table.concat(result_table), code, headers, status
136 end
137 return res, code, headers, status
138end
139
140--------------------------------------------------------------------------------
141-- Export module
142--
143
144_M.request = request
145_M.tcp = tcp
146
147return _M
diff --git a/vendor/luasec/src/luasocket/LICENSE b/vendor/luasec/src/luasocket/LICENSE
new file mode 100644
index 00000000..eadb747b
--- /dev/null
+++ b/vendor/luasec/src/luasocket/LICENSE
@@ -0,0 +1,21 @@
1LuaSocket 3.0-RC1 license
2Copyright (C) 2004-2013 Diego Nehab
3
4Permission is hereby granted, free of charge, to any person obtaining
5a copy of this software and associated documentation files (the
6"Software"), to deal in the Software without restriction, including
7without limitation the rights to use, copy, modify, merge, publish,
8distribute, sublicense, and/or sell copies of the Software, and to
9permit persons to whom the Software is furnished to do so, subject to
10the following conditions:
11
12The above copyright notice and this permission notice shall be
13included in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/luasec/src/luasocket/Makefile b/vendor/luasec/src/luasocket/Makefile
new file mode 100644
index 00000000..b700fb63
--- /dev/null
+++ b/vendor/luasec/src/luasocket/Makefile
@@ -0,0 +1,26 @@
1OBJS= \
2 io.o \
3 buffer.o \
4 timeout.o \
5 usocket.o
6
7CC ?= cc
8CFLAGS += $(MYCFLAGS) -DLUASOCKET_DEBUG
9AR ?= ar
10RANLIB ?= ranlib
11
12.PHONY: all clean
13
14all: libluasocket.a
15
16libluasocket.a: $(OBJS)
17 $(AR) rcu $@ $(OBJS)
18 $(RANLIB) $@
19
20clean:
21 rm -f $(OBJS) libluasocket.a
22
23buffer.o: buffer.c buffer.h io.h timeout.h
24io.o: io.c io.h timeout.h
25timeout.o: timeout.c timeout.h
26usocket.o: usocket.c socket.h io.h timeout.h usocket.h
diff --git a/vendor/luasec/src/luasocket/buffer.c b/vendor/luasec/src/luasocket/buffer.c
new file mode 100644
index 00000000..0eaac418
--- /dev/null
+++ b/vendor/luasec/src/luasocket/buffer.c
@@ -0,0 +1,278 @@
1/*=========================================================================*\
2* Input/Output interface for Lua programs
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "lua.h"
6#include "lauxlib.h"
7
8#include "buffer.h"
9
10/*=========================================================================*\
11* Internal function prototypes
12\*=========================================================================*/
13static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b);
14static int recvline(p_buffer buf, luaL_Buffer *b);
15static int recvall(p_buffer buf, luaL_Buffer *b);
16static int buffer_get(p_buffer buf, const char **data, size_t *count);
17static void buffer_skip(p_buffer buf, size_t count);
18static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent);
19
20/* min and max macros */
21#ifndef MIN
22#define MIN(x, y) ((x) < (y) ? x : y)
23#endif
24#ifndef MAX
25#define MAX(x, y) ((x) > (y) ? x : y)
26#endif
27
28/*=========================================================================*\
29* Exported functions
30\*=========================================================================*/
31/*-------------------------------------------------------------------------*\
32* Initializes module
33\*-------------------------------------------------------------------------*/
34int buffer_open(lua_State *L) {
35 (void) L;
36 return 0;
37}
38
39/*-------------------------------------------------------------------------*\
40* Initializes C structure
41\*-------------------------------------------------------------------------*/
42void buffer_init(p_buffer buf, p_io io, p_timeout tm) {
43 buf->first = buf->last = 0;
44 buf->io = io;
45 buf->tm = tm;
46 buf->received = buf->sent = 0;
47 buf->birthday = timeout_gettime();
48}
49
50/*-------------------------------------------------------------------------*\
51* object:getstats() interface
52\*-------------------------------------------------------------------------*/
53int buffer_meth_getstats(lua_State *L, p_buffer buf) {
54 lua_pushnumber(L, (lua_Number) buf->received);
55 lua_pushnumber(L, (lua_Number) buf->sent);
56 lua_pushnumber(L, timeout_gettime() - buf->birthday);
57 return 3;
58}
59
60/*-------------------------------------------------------------------------*\
61* object:setstats() interface
62\*-------------------------------------------------------------------------*/
63int buffer_meth_setstats(lua_State *L, p_buffer buf) {
64 buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received);
65 buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent);
66 if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4);
67 lua_pushnumber(L, 1);
68 return 1;
69}
70
71/*-------------------------------------------------------------------------*\
72* object:send() interface
73\*-------------------------------------------------------------------------*/
74int buffer_meth_send(lua_State *L, p_buffer buf) {
75 int top = lua_gettop(L);
76 int err = IO_DONE;
77 size_t size = 0, sent = 0;
78 const char *data = luaL_checklstring(L, 2, &size);
79 long start = (long) luaL_optnumber(L, 3, 1);
80 long end = (long) luaL_optnumber(L, 4, -1);
81 timeout_markstart(buf->tm);
82 if (start < 0) start = (long) (size+start+1);
83 if (end < 0) end = (long) (size+end+1);
84 if (start < 1) start = (long) 1;
85 if (end > (long) size) end = (long) size;
86 if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent);
87 /* check if there was an error */
88 if (err != IO_DONE) {
89 lua_pushnil(L);
90 lua_pushstring(L, buf->io->error(buf->io->ctx, err));
91 lua_pushnumber(L, (lua_Number) (sent+start-1));
92 } else {
93 lua_pushnumber(L, (lua_Number) (sent+start-1));
94 lua_pushnil(L);
95 lua_pushnil(L);
96 }
97#ifdef LUASOCKET_DEBUG
98 /* push time elapsed during operation as the last return value */
99 lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
100#endif
101 return lua_gettop(L) - top;
102}
103
104/*-------------------------------------------------------------------------*\
105* object:receive() interface
106\*-------------------------------------------------------------------------*/
107int buffer_meth_receive(lua_State *L, p_buffer buf) {
108 luaL_Buffer b;
109 size_t size;
110 const char *part;
111 int err = IO_DONE;
112 int top = lua_gettop(L);
113 if (top < 3) {
114 lua_settop(L, 3);
115 top = 3;
116 }
117 part = luaL_optlstring(L, 3, "", &size);
118 timeout_markstart(buf->tm);
119 /* initialize buffer with optional extra prefix
120 * (useful for concatenating previous partial results) */
121 luaL_buffinit(L, &b);
122 luaL_addlstring(&b, part, size);
123 /* receive new patterns */
124 if (!lua_isnumber(L, 2)) {
125 const char *p= luaL_optstring(L, 2, "*l");
126 if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b);
127 else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b);
128 else luaL_argcheck(L, 0, 2, "invalid receive pattern");
129 /* get a fixed number of bytes (minus what was already partially
130 * received) */
131 } else {
132 double n = lua_tonumber(L, 2);
133 size_t wanted = (size_t) n;
134 luaL_argcheck(L, n >= 0, 2, "invalid receive pattern");
135 if (size == 0 || wanted > size)
136 err = recvraw(buf, wanted-size, &b);
137 }
138 /* check if there was an error */
139 if (err != IO_DONE) {
140 /* we can't push anything in the stack before pushing the
141 * contents of the buffer. this is the reason for the complication */
142 luaL_pushresult(&b);
143 lua_pushstring(L, buf->io->error(buf->io->ctx, err));
144 lua_pushvalue(L, -2);
145 lua_pushnil(L);
146 lua_replace(L, -4);
147 } else {
148 luaL_pushresult(&b);
149 lua_pushnil(L);
150 lua_pushnil(L);
151 }
152#ifdef LUASOCKET_DEBUG
153 /* push time elapsed during operation as the last return value */
154 lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
155#endif
156 return lua_gettop(L) - top;
157}
158
159/*-------------------------------------------------------------------------*\
160* Determines if there is any data in the read buffer
161\*-------------------------------------------------------------------------*/
162int buffer_isempty(p_buffer buf) {
163 return buf->first >= buf->last;
164}
165
166/*=========================================================================*\
167* Internal functions
168\*=========================================================================*/
169/*-------------------------------------------------------------------------*\
170* Sends a block of data (unbuffered)
171\*-------------------------------------------------------------------------*/
172#define STEPSIZE 8192
173static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) {
174 p_io io = buf->io;
175 p_timeout tm = buf->tm;
176 size_t total = 0;
177 int err = IO_DONE;
178 while (total < count && err == IO_DONE) {
179 size_t done = 0;
180 size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE;
181 err = io->send(io->ctx, data+total, step, &done, tm);
182 total += done;
183 }
184 *sent = total;
185 buf->sent += total;
186 return err;
187}
188
189/*-------------------------------------------------------------------------*\
190* Reads a fixed number of bytes (buffered)
191\*-------------------------------------------------------------------------*/
192static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) {
193 int err = IO_DONE;
194 size_t total = 0;
195 while (err == IO_DONE) {
196 size_t count; const char *data;
197 err = buffer_get(buf, &data, &count);
198 count = MIN(count, wanted - total);
199 luaL_addlstring(b, data, count);
200 buffer_skip(buf, count);
201 total += count;
202 if (total >= wanted) break;
203 }
204 return err;
205}
206
207/*-------------------------------------------------------------------------*\
208* Reads everything until the connection is closed (buffered)
209\*-------------------------------------------------------------------------*/
210static int recvall(p_buffer buf, luaL_Buffer *b) {
211 int err = IO_DONE;
212 size_t total = 0;
213 while (err == IO_DONE) {
214 const char *data; size_t count;
215 err = buffer_get(buf, &data, &count);
216 total += count;
217 luaL_addlstring(b, data, count);
218 buffer_skip(buf, count);
219 }
220 if (err == IO_CLOSED) {
221 if (total > 0) return IO_DONE;
222 else return IO_CLOSED;
223 } else return err;
224}
225
226/*-------------------------------------------------------------------------*\
227* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
228* are not returned by the function and are discarded from the buffer
229\*-------------------------------------------------------------------------*/
230static int recvline(p_buffer buf, luaL_Buffer *b) {
231 int err = IO_DONE;
232 while (err == IO_DONE) {
233 size_t count, pos; const char *data;
234 err = buffer_get(buf, &data, &count);
235 pos = 0;
236 while (pos < count && data[pos] != '\n') {
237 /* we ignore all \r's */
238 if (data[pos] != '\r') luaL_addchar(b, data[pos]);
239 pos++;
240 }
241 if (pos < count) { /* found '\n' */
242 buffer_skip(buf, pos+1); /* skip '\n' too */
243 break; /* we are done */
244 } else /* reached the end of the buffer */
245 buffer_skip(buf, pos);
246 }
247 return err;
248}
249
250/*-------------------------------------------------------------------------*\
251* Skips a given number of bytes from read buffer. No data is read from the
252* transport layer
253\*-------------------------------------------------------------------------*/
254static void buffer_skip(p_buffer buf, size_t count) {
255 buf->received += count;
256 buf->first += count;
257 if (buffer_isempty(buf))
258 buf->first = buf->last = 0;
259}
260
261/*-------------------------------------------------------------------------*\
262* Return any data available in buffer, or get more data from transport layer
263* if buffer is empty
264\*-------------------------------------------------------------------------*/
265static int buffer_get(p_buffer buf, const char **data, size_t *count) {
266 int err = IO_DONE;
267 p_io io = buf->io;
268 p_timeout tm = buf->tm;
269 if (buffer_isempty(buf)) {
270 size_t got;
271 err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm);
272 buf->first = 0;
273 buf->last = got;
274 }
275 *count = buf->last - buf->first;
276 *data = buf->data + buf->first;
277 return err;
278}
diff --git a/vendor/luasec/src/luasocket/buffer.h b/vendor/luasec/src/luasocket/buffer.h
new file mode 100644
index 00000000..1281bb39
--- /dev/null
+++ b/vendor/luasec/src/luasocket/buffer.h
@@ -0,0 +1,45 @@
1#ifndef BUF_H
2#define BUF_H
3/*=========================================================================*\
4* Input/Output interface for Lua programs
5* LuaSocket toolkit
6*
7* Line patterns require buffering. Reading one character at a time involves
8* too many system calls and is very slow. This module implements the
9* LuaSocket interface for input/output on connected objects, as seen by
10* Lua programs.
11*
12* Input is buffered. Output is *not* buffered because there was no simple
13* way of making sure the buffered output data would ever be sent.
14*
15* The module is built on top of the I/O abstraction defined in io.h and the
16* timeout management is done with the timeout.h interface.
17\*=========================================================================*/
18#include "lua.h"
19
20#include "io.h"
21#include "timeout.h"
22
23/* buffer size in bytes */
24#define BUF_SIZE 8192
25
26/* buffer control structure */
27typedef struct t_buffer_ {
28 double birthday; /* throttle support info: creation time, */
29 size_t sent, received; /* bytes sent, and bytes received */
30 p_io io; /* IO driver used for this buffer */
31 p_timeout tm; /* timeout management for this buffer */
32 size_t first, last; /* index of first and last bytes of stored data */
33 char data[BUF_SIZE]; /* storage space for buffer data */
34} t_buffer;
35typedef t_buffer *p_buffer;
36
37int buffer_open(lua_State *L);
38void buffer_init(p_buffer buf, p_io io, p_timeout tm);
39int buffer_meth_send(lua_State *L, p_buffer buf);
40int buffer_meth_receive(lua_State *L, p_buffer buf);
41int buffer_meth_getstats(lua_State *L, p_buffer buf);
42int buffer_meth_setstats(lua_State *L, p_buffer buf);
43int buffer_isempty(p_buffer buf);
44
45#endif /* BUF_H */
diff --git a/vendor/luasec/src/luasocket/io.c b/vendor/luasec/src/luasocket/io.c
new file mode 100644
index 00000000..35f46f78
--- /dev/null
+++ b/vendor/luasec/src/luasocket/io.c
@@ -0,0 +1,30 @@
1/*=========================================================================*\
2* Input/Output abstraction
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "io.h"
6
7/*=========================================================================*\
8* Exported functions
9\*=========================================================================*/
10/*-------------------------------------------------------------------------*\
11* Initializes C structure
12\*-------------------------------------------------------------------------*/
13void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx) {
14 io->send = send;
15 io->recv = recv;
16 io->error = error;
17 io->ctx = ctx;
18}
19
20/*-------------------------------------------------------------------------*\
21* I/O error strings
22\*-------------------------------------------------------------------------*/
23const char *io_strerror(int err) {
24 switch (err) {
25 case IO_DONE: return NULL;
26 case IO_CLOSED: return "closed";
27 case IO_TIMEOUT: return "timeout";
28 default: return "unknown error";
29 }
30}
diff --git a/vendor/luasec/src/luasocket/io.h b/vendor/luasec/src/luasocket/io.h
new file mode 100644
index 00000000..8945e2c0
--- /dev/null
+++ b/vendor/luasec/src/luasocket/io.h
@@ -0,0 +1,65 @@
1#ifndef IO_H
2#define IO_H
3/*=========================================================================*\
4* Input/Output abstraction
5* LuaSocket toolkit
6*
7* This module defines the interface that LuaSocket expects from the
8* transport layer for streamed input/output. The idea is that if any
9* transport implements this interface, then the buffer.c functions
10* automatically work on it.
11*
12* The module socket.h implements this interface, and thus the module tcp.h
13* is very simple.
14\*=========================================================================*/
15#include <stdio.h>
16#include "lua.h"
17
18#include "timeout.h"
19
20/* IO error codes */
21enum {
22 IO_DONE = 0, /* operation completed successfully */
23 IO_TIMEOUT = -1, /* operation timed out */
24 IO_CLOSED = -2, /* the connection has been closed */
25 IO_UNKNOWN = -3
26};
27
28/* interface to error message function */
29typedef const char *(*p_error) (
30 void *ctx, /* context needed by send */
31 int err /* error code */
32);
33
34/* interface to send function */
35typedef int (*p_send) (
36 void *ctx, /* context needed by send */
37 const char *data, /* pointer to buffer with data to send */
38 size_t count, /* number of bytes to send from buffer */
39 size_t *sent, /* number of bytes sent uppon return */
40 p_timeout tm /* timeout control */
41);
42
43/* interface to recv function */
44typedef int (*p_recv) (
45 void *ctx, /* context needed by recv */
46 char *data, /* pointer to buffer where data will be written */
47 size_t count, /* number of bytes to receive into buffer */
48 size_t *got, /* number of bytes received uppon return */
49 p_timeout tm /* timeout control */
50);
51
52/* IO driver definition */
53typedef struct t_io_ {
54 void *ctx; /* context needed by send/recv */
55 p_send send; /* send function pointer */
56 p_recv recv; /* receive function pointer */
57 p_error error; /* strerror function */
58} t_io;
59typedef t_io *p_io;
60
61void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx);
62const char *io_strerror(int err);
63
64#endif /* IO_H */
65
diff --git a/vendor/luasec/src/luasocket/socket.h b/vendor/luasec/src/luasocket/socket.h
new file mode 100644
index 00000000..07c20fe3
--- /dev/null
+++ b/vendor/luasec/src/luasocket/socket.h
@@ -0,0 +1,78 @@
1#ifndef SOCKET_H
2#define SOCKET_H
3/*=========================================================================*\
4* Socket compatibilization module
5* LuaSocket toolkit
6*
7* BSD Sockets and WinSock are similar, but there are a few irritating
8* differences. Also, not all *nix platforms behave the same. This module
9* (and the associated usocket.h and wsocket.h) factor these differences and
10* creates a interface compatible with the io.h module.
11\*=========================================================================*/
12#include "io.h"
13
14/*=========================================================================*\
15* Platform specific compatibilization
16\*=========================================================================*/
17#ifdef _WIN32
18#include "wsocket.h"
19#else
20#include "usocket.h"
21#endif
22
23/*=========================================================================*\
24* The connect and accept functions accept a timeout and their
25* implementations are somewhat complicated. We chose to move
26* the timeout control into this module for these functions in
27* order to simplify the modules that use them.
28\*=========================================================================*/
29#include "timeout.h"
30
31/* we are lazy... */
32typedef struct sockaddr SA;
33
34/*=========================================================================*\
35* Functions below implement a comfortable platform independent
36* interface to sockets
37\*=========================================================================*/
38int socket_open(void);
39int socket_close(void);
40void socket_destroy(p_socket ps);
41void socket_shutdown(p_socket ps, int how);
42int socket_sendto(p_socket ps, const char *data, size_t count,
43 size_t *sent, SA *addr, socklen_t addr_len, p_timeout tm);
44int socket_recvfrom(p_socket ps, char *data, size_t count,
45 size_t *got, SA *addr, socklen_t *addr_len, p_timeout tm);
46
47void socket_setnonblocking(p_socket ps);
48void socket_setblocking(p_socket ps);
49
50int socket_waitfd(p_socket ps, int sw, p_timeout tm);
51int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
52 p_timeout tm);
53
54int socket_connect(p_socket ps, SA *addr, socklen_t addr_len, p_timeout tm);
55int socket_create(p_socket ps, int domain, int type, int protocol);
56int socket_bind(p_socket ps, SA *addr, socklen_t addr_len);
57int socket_listen(p_socket ps, int backlog);
58int socket_accept(p_socket ps, p_socket pa, SA *addr,
59 socklen_t *addr_len, p_timeout tm);
60
61const char *socket_hoststrerror(int err);
62const char *socket_gaistrerror(int err);
63const char *socket_strerror(int err);
64
65/* these are perfect to use with the io abstraction module
66 and the buffered input module */
67int socket_send(p_socket ps, const char *data, size_t count,
68 size_t *sent, p_timeout tm);
69int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm);
70int socket_write(p_socket ps, const char *data, size_t count,
71 size_t *sent, p_timeout tm);
72int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm);
73const char *socket_ioerror(p_socket ps, int err);
74
75int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp);
76int socket_gethostbyname(const char *addr, struct hostent **hp);
77
78#endif /* SOCKET_H */
diff --git a/vendor/luasec/src/luasocket/timeout.c b/vendor/luasec/src/luasocket/timeout.c
new file mode 100644
index 00000000..94a524be
--- /dev/null
+++ b/vendor/luasec/src/luasocket/timeout.c
@@ -0,0 +1,220 @@
1/*=========================================================================*\
2* Timeout management functions
3* LuaSocket toolkit
4\*=========================================================================*/
5#include <stdio.h>
6#include <limits.h>
7#include <float.h>
8
9#include "lua.h"
10#include "lauxlib.h"
11
12#include "timeout.h"
13
14#ifdef _WIN32
15#include <windows.h>
16#else
17#include <time.h>
18#include <sys/time.h>
19#endif
20
21/* min and max macros */
22#ifndef MIN
23#define MIN(x, y) ((x) < (y) ? x : y)
24#endif
25#ifndef MAX
26#define MAX(x, y) ((x) > (y) ? x : y)
27#endif
28
29/*=========================================================================*\
30* Internal function prototypes
31\*=========================================================================*/
32static int timeout_lua_gettime(lua_State *L);
33static int timeout_lua_sleep(lua_State *L);
34
35static luaL_Reg func[] = {
36 { "gettime", timeout_lua_gettime },
37 { "sleep", timeout_lua_sleep },
38 { NULL, NULL }
39};
40
41/*=========================================================================*\
42* Exported functions.
43\*=========================================================================*/
44/*-------------------------------------------------------------------------*\
45* Initialize structure
46\*-------------------------------------------------------------------------*/
47void timeout_init(p_timeout tm, double block, double total) {
48 tm->block = block;
49 tm->total = total;
50}
51
52/*-------------------------------------------------------------------------*\
53* Determines how much time we have left for the next system call,
54* if the previous call was successful
55* Input
56* tm: timeout control structure
57* Returns
58* the number of ms left or -1 if there is no time limit
59\*-------------------------------------------------------------------------*/
60double timeout_get(p_timeout tm) {
61 if (tm->block < 0.0 && tm->total < 0.0) {
62 return -1;
63 } else if (tm->block < 0.0) {
64 double t = tm->total - timeout_gettime() + tm->start;
65 return MAX(t, 0.0);
66 } else if (tm->total < 0.0) {
67 return tm->block;
68 } else {
69 double t = tm->total - timeout_gettime() + tm->start;
70 return MIN(tm->block, MAX(t, 0.0));
71 }
72}
73
74/*-------------------------------------------------------------------------*\
75* Returns time since start of operation
76* Input
77* tm: timeout control structure
78* Returns
79* start field of structure
80\*-------------------------------------------------------------------------*/
81double timeout_getstart(p_timeout tm) {
82 return tm->start;
83}
84
85/*-------------------------------------------------------------------------*\
86* Determines how much time we have left for the next system call,
87* if the previous call was a failure
88* Input
89* tm: timeout control structure
90* Returns
91* the number of ms left or -1 if there is no time limit
92\*-------------------------------------------------------------------------*/
93double timeout_getretry(p_timeout tm) {
94 if (tm->block < 0.0 && tm->total < 0.0) {
95 return -1;
96 } else if (tm->block < 0.0) {
97 double t = tm->total - timeout_gettime() + tm->start;
98 return MAX(t, 0.0);
99 } else if (tm->total < 0.0) {
100 double t = tm->block - timeout_gettime() + tm->start;
101 return MAX(t, 0.0);
102 } else {
103 double t = tm->total - timeout_gettime() + tm->start;
104 return MIN(tm->block, MAX(t, 0.0));
105 }
106}
107
108/*-------------------------------------------------------------------------*\
109* Marks the operation start time in structure
110* Input
111* tm: timeout control structure
112\*-------------------------------------------------------------------------*/
113p_timeout timeout_markstart(p_timeout tm) {
114 tm->start = timeout_gettime();
115 return tm;
116}
117
118/*-------------------------------------------------------------------------*\
119* Gets time in s, relative to January 1, 1970 (UTC)
120* Returns
121* time in s.
122\*-------------------------------------------------------------------------*/
123#ifdef _WIN32
124double timeout_gettime(void) {
125 FILETIME ft;
126 double t;
127 GetSystemTimeAsFileTime(&ft);
128 /* Windows file time (time since January 1, 1601 (UTC)) */
129 t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7);
130 /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */
131 return (t - 11644473600.0);
132}
133#else
134double timeout_gettime(void) {
135 struct timeval v;
136 gettimeofday(&v, (struct timezone *) NULL);
137 /* Unix Epoch time (time since January 1, 1970 (UTC)) */
138 return v.tv_sec + v.tv_usec/1.0e6;
139}
140#endif
141
142/*-------------------------------------------------------------------------*\
143* Initializes module
144\*-------------------------------------------------------------------------*/
145int timeout_open(lua_State *L) {
146#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
147 luaL_setfuncs(L, func, 0);
148#else
149 luaL_openlib(L, NULL, func, 0);
150#endif
151 return 0;
152}
153
154/*-------------------------------------------------------------------------*\
155* Sets timeout values for IO operations
156* Lua Input: base, time [, mode]
157* time: time out value in seconds
158* mode: "b" for block timeout, "t" for total timeout. (default: b)
159\*-------------------------------------------------------------------------*/
160int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
161 double t = luaL_optnumber(L, 2, -1);
162 const char *mode = luaL_optstring(L, 3, "b");
163 switch (*mode) {
164 case 'b':
165 tm->block = t;
166 break;
167 case 'r': case 't':
168 tm->total = t;
169 break;
170 default:
171 luaL_argcheck(L, 0, 3, "invalid timeout mode");
172 break;
173 }
174 lua_pushnumber(L, 1);
175 return 1;
176}
177
178/*=========================================================================*\
179* Test support functions
180\*=========================================================================*/
181/*-------------------------------------------------------------------------*\
182* Returns the time the system has been up, in secconds.
183\*-------------------------------------------------------------------------*/
184static int timeout_lua_gettime(lua_State *L)
185{
186 lua_pushnumber(L, timeout_gettime());
187 return 1;
188}
189
190/*-------------------------------------------------------------------------*\
191* Sleep for n seconds.
192\*-------------------------------------------------------------------------*/
193#ifdef _WIN32
194int timeout_lua_sleep(lua_State *L)
195{
196 double n = luaL_checknumber(L, 1);
197 if (n < 0.0) n = 0.0;
198 if (n < DBL_MAX/1000.0) n *= 1000.0;
199 if (n > INT_MAX) n = INT_MAX;
200 Sleep((int)n);
201 return 0;
202}
203#else
204int timeout_lua_sleep(lua_State *L)
205{
206 double n = luaL_checknumber(L, 1);
207 struct timespec t, r;
208 if (n < 0.0) n = 0.0;
209 if (n > INT_MAX) n = INT_MAX;
210 t.tv_sec = (int) n;
211 n -= t.tv_sec;
212 t.tv_nsec = (int) (n * 1000000000);
213 if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999;
214 while (nanosleep(&t, &r) != 0) {
215 t.tv_sec = r.tv_sec;
216 t.tv_nsec = r.tv_nsec;
217 }
218 return 0;
219}
220#endif
diff --git a/vendor/luasec/src/luasocket/timeout.h b/vendor/luasec/src/luasocket/timeout.h
new file mode 100644
index 00000000..4957593b
--- /dev/null
+++ b/vendor/luasec/src/luasocket/timeout.h
@@ -0,0 +1,28 @@
1#ifndef TIMEOUT_H
2#define TIMEOUT_H
3/*=========================================================================*\
4* Timeout management functions
5* LuaSocket toolkit
6\*=========================================================================*/
7#include "lua.h"
8
9/* timeout control structure */
10typedef struct t_timeout_ {
11 double block; /* maximum time for blocking calls */
12 double total; /* total number of milliseconds for operation */
13 double start; /* time of start of operation */
14} t_timeout;
15typedef t_timeout *p_timeout;
16
17int timeout_open(lua_State *L);
18void timeout_init(p_timeout tm, double block, double total);
19double timeout_get(p_timeout tm);
20double timeout_getretry(p_timeout tm);
21p_timeout timeout_markstart(p_timeout tm);
22double timeout_getstart(p_timeout tm);
23double timeout_gettime(void);
24int timeout_meth_settimeout(lua_State *L, p_timeout tm);
25
26#define timeout_iszero(tm) ((tm)->block == 0.0)
27
28#endif /* TIMEOUT_H */
diff --git a/vendor/luasec/src/luasocket/usocket.c b/vendor/luasec/src/luasocket/usocket.c
new file mode 100644
index 00000000..49e618c4
--- /dev/null
+++ b/vendor/luasec/src/luasocket/usocket.c
@@ -0,0 +1,441 @@
1/*=========================================================================*\
2* Socket compatibilization module for Unix
3* LuaSocket toolkit
4*
5* The code is now interrupt-safe.
6* The penalty of calling select to avoid busy-wait is only paid when
7* the I/O call fail in the first place.
8\*=========================================================================*/
9#include <string.h>
10#include <signal.h>
11
12#include "socket.h"
13
14/*-------------------------------------------------------------------------*\
15* Wait for readable/writable/connected socket with timeout
16\*-------------------------------------------------------------------------*/
17#ifndef SOCKET_SELECT
18int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
19 int ret;
20 struct pollfd pfd;
21 pfd.fd = *ps;
22 pfd.events = sw;
23 pfd.revents = 0;
24 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
25 do {
26 int t = (int)(timeout_getretry(tm)*1e3);
27 ret = poll(&pfd, 1, t >= 0? t: -1);
28 } while (ret == -1 && errno == EINTR);
29 if (ret == -1) return errno;
30 if (ret == 0) return IO_TIMEOUT;
31 if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED;
32 return IO_DONE;
33}
34#else
35int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
36 int ret;
37 fd_set rfds, wfds, *rp, *wp;
38 struct timeval tv, *tp;
39 double t;
40 if (*ps >= FD_SETSIZE) return EINVAL;
41 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
42 do {
43 /* must set bits within loop, because select may have modified them */
44 rp = wp = NULL;
45 if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; }
46 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
47 t = timeout_getretry(tm);
48 tp = NULL;
49 if (t >= 0.0) {
50 tv.tv_sec = (int)t;
51 tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6);
52 tp = &tv;
53 }
54 ret = select(*ps+1, rp, wp, NULL, tp);
55 } while (ret == -1 && errno == EINTR);
56 if (ret == -1) return errno;
57 if (ret == 0) return IO_TIMEOUT;
58 if (sw == WAITFD_C && FD_ISSET(*ps, &rfds)) return IO_CLOSED;
59 return IO_DONE;
60}
61#endif
62
63
64/*-------------------------------------------------------------------------*\
65* Initializes module
66\*-------------------------------------------------------------------------*/
67int socket_open(void) {
68 /* instals a handler to ignore sigpipe or it will crash us */
69 signal(SIGPIPE, SIG_IGN);
70 return 1;
71}
72
73/*-------------------------------------------------------------------------*\
74* Close module
75\*-------------------------------------------------------------------------*/
76int socket_close(void) {
77 return 1;
78}
79
80/*-------------------------------------------------------------------------*\
81* Close and inutilize socket
82\*-------------------------------------------------------------------------*/
83void socket_destroy(p_socket ps) {
84 if (*ps != SOCKET_INVALID) {
85 socket_setblocking(ps);
86 close(*ps);
87 *ps = SOCKET_INVALID;
88 }
89}
90
91/*-------------------------------------------------------------------------*\
92* Select with timeout control
93\*-------------------------------------------------------------------------*/
94int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
95 p_timeout tm) {
96 int ret;
97 do {
98 struct timeval tv;
99 double t = timeout_getretry(tm);
100 tv.tv_sec = (int) t;
101 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
102 /* timeout = 0 means no wait */
103 ret = select(n, rfds, wfds, efds, t >= 0.0 ? &tv: NULL);
104 } while (ret < 0 && errno == EINTR);
105 return ret;
106}
107
108/*-------------------------------------------------------------------------*\
109* Creates and sets up a socket
110\*-------------------------------------------------------------------------*/
111int socket_create(p_socket ps, int domain, int type, int protocol) {
112 *ps = socket(domain, type, protocol);
113 if (*ps != SOCKET_INVALID) return IO_DONE;
114 else return errno;
115}
116
117/*-------------------------------------------------------------------------*\
118* Binds or returns error message
119\*-------------------------------------------------------------------------*/
120int socket_bind(p_socket ps, SA *addr, socklen_t len) {
121 int err = IO_DONE;
122 socket_setblocking(ps);
123 if (bind(*ps, addr, len) < 0) err = errno;
124 socket_setnonblocking(ps);
125 return err;
126}
127
128/*-------------------------------------------------------------------------*\
129*
130\*-------------------------------------------------------------------------*/
131int socket_listen(p_socket ps, int backlog) {
132 int err = IO_DONE;
133 socket_setblocking(ps);
134 if (listen(*ps, backlog)) err = errno;
135 socket_setnonblocking(ps);
136 return err;
137}
138
139/*-------------------------------------------------------------------------*\
140*
141\*-------------------------------------------------------------------------*/
142void socket_shutdown(p_socket ps, int how) {
143 socket_setblocking(ps);
144 shutdown(*ps, how);
145 socket_setnonblocking(ps);
146}
147
148/*-------------------------------------------------------------------------*\
149* Connects or returns error message
150\*-------------------------------------------------------------------------*/
151int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
152 int err;
153 /* avoid calling on closed sockets */
154 if (*ps == SOCKET_INVALID) return IO_CLOSED;
155 /* call connect until done or failed without being interrupted */
156 do if (connect(*ps, addr, len) == 0) return IO_DONE;
157 while ((err = errno) == EINTR);
158 /* if connection failed immediately, return error code */
159 if (err != EINPROGRESS && err != EAGAIN) return err;
160 /* zero timeout case optimization */
161 if (timeout_iszero(tm)) return IO_TIMEOUT;
162 /* wait until we have the result of the connection attempt or timeout */
163 err = socket_waitfd(ps, WAITFD_C, tm);
164 if (err == IO_CLOSED) {
165 if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE;
166 else return errno;
167 } else return err;
168}
169
170/*-------------------------------------------------------------------------*\
171* Accept with timeout
172\*-------------------------------------------------------------------------*/
173int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) {
174 if (*ps == SOCKET_INVALID) return IO_CLOSED;
175 for ( ;; ) {
176 int err;
177 if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE;
178 err = errno;
179 if (err == EINTR) continue;
180 if (err != EAGAIN && err != ECONNABORTED) return err;
181 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
182 }
183 /* can't reach here */
184 return IO_UNKNOWN;
185}
186
187/*-------------------------------------------------------------------------*\
188* Send with timeout
189\*-------------------------------------------------------------------------*/
190int socket_send(p_socket ps, const char *data, size_t count,
191 size_t *sent, p_timeout tm)
192{
193 int err;
194 *sent = 0;
195 /* avoid making system calls on closed sockets */
196 if (*ps == SOCKET_INVALID) return IO_CLOSED;
197 /* loop until we send something or we give up on error */
198 for ( ;; ) {
199 long put = (long) send(*ps, data, count, 0);
200 /* if we sent anything, we are done */
201 if (put >= 0) {
202 *sent = put;
203 return IO_DONE;
204 }
205 err = errno;
206 /* EPIPE means the connection was closed */
207 if (err == EPIPE) return IO_CLOSED;
208 /* we call was interrupted, just try again */
209 if (err == EINTR) continue;
210 /* if failed fatal reason, report error */
211 if (err != EAGAIN) return err;
212 /* wait until we can send something or we timeout */
213 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
214 }
215 /* can't reach here */
216 return IO_UNKNOWN;
217}
218
219/*-------------------------------------------------------------------------*\
220* Sendto with timeout
221\*-------------------------------------------------------------------------*/
222int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
223 SA *addr, socklen_t len, p_timeout tm)
224{
225 int err;
226 *sent = 0;
227 if (*ps == SOCKET_INVALID) return IO_CLOSED;
228 for ( ;; ) {
229 long put = (long) sendto(*ps, data, count, 0, addr, len);
230 if (put >= 0) {
231 *sent = put;
232 return IO_DONE;
233 }
234 err = errno;
235 if (err == EPIPE) return IO_CLOSED;
236 if (err == EINTR) continue;
237 if (err != EAGAIN) return err;
238 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
239 }
240 return IO_UNKNOWN;
241}
242
243/*-------------------------------------------------------------------------*\
244* Receive with timeout
245\*-------------------------------------------------------------------------*/
246int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) {
247 int err;
248 *got = 0;
249 if (*ps == SOCKET_INVALID) return IO_CLOSED;
250 for ( ;; ) {
251 long taken = (long) recv(*ps, data, count, 0);
252 if (taken > 0) {
253 *got = taken;
254 return IO_DONE;
255 }
256 err = errno;
257 if (taken == 0) return IO_CLOSED;
258 if (err == EINTR) continue;
259 if (err != EAGAIN) return err;
260 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
261 }
262 return IO_UNKNOWN;
263}
264
265/*-------------------------------------------------------------------------*\
266* Recvfrom with timeout
267\*-------------------------------------------------------------------------*/
268int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
269 SA *addr, socklen_t *len, p_timeout tm) {
270 int err;
271 *got = 0;
272 if (*ps == SOCKET_INVALID) return IO_CLOSED;
273 for ( ;; ) {
274 long taken = (long) recvfrom(*ps, data, count, 0, addr, len);
275 if (taken > 0) {
276 *got = taken;
277 return IO_DONE;
278 }
279 err = errno;
280 if (taken == 0) return IO_CLOSED;
281 if (err == EINTR) continue;
282 if (err != EAGAIN) return err;
283 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
284 }
285 return IO_UNKNOWN;
286}
287
288
289/*-------------------------------------------------------------------------*\
290* Write with timeout
291*
292* socket_read and socket_write are cut-n-paste of socket_send and socket_recv,
293* with send/recv replaced with write/read. We can't just use write/read
294* in the socket version, because behaviour when size is zero is different.
295\*-------------------------------------------------------------------------*/
296int socket_write(p_socket ps, const char *data, size_t count,
297 size_t *sent, p_timeout tm)
298{
299 int err;
300 *sent = 0;
301 /* avoid making system calls on closed sockets */
302 if (*ps == SOCKET_INVALID) return IO_CLOSED;
303 /* loop until we send something or we give up on error */
304 for ( ;; ) {
305 long put = (long) write(*ps, data, count);
306 /* if we sent anything, we are done */
307 if (put >= 0) {
308 *sent = put;
309 return IO_DONE;
310 }
311 err = errno;
312 /* EPIPE means the connection was closed */
313 if (err == EPIPE) return IO_CLOSED;
314 /* we call was interrupted, just try again */
315 if (err == EINTR) continue;
316 /* if failed fatal reason, report error */
317 if (err != EAGAIN) return err;
318 /* wait until we can send something or we timeout */
319 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
320 }
321 /* can't reach here */
322 return IO_UNKNOWN;
323}
324
325/*-------------------------------------------------------------------------*\
326* Read with timeout
327* See note for socket_write
328\*-------------------------------------------------------------------------*/
329int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) {
330 int err;
331 *got = 0;
332 if (*ps == SOCKET_INVALID) return IO_CLOSED;
333 for ( ;; ) {
334 long taken = (long) read(*ps, data, count);
335 if (taken > 0) {
336 *got = taken;
337 return IO_DONE;
338 }
339 err = errno;
340 if (taken == 0) return IO_CLOSED;
341 if (err == EINTR) continue;
342 if (err != EAGAIN) return err;
343 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
344 }
345 return IO_UNKNOWN;
346}
347
348/*-------------------------------------------------------------------------*\
349* Put socket into blocking mode
350\*-------------------------------------------------------------------------*/
351void socket_setblocking(p_socket ps) {
352 int flags = fcntl(*ps, F_GETFL, 0);
353 flags &= (~(O_NONBLOCK));
354 fcntl(*ps, F_SETFL, flags);
355}
356
357/*-------------------------------------------------------------------------*\
358* Put socket into non-blocking mode
359\*-------------------------------------------------------------------------*/
360void socket_setnonblocking(p_socket ps) {
361 int flags = fcntl(*ps, F_GETFL, 0);
362 flags |= O_NONBLOCK;
363 fcntl(*ps, F_SETFL, flags);
364}
365
366/*-------------------------------------------------------------------------*\
367* DNS helpers
368\*-------------------------------------------------------------------------*/
369int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
370 *hp = gethostbyaddr(addr, len, AF_INET);
371 if (*hp) return IO_DONE;
372 else if (h_errno) return h_errno;
373 else if (errno) return errno;
374 else return IO_UNKNOWN;
375}
376
377int socket_gethostbyname(const char *addr, struct hostent **hp) {
378 *hp = gethostbyname(addr);
379 if (*hp) return IO_DONE;
380 else if (h_errno) return h_errno;
381 else if (errno) return errno;
382 else return IO_UNKNOWN;
383}
384
385/*-------------------------------------------------------------------------*\
386* Error translation functions
387* Make sure important error messages are standard
388\*-------------------------------------------------------------------------*/
389const char *socket_hoststrerror(int err) {
390 if (err <= 0) return io_strerror(err);
391 switch (err) {
392 case HOST_NOT_FOUND: return "host not found";
393 default: return hstrerror(err);
394 }
395}
396
397const char *socket_strerror(int err) {
398 if (err <= 0) return io_strerror(err);
399 switch (err) {
400 case EADDRINUSE: return "address already in use";
401 case EISCONN: return "already connected";
402 case EACCES: return "permission denied";
403 case ECONNREFUSED: return "connection refused";
404 case ECONNABORTED: return "closed";
405 case ECONNRESET: return "closed";
406 case ETIMEDOUT: return "timeout";
407 default: return strerror(err);
408 }
409}
410
411const char *socket_ioerror(p_socket ps, int err) {
412 (void) ps;
413 return socket_strerror(err);
414}
415
416const char *socket_gaistrerror(int err) {
417 if (err == 0) return NULL;
418 switch (err) {
419 case EAI_AGAIN: return "temporary failure in name resolution";
420 case EAI_BADFLAGS: return "invalid value for ai_flags";
421#ifdef EAI_BADHINTS
422 case EAI_BADHINTS: return "invalid value for hints";
423#endif
424 case EAI_FAIL: return "non-recoverable failure in name resolution";
425 case EAI_FAMILY: return "ai_family not supported";
426 case EAI_MEMORY: return "memory allocation failure";
427 case EAI_NONAME:
428 return "host or service not provided, or not known";
429#ifdef EAI_OVERFLOW
430 case EAI_OVERFLOW: return "argument buffer overflow";
431#endif
432#ifdef EAI_PROTOCOL
433 case EAI_PROTOCOL: return "resolved protocol is unknown";
434#endif
435 case EAI_SERVICE: return "service not supported for socket type";
436 case EAI_SOCKTYPE: return "ai_socktype not supported";
437 case EAI_SYSTEM: return strerror(errno);
438 default: return gai_strerror(err);
439 }
440}
441
diff --git a/vendor/luasec/src/luasocket/usocket.h b/vendor/luasec/src/luasocket/usocket.h
new file mode 100644
index 00000000..ecbcd8e5
--- /dev/null
+++ b/vendor/luasec/src/luasocket/usocket.h
@@ -0,0 +1,70 @@
1#ifndef USOCKET_H
2#define USOCKET_H
3/*=========================================================================*\
4* Socket compatibilization module for Unix
5* LuaSocket toolkit
6\*=========================================================================*/
7
8/*=========================================================================*\
9* BSD include files
10\*=========================================================================*/
11/* error codes */
12#include <errno.h>
13/* close function */
14#include <unistd.h>
15/* fnctnl function and associated constants */
16#include <fcntl.h>
17/* struct sockaddr */
18#include <sys/types.h>
19/* socket function */
20#include <sys/socket.h>
21/* struct timeval */
22#include <sys/time.h>
23/* gethostbyname and gethostbyaddr functions */
24#include <netdb.h>
25/* sigpipe handling */
26#include <signal.h>
27/* IP stuff*/
28#include <netinet/in.h>
29#include <arpa/inet.h>
30/* TCP options (nagle algorithm disable) */
31#include <netinet/tcp.h>
32#include <net/if.h>
33
34#ifndef SOCKET_SELECT
35#include <sys/poll.h>
36#define WAITFD_R POLLIN
37#define WAITFD_W POLLOUT
38#define WAITFD_C (POLLIN|POLLOUT)
39#else
40#define WAITFD_R 1
41#define WAITFD_W 2
42#define WAITFD_C (WAITFD_R|WAITFD_W)
43#endif
44
45#ifndef SO_REUSEPORT
46#define SO_REUSEPORT SO_REUSEADDR
47#endif
48
49/* Some platforms use IPV6_JOIN_GROUP instead if
50 * IPV6_ADD_MEMBERSHIP. The semantics are same, though. */
51#ifndef IPV6_ADD_MEMBERSHIP
52#ifdef IPV6_JOIN_GROUP
53#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
54#endif /* IPV6_JOIN_GROUP */
55#endif /* !IPV6_ADD_MEMBERSHIP */
56
57/* Same with IPV6_DROP_MEMBERSHIP / IPV6_LEAVE_GROUP. */
58#ifndef IPV6_DROP_MEMBERSHIP
59#ifdef IPV6_LEAVE_GROUP
60#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
61#endif /* IPV6_LEAVE_GROUP */
62#endif /* !IPV6_DROP_MEMBERSHIP */
63
64typedef int t_socket;
65typedef t_socket *p_socket;
66typedef struct sockaddr_storage t_sockaddr_storage;
67
68#define SOCKET_INVALID (-1)
69
70#endif /* USOCKET_H */
diff --git a/vendor/luasec/src/luasocket/wsocket.c b/vendor/luasec/src/luasocket/wsocket.c
new file mode 100644
index 00000000..8c7640eb
--- /dev/null
+++ b/vendor/luasec/src/luasocket/wsocket.c
@@ -0,0 +1,429 @@
1/*=========================================================================*\
2* Socket compatibilization module for Win32
3* LuaSocket toolkit
4*
5* The penalty of calling select to avoid busy-wait is only paid when
6* the I/O call fail in the first place.
7\*=========================================================================*/
8#include <string.h>
9
10#include "socket.h"
11
12/* WinSock doesn't have a strerror... */
13static const char *wstrerror(int err);
14
15/*-------------------------------------------------------------------------*\
16* Initializes module
17\*-------------------------------------------------------------------------*/
18int socket_open(void) {
19 WSADATA wsaData;
20 WORD wVersionRequested = MAKEWORD(2, 0);
21 int err = WSAStartup(wVersionRequested, &wsaData );
22 if (err != 0) return 0;
23 if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) &&
24 (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) {
25 WSACleanup();
26 return 0;
27 }
28 return 1;
29}
30
31/*-------------------------------------------------------------------------*\
32* Close module
33\*-------------------------------------------------------------------------*/
34int socket_close(void) {
35 WSACleanup();
36 return 1;
37}
38
39/*-------------------------------------------------------------------------*\
40* Wait for readable/writable/connected socket with timeout
41\*-------------------------------------------------------------------------*/
42int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
43 int ret;
44 fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL;
45 struct timeval tv, *tp = NULL;
46 double t;
47 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
48 if (sw & WAITFD_R) {
49 FD_ZERO(&rfds);
50 FD_SET(*ps, &rfds);
51 rp = &rfds;
52 }
53 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
54 if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; }
55 if ((t = timeout_get(tm)) >= 0.0) {
56 tv.tv_sec = (int) t;
57 tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6);
58 tp = &tv;
59 }
60 ret = select(0, rp, wp, ep, tp);
61 if (ret == -1) return WSAGetLastError();
62 if (ret == 0) return IO_TIMEOUT;
63 if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED;
64 return IO_DONE;
65}
66
67/*-------------------------------------------------------------------------*\
68* Select with int timeout in ms
69\*-------------------------------------------------------------------------*/
70int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
71 p_timeout tm) {
72 struct timeval tv;
73 double t = timeout_get(tm);
74 tv.tv_sec = (int) t;
75 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
76 if (n <= 0) {
77 Sleep((DWORD) (1000*t));
78 return 0;
79 } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL);
80}
81
82/*-------------------------------------------------------------------------*\
83* Close and inutilize socket
84\*-------------------------------------------------------------------------*/
85void socket_destroy(p_socket ps) {
86 if (*ps != SOCKET_INVALID) {
87 socket_setblocking(ps); /* close can take a long time on WIN32 */
88 closesocket(*ps);
89 *ps = SOCKET_INVALID;
90 }
91}
92
93/*-------------------------------------------------------------------------*\
94*
95\*-------------------------------------------------------------------------*/
96void socket_shutdown(p_socket ps, int how) {
97 socket_setblocking(ps);
98 shutdown(*ps, how);
99 socket_setnonblocking(ps);
100}
101
102/*-------------------------------------------------------------------------*\
103* Creates and sets up a socket
104\*-------------------------------------------------------------------------*/
105int socket_create(p_socket ps, int domain, int type, int protocol) {
106 *ps = socket(domain, type, protocol);
107 if (*ps != SOCKET_INVALID) return IO_DONE;
108 else return WSAGetLastError();
109}
110
111/*-------------------------------------------------------------------------*\
112* Connects or returns error message
113\*-------------------------------------------------------------------------*/
114int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
115 int err;
116 /* don't call on closed socket */
117 if (*ps == SOCKET_INVALID) return IO_CLOSED;
118 /* ask system to connect */
119 if (connect(*ps, addr, len) == 0) return IO_DONE;
120 /* make sure the system is trying to connect */
121 err = WSAGetLastError();
122 if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err;
123 /* zero timeout case optimization */
124 if (timeout_iszero(tm)) return IO_TIMEOUT;
125 /* we wait until something happens */
126 err = socket_waitfd(ps, WAITFD_C, tm);
127 if (err == IO_CLOSED) {
128 int len = sizeof(err);
129 /* give windows time to set the error (yes, disgusting) */
130 Sleep(10);
131 /* find out why we failed */
132 getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
133 /* we KNOW there was an error. if 'why' is 0, we will return
134 * "unknown error", but it's not really our fault */
135 return err > 0? err: IO_UNKNOWN;
136 } else return err;
137
138}
139
140/*-------------------------------------------------------------------------*\
141* Binds or returns error message
142\*-------------------------------------------------------------------------*/
143int socket_bind(p_socket ps, SA *addr, socklen_t len) {
144 int err = IO_DONE;
145 socket_setblocking(ps);
146 if (bind(*ps, addr, len) < 0) err = WSAGetLastError();
147 socket_setnonblocking(ps);
148 return err;
149}
150
151/*-------------------------------------------------------------------------*\
152*
153\*-------------------------------------------------------------------------*/
154int socket_listen(p_socket ps, int backlog) {
155 int err = IO_DONE;
156 socket_setblocking(ps);
157 if (listen(*ps, backlog) < 0) err = WSAGetLastError();
158 socket_setnonblocking(ps);
159 return err;
160}
161
162/*-------------------------------------------------------------------------*\
163* Accept with timeout
164\*-------------------------------------------------------------------------*/
165int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len,
166 p_timeout tm) {
167 if (*ps == SOCKET_INVALID) return IO_CLOSED;
168 for ( ;; ) {
169 int err;
170 /* try to get client socket */
171 if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE;
172 /* find out why we failed */
173 err = WSAGetLastError();
174 /* if we failed because there was no connectoin, keep trying */
175 if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err;
176 /* call select to avoid busy wait */
177 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
178 }
179}
180
181/*-------------------------------------------------------------------------*\
182* Send with timeout
183* On windows, if you try to send 10MB, the OS will buffer EVERYTHING
184* this can take an awful lot of time and we will end up blocked.
185* Therefore, whoever calls this function should not pass a huge buffer.
186\*-------------------------------------------------------------------------*/
187int socket_send(p_socket ps, const char *data, size_t count,
188 size_t *sent, p_timeout tm)
189{
190 int err;
191 *sent = 0;
192 /* avoid making system calls on closed sockets */
193 if (*ps == SOCKET_INVALID) return IO_CLOSED;
194 /* loop until we send something or we give up on error */
195 for ( ;; ) {
196 /* try to send something */
197 int put = send(*ps, data, (int) count, 0);
198 /* if we sent something, we are done */
199 if (put > 0) {
200 *sent = put;
201 return IO_DONE;
202 }
203 /* deal with failure */
204 err = WSAGetLastError();
205 /* we can only proceed if there was no serious error */
206 if (err != WSAEWOULDBLOCK) return err;
207 /* avoid busy wait */
208 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
209 }
210}
211
212/*-------------------------------------------------------------------------*\
213* Sendto with timeout
214\*-------------------------------------------------------------------------*/
215int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
216 SA *addr, socklen_t len, p_timeout tm)
217{
218 int err;
219 *sent = 0;
220 if (*ps == SOCKET_INVALID) return IO_CLOSED;
221 for ( ;; ) {
222 int put = sendto(*ps, data, (int) count, 0, addr, len);
223 if (put > 0) {
224 *sent = put;
225 return IO_DONE;
226 }
227 err = WSAGetLastError();
228 if (err != WSAEWOULDBLOCK) return err;
229 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
230 }
231}
232
233/*-------------------------------------------------------------------------*\
234* Receive with timeout
235\*-------------------------------------------------------------------------*/
236int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
237 p_timeout tm)
238{
239 int err, prev = IO_DONE;
240 *got = 0;
241 if (*ps == SOCKET_INVALID) return IO_CLOSED;
242 for ( ;; ) {
243 int taken = recv(*ps, data, (int) count, 0);
244 if (taken > 0) {
245 *got = taken;
246 return IO_DONE;
247 }
248 if (taken == 0) return IO_CLOSED;
249 err = WSAGetLastError();
250 /* On UDP, a connreset simply means the previous send failed.
251 * So we try again.
252 * On TCP, it means our socket is now useless, so the error passes.
253 * (We will loop again, exiting because the same error will happen) */
254 if (err != WSAEWOULDBLOCK) {
255 if (err != WSAECONNRESET || prev == WSAECONNRESET) return err;
256 prev = err;
257 }
258 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
259 }
260}
261
262/*-------------------------------------------------------------------------*\
263* Recvfrom with timeout
264\*-------------------------------------------------------------------------*/
265int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
266 SA *addr, socklen_t *len, p_timeout tm)
267{
268 int err, prev = IO_DONE;
269 *got = 0;
270 if (*ps == SOCKET_INVALID) return IO_CLOSED;
271 for ( ;; ) {
272 int taken = recvfrom(*ps, data, (int) count, 0, addr, len);
273 if (taken > 0) {
274 *got = taken;
275 return IO_DONE;
276 }
277 if (taken == 0) return IO_CLOSED;
278 err = WSAGetLastError();
279 /* On UDP, a connreset simply means the previous send failed.
280 * So we try again.
281 * On TCP, it means our socket is now useless, so the error passes.
282 * (We will loop again, exiting because the same error will happen) */
283 if (err != WSAEWOULDBLOCK) {
284 if (err != WSAECONNRESET || prev == WSAECONNRESET) return err;
285 prev = err;
286 }
287 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
288 }
289}
290
291/*-------------------------------------------------------------------------*\
292* Put socket into blocking mode
293\*-------------------------------------------------------------------------*/
294void socket_setblocking(p_socket ps) {
295 u_long argp = 0;
296 ioctlsocket(*ps, FIONBIO, &argp);
297}
298
299/*-------------------------------------------------------------------------*\
300* Put socket into non-blocking mode
301\*-------------------------------------------------------------------------*/
302void socket_setnonblocking(p_socket ps) {
303 u_long argp = 1;
304 ioctlsocket(*ps, FIONBIO, &argp);
305}
306
307/*-------------------------------------------------------------------------*\
308* DNS helpers
309\*-------------------------------------------------------------------------*/
310int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
311 *hp = gethostbyaddr(addr, len, AF_INET);
312 if (*hp) return IO_DONE;
313 else return WSAGetLastError();
314}
315
316int socket_gethostbyname(const char *addr, struct hostent **hp) {
317 *hp = gethostbyname(addr);
318 if (*hp) return IO_DONE;
319 else return WSAGetLastError();
320}
321
322/*-------------------------------------------------------------------------*\
323* Error translation functions
324\*-------------------------------------------------------------------------*/
325const char *socket_hoststrerror(int err) {
326 if (err <= 0) return io_strerror(err);
327 switch (err) {
328 case WSAHOST_NOT_FOUND: return "host not found";
329 default: return wstrerror(err);
330 }
331}
332
333const char *socket_strerror(int err) {
334 if (err <= 0) return io_strerror(err);
335 switch (err) {
336 case WSAEADDRINUSE: return "address already in use";
337 case WSAECONNREFUSED: return "connection refused";
338 case WSAEISCONN: return "already connected";
339 case WSAEACCES: return "permission denied";
340 case WSAECONNABORTED: return "closed";
341 case WSAECONNRESET: return "closed";
342 case WSAETIMEDOUT: return "timeout";
343 default: return wstrerror(err);
344 }
345}
346
347const char *socket_ioerror(p_socket ps, int err) {
348 (void) ps;
349 return socket_strerror(err);
350}
351
352static const char *wstrerror(int err) {
353 switch (err) {
354 case WSAEINTR: return "Interrupted function call";
355 case WSAEACCES: return "Permission denied";
356 case WSAEFAULT: return "Bad address";
357 case WSAEINVAL: return "Invalid argument";
358 case WSAEMFILE: return "Too many open files";
359 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
360 case WSAEINPROGRESS: return "Operation now in progress";
361 case WSAEALREADY: return "Operation already in progress";
362 case WSAENOTSOCK: return "Socket operation on nonsocket";
363 case WSAEDESTADDRREQ: return "Destination address required";
364 case WSAEMSGSIZE: return "Message too long";
365 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
366 case WSAENOPROTOOPT: return "Bad protocol option";
367 case WSAEPROTONOSUPPORT: return "Protocol not supported";
368 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
369 case WSAEOPNOTSUPP: return "Operation not supported";
370 case WSAEPFNOSUPPORT: return "Protocol family not supported";
371 case WSAEAFNOSUPPORT:
372 return "Address family not supported by protocol family";
373 case WSAEADDRINUSE: return "Address already in use";
374 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
375 case WSAENETDOWN: return "Network is down";
376 case WSAENETUNREACH: return "Network is unreachable";
377 case WSAENETRESET: return "Network dropped connection on reset";
378 case WSAECONNABORTED: return "Software caused connection abort";
379 case WSAECONNRESET: return "Connection reset by peer";
380 case WSAENOBUFS: return "No buffer space available";
381 case WSAEISCONN: return "Socket is already connected";
382 case WSAENOTCONN: return "Socket is not connected";
383 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
384 case WSAETIMEDOUT: return "Connection timed out";
385 case WSAECONNREFUSED: return "Connection refused";
386 case WSAEHOSTDOWN: return "Host is down";
387 case WSAEHOSTUNREACH: return "No route to host";
388 case WSAEPROCLIM: return "Too many processes";
389 case WSASYSNOTREADY: return "Network subsystem is unavailable";
390 case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range";
391 case WSANOTINITIALISED:
392 return "Successful WSAStartup not yet performed";
393 case WSAEDISCON: return "Graceful shutdown in progress";
394 case WSAHOST_NOT_FOUND: return "Host not found";
395 case WSATRY_AGAIN: return "Nonauthoritative host not found";
396 case WSANO_RECOVERY: return "Nonrecoverable name lookup error";
397 case WSANO_DATA: return "Valid name, no data record of requested type";
398 default: return "Unknown error";
399 }
400}
401
402const char *socket_gaistrerror(int err) {
403 if (err == 0) return NULL;
404 switch (err) {
405 case EAI_AGAIN: return "temporary failure in name resolution";
406 case EAI_BADFLAGS: return "invalid value for ai_flags";
407#ifdef EAI_BADHINTS
408 case EAI_BADHINTS: return "invalid value for hints";
409#endif
410 case EAI_FAIL: return "non-recoverable failure in name resolution";
411 case EAI_FAMILY: return "ai_family not supported";
412 case EAI_MEMORY: return "memory allocation failure";
413 case EAI_NONAME:
414 return "host or service not provided, or not known";
415#ifdef EAI_OVERFLOW
416 case EAI_OVERFLOW: return "argument buffer overflow";
417#endif
418#ifdef EAI_PROTOCOL
419 case EAI_PROTOCOL: return "resolved protocol is unknown";
420#endif
421 case EAI_SERVICE: return "service not supported for socket type";
422 case EAI_SOCKTYPE: return "ai_socktype not supported";
423#ifdef EAI_SYSTEM
424 case EAI_SYSTEM: return strerror(errno);
425#endif
426 default: return gai_strerror(err);
427 }
428}
429
diff --git a/vendor/luasec/src/luasocket/wsocket.h b/vendor/luasec/src/luasocket/wsocket.h
new file mode 100644
index 00000000..c5a4b1ce
--- /dev/null
+++ b/vendor/luasec/src/luasocket/wsocket.h
@@ -0,0 +1,38 @@
1#ifndef WSOCKET_H
2#define WSOCKET_H
3/*=========================================================================*\
4* Socket compatibilization module for Win32
5* LuaSocket toolkit
6\*=========================================================================*/
7
8/*=========================================================================*\
9* WinSock include files
10\*=========================================================================*/
11#include <winsock2.h>
12#include <ws2tcpip.h>
13
14typedef int socklen_t;
15typedef SOCKADDR_STORAGE t_sockaddr_storage;
16typedef SOCKET t_socket;
17typedef t_socket *p_socket;
18
19#define WAITFD_R 1
20#define WAITFD_W 2
21#define WAITFD_E 4
22#define WAITFD_C (WAITFD_E|WAITFD_W)
23
24#ifndef IPV6_V6ONLY
25#define IPV6_V6ONLY 27
26#endif
27
28#define SOCKET_INVALID (INVALID_SOCKET)
29
30#ifndef SO_REUSEPORT
31#define SO_REUSEPORT SO_REUSEADDR
32#endif
33
34#ifndef AI_NUMERICSERV
35#define AI_NUMERICSERV (0)
36#endif
37
38#endif /* WSOCKET_H */
diff --git a/vendor/luasec/src/options.c b/vendor/luasec/src/options.c
new file mode 100644
index 00000000..3d17d6d5
--- /dev/null
+++ b/vendor/luasec/src/options.c
@@ -0,0 +1,185 @@
1/*--------------------------------------------------------------------------
2 * LuaSec 1.3.2
3 *
4 * Copyright (C) 2006-2023 Bruno Silvestre
5 *
6 *--------------------------------------------------------------------------*/
7
8#include <openssl/ssl.h>
9
10#include "options.h"
11
12/* If you need to generate these options again, see options.lua */
13
14
15/*
16 OpenSSL version: OpenSSL 3.0.8
17*/
18
19static lsec_ssl_option_t ssl_options[] = {
20#if defined(SSL_OP_ALL)
21 {"all", SSL_OP_ALL},
22#endif
23#if defined(SSL_OP_ALLOW_CLIENT_RENEGOTIATION)
24 {"allow_client_renegotiation", SSL_OP_ALLOW_CLIENT_RENEGOTIATION},
25#endif
26#if defined(SSL_OP_ALLOW_NO_DHE_KEX)
27 {"allow_no_dhe_kex", SSL_OP_ALLOW_NO_DHE_KEX},
28#endif
29#if defined(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
30 {"allow_unsafe_legacy_renegotiation", SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION},
31#endif
32#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
33 {"cipher_server_preference", SSL_OP_CIPHER_SERVER_PREFERENCE},
34#endif
35#if defined(SSL_OP_CISCO_ANYCONNECT)
36 {"cisco_anyconnect", SSL_OP_CISCO_ANYCONNECT},
37#endif
38#if defined(SSL_OP_CLEANSE_PLAINTEXT)
39 {"cleanse_plaintext", SSL_OP_CLEANSE_PLAINTEXT},
40#endif
41#if defined(SSL_OP_COOKIE_EXCHANGE)
42 {"cookie_exchange", SSL_OP_COOKIE_EXCHANGE},
43#endif
44#if defined(SSL_OP_CRYPTOPRO_TLSEXT_BUG)
45 {"cryptopro_tlsext_bug", SSL_OP_CRYPTOPRO_TLSEXT_BUG},
46#endif
47#if defined(SSL_OP_DISABLE_TLSEXT_CA_NAMES)
48 {"disable_tlsext_ca_names", SSL_OP_DISABLE_TLSEXT_CA_NAMES},
49#endif
50#if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
51 {"dont_insert_empty_fragments", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS},
52#endif
53#if defined(SSL_OP_ENABLE_KTLS)
54 {"enable_ktls", SSL_OP_ENABLE_KTLS},
55#endif
56#if defined(SSL_OP_ENABLE_MIDDLEBOX_COMPAT)
57 {"enable_middlebox_compat", SSL_OP_ENABLE_MIDDLEBOX_COMPAT},
58#endif
59#if defined(SSL_OP_EPHEMERAL_RSA)
60 {"ephemeral_rsa", SSL_OP_EPHEMERAL_RSA},
61#endif
62#if defined(SSL_OP_IGNORE_UNEXPECTED_EOF)
63 {"ignore_unexpected_eof", SSL_OP_IGNORE_UNEXPECTED_EOF},
64#endif
65#if defined(SSL_OP_LEGACY_SERVER_CONNECT)
66 {"legacy_server_connect", SSL_OP_LEGACY_SERVER_CONNECT},
67#endif
68#if defined(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
69 {"microsoft_big_sslv3_buffer", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER},
70#endif
71#if defined(SSL_OP_MICROSOFT_SESS_ID_BUG)
72 {"microsoft_sess_id_bug", SSL_OP_MICROSOFT_SESS_ID_BUG},
73#endif
74#if defined(SSL_OP_MSIE_SSLV2_RSA_PADDING)
75 {"msie_sslv2_rsa_padding", SSL_OP_MSIE_SSLV2_RSA_PADDING},
76#endif
77#if defined(SSL_OP_NETSCAPE_CA_DN_BUG)
78 {"netscape_ca_dn_bug", SSL_OP_NETSCAPE_CA_DN_BUG},
79#endif
80#if defined(SSL_OP_NETSCAPE_CHALLENGE_BUG)
81 {"netscape_challenge_bug", SSL_OP_NETSCAPE_CHALLENGE_BUG},
82#endif
83#if defined(SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
84 {"netscape_demo_cipher_change_bug", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG},
85#endif
86#if defined(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)
87 {"netscape_reuse_cipher_change_bug", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG},
88#endif
89#if defined(SSL_OP_NO_ANTI_REPLAY)
90 {"no_anti_replay", SSL_OP_NO_ANTI_REPLAY},
91#endif
92#if defined(SSL_OP_NO_COMPRESSION)
93 {"no_compression", SSL_OP_NO_COMPRESSION},
94#endif
95#if defined(SSL_OP_NO_DTLS_MASK)
96 {"no_dtls_mask", SSL_OP_NO_DTLS_MASK},
97#endif
98#if defined(SSL_OP_NO_DTLSv1)
99 {"no_dtlsv1", SSL_OP_NO_DTLSv1},
100#endif
101#if defined(SSL_OP_NO_DTLSv1_2)
102 {"no_dtlsv1_2", SSL_OP_NO_DTLSv1_2},
103#endif
104#if defined(SSL_OP_NO_ENCRYPT_THEN_MAC)
105 {"no_encrypt_then_mac", SSL_OP_NO_ENCRYPT_THEN_MAC},
106#endif
107#if defined(SSL_OP_NO_EXTENDED_MASTER_SECRET)
108 {"no_extended_master_secret", SSL_OP_NO_EXTENDED_MASTER_SECRET},
109#endif
110#if defined(SSL_OP_NO_QUERY_MTU)
111 {"no_query_mtu", SSL_OP_NO_QUERY_MTU},
112#endif
113#if defined(SSL_OP_NO_RENEGOTIATION)
114 {"no_renegotiation", SSL_OP_NO_RENEGOTIATION},
115#endif
116#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
117 {"no_session_resumption_on_renegotiation", SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION},
118#endif
119#if defined(SSL_OP_NO_SSL_MASK)
120 {"no_ssl_mask", SSL_OP_NO_SSL_MASK},
121#endif
122#if defined(SSL_OP_NO_SSLv2)
123 {"no_sslv2", SSL_OP_NO_SSLv2},
124#endif
125#if defined(SSL_OP_NO_SSLv3)
126 {"no_sslv3", SSL_OP_NO_SSLv3},
127#endif
128#if defined(SSL_OP_NO_TICKET)
129 {"no_ticket", SSL_OP_NO_TICKET},
130#endif
131#if defined(SSL_OP_NO_TLSv1)
132 {"no_tlsv1", SSL_OP_NO_TLSv1},
133#endif
134#if defined(SSL_OP_NO_TLSv1_1)
135 {"no_tlsv1_1", SSL_OP_NO_TLSv1_1},
136#endif
137#if defined(SSL_OP_NO_TLSv1_2)
138 {"no_tlsv1_2", SSL_OP_NO_TLSv1_2},
139#endif
140#if defined(SSL_OP_NO_TLSv1_3)
141 {"no_tlsv1_3", SSL_OP_NO_TLSv1_3},
142#endif
143#if defined(SSL_OP_PKCS1_CHECK_1)
144 {"pkcs1_check_1", SSL_OP_PKCS1_CHECK_1},
145#endif
146#if defined(SSL_OP_PKCS1_CHECK_2)
147 {"pkcs1_check_2", SSL_OP_PKCS1_CHECK_2},
148#endif
149#if defined(SSL_OP_PRIORITIZE_CHACHA)
150 {"prioritize_chacha", SSL_OP_PRIORITIZE_CHACHA},
151#endif
152#if defined(SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
153 {"safari_ecdhe_ecdsa_bug", SSL_OP_SAFARI_ECDHE_ECDSA_BUG},
154#endif
155#if defined(SSL_OP_SINGLE_DH_USE)
156 {"single_dh_use", SSL_OP_SINGLE_DH_USE},
157#endif
158#if defined(SSL_OP_SINGLE_ECDH_USE)
159 {"single_ecdh_use", SSL_OP_SINGLE_ECDH_USE},
160#endif
161#if defined(SSL_OP_SSLEAY_080_CLIENT_DH_BUG)
162 {"ssleay_080_client_dh_bug", SSL_OP_SSLEAY_080_CLIENT_DH_BUG},
163#endif
164#if defined(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG)
165 {"sslref2_reuse_cert_type_bug", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG},
166#endif
167#if defined(SSL_OP_TLSEXT_PADDING)
168 {"tlsext_padding", SSL_OP_TLSEXT_PADDING},
169#endif
170#if defined(SSL_OP_TLS_BLOCK_PADDING_BUG)
171 {"tls_block_padding_bug", SSL_OP_TLS_BLOCK_PADDING_BUG},
172#endif
173#if defined(SSL_OP_TLS_D5_BUG)
174 {"tls_d5_bug", SSL_OP_TLS_D5_BUG},
175#endif
176#if defined(SSL_OP_TLS_ROLLBACK_BUG)
177 {"tls_rollback_bug", SSL_OP_TLS_ROLLBACK_BUG},
178#endif
179 {NULL, 0L}
180};
181
182LSEC_API lsec_ssl_option_t* lsec_get_ssl_options() {
183 return ssl_options;
184}
185
diff --git a/vendor/luasec/src/options.h b/vendor/luasec/src/options.h
new file mode 100644
index 00000000..c72d52d0
--- /dev/null
+++ b/vendor/luasec/src/options.h
@@ -0,0 +1,22 @@
1#ifndef LSEC_OPTIONS_H
2#define LSEC_OPTIONS_H
3
4/*--------------------------------------------------------------------------
5 * LuaSec 1.3.2
6 *
7 * Copyright (C) 2006-2023 Bruno Silvestre
8 *
9 *--------------------------------------------------------------------------*/
10
11#include "compat.h"
12
13struct lsec_ssl_option_s {
14 const char *name;
15 unsigned long code;
16};
17
18typedef struct lsec_ssl_option_s lsec_ssl_option_t;
19
20LSEC_API lsec_ssl_option_t* lsec_get_ssl_options();
21
22#endif
diff --git a/vendor/luasec/src/options.lua b/vendor/luasec/src/options.lua
new file mode 100644
index 00000000..72428c01
--- /dev/null
+++ b/vendor/luasec/src/options.lua
@@ -0,0 +1,93 @@
1local function usage()
2 print("Usage:")
3 print("* Generate options of your system:")
4 print(" lua options.lua -g /path/to/ssl.h [version] > options.c")
5 print("* Examples:")
6 print(" lua options.lua -g /usr/include/openssl/ssl.h > options.c\n")
7 print(" lua options.lua -g /usr/include/openssl/ssl.h \"OpenSSL 1.1.1f\" > options.c\n")
8
9 print("* List options of your system:")
10 print(" lua options.lua -l /path/to/ssl.h\n")
11end
12
13--
14local function printf(str, ...)
15 print(string.format(str, ...))
16end
17
18local function generate(options, version)
19 print([[
20/*--------------------------------------------------------------------------
21 * LuaSec 1.3.2
22 *
23 * Copyright (C) 2006-2023 Bruno Silvestre
24 *
25 *--------------------------------------------------------------------------*/
26
27#include <openssl/ssl.h>
28
29#include "options.h"
30
31/* If you need to generate these options again, see options.lua */
32
33]])
34
35 printf([[
36/*
37 OpenSSL version: %s
38*/
39]], version)
40
41 print([[static lsec_ssl_option_t ssl_options[] = {]])
42
43 for k, option in ipairs(options) do
44 local name = string.lower(string.sub(option, 8))
45 print(string.format([[#if defined(%s)]], option))
46 print(string.format([[ {"%s", %s},]], name, option))
47 print([[#endif]])
48 end
49 print([[ {NULL, 0L}]])
50 print([[
51};
52
53LSEC_API lsec_ssl_option_t* lsec_get_ssl_options() {
54 return ssl_options;
55}
56]])
57end
58
59local function loadoptions(file)
60 local options = {}
61 local f = assert(io.open(file, "r"))
62 for line in f:lines() do
63 local op = string.match(line, "define%s+(SSL_OP_BIT%()")
64 if not op then
65 op = string.match(line, "define%s+(SSL_OP_%S+)")
66 if op then
67 table.insert(options, op)
68 end
69 end
70 end
71 table.sort(options, function(a,b) return a<b end)
72 return options
73end
74--
75
76local options
77local flag, file, version = ...
78
79version = version or "Unknown"
80
81if not file then
82 usage()
83elseif flag == "-g" then
84 options = loadoptions(file)
85 generate(options, version)
86elseif flag == "-l" then
87 options = loadoptions(file)
88 for k, option in ipairs(options) do
89 print(option)
90 end
91else
92 usage()
93end
diff --git a/vendor/luasec/src/ssl.c b/vendor/luasec/src/ssl.c
new file mode 100644
index 00000000..934bb81b
--- /dev/null
+++ b/vendor/luasec/src/ssl.c
@@ -0,0 +1,1092 @@
1/*--------------------------------------------------------------------------
2 * LuaSec 1.3.2
3 *
4 * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild
5 * Copyright (C) 2006-2023 Bruno Silvestre
6 *
7 *--------------------------------------------------------------------------*/
8
9#include <errno.h>
10#include <string.h>
11
12#if defined(WIN32)
13#include <winsock2.h>
14#endif
15
16#include <openssl/ssl.h>
17#include <openssl/x509v3.h>
18#include <openssl/x509_vfy.h>
19#include <openssl/err.h>
20#include <openssl/dh.h>
21
22#include <lua.h>
23#include <lauxlib.h>
24
25#include <luasocket/io.h>
26#include <luasocket/buffer.h>
27#include <luasocket/timeout.h>
28#include <luasocket/socket.h>
29
30#include "x509.h"
31#include "context.h"
32#include "ssl.h"
33
34
35#ifndef LSEC_API_OPENSSL_1_1_0
36#define SSL_is_server(s) (s->server)
37#define SSL_up_ref(ssl) CRYPTO_add(&(ssl)->references, 1, CRYPTO_LOCK_SSL)
38#define X509_up_ref(c) CRYPTO_add(&c->references, 1, CRYPTO_LOCK_X509)
39#endif
40
41
42/**
43 * Underline socket error.
44 */
45static int lsec_socket_error()
46{
47#if defined(WIN32)
48 return WSAGetLastError();
49#else
50#if defined(LSEC_OPENSSL_ERRNO_BUG)
51 // Bug in OpenSSL
52 if (errno == 0)
53 return LSEC_IO_SSL;
54#endif
55 return errno;
56#endif
57}
58
59/**
60 * Map error code into string.
61 */
62static const char *ssl_ioerror(void *ctx, int err)
63{
64 if (err == LSEC_IO_SSL) {
65 p_ssl ssl = (p_ssl) ctx;
66 switch(ssl->error) {
67 case SSL_ERROR_NONE: return "No error";
68 case SSL_ERROR_ZERO_RETURN: return "closed";
69 case SSL_ERROR_WANT_READ: return "wantread";
70 case SSL_ERROR_WANT_WRITE: return "wantwrite";
71 case SSL_ERROR_WANT_CONNECT: return "'connect' not completed";
72 case SSL_ERROR_WANT_ACCEPT: return "'accept' not completed";
73 case SSL_ERROR_WANT_X509_LOOKUP: return "Waiting for callback";
74 case SSL_ERROR_SYSCALL: return "System error";
75 case SSL_ERROR_SSL: return ERR_reason_error_string(ERR_get_error());
76 default: return "Unknown SSL error";
77 }
78 }
79 return socket_strerror(err);
80}
81
82/**
83 * Close the connection before the GC collect the object.
84 */
85static int meth_destroy(lua_State *L)
86{
87 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
88 if (ssl->state == LSEC_STATE_CONNECTED) {
89 socket_setblocking(&ssl->sock);
90 SSL_shutdown(ssl->ssl);
91 }
92 if (ssl->sock != SOCKET_INVALID) {
93 socket_destroy(&ssl->sock);
94 }
95 ssl->state = LSEC_STATE_CLOSED;
96 if (ssl->ssl) {
97 /* Clear the registries */
98 luaL_getmetatable(L, "SSL:Verify:Registry");
99 lua_pushlightuserdata(L, (void*)ssl->ssl);
100 lua_pushnil(L);
101 lua_settable(L, -3);
102 luaL_getmetatable(L, "SSL:SNI:Registry");
103 lua_pushlightuserdata(L, (void*)ssl->ssl);
104 lua_pushnil(L);
105 lua_settable(L, -3);
106 /* Destroy the object */
107 SSL_free(ssl->ssl);
108 ssl->ssl = NULL;
109 }
110 return 0;
111}
112
113/**
114 * Perform the TLS/SSL handshake
115 */
116static int handshake(p_ssl ssl)
117{
118 int err;
119 p_timeout tm = timeout_markstart(&ssl->tm);
120 if (ssl->state == LSEC_STATE_CLOSED)
121 return IO_CLOSED;
122 for ( ; ; ) {
123 ERR_clear_error();
124 err = SSL_do_handshake(ssl->ssl);
125 ssl->error = SSL_get_error(ssl->ssl, err);
126 switch (ssl->error) {
127 case SSL_ERROR_NONE:
128 ssl->state = LSEC_STATE_CONNECTED;
129 return IO_DONE;
130 case SSL_ERROR_WANT_READ:
131 err = socket_waitfd(&ssl->sock, WAITFD_R, tm);
132 if (err == IO_TIMEOUT) return LSEC_IO_SSL;
133 if (err != IO_DONE) return err;
134 break;
135 case SSL_ERROR_WANT_WRITE:
136 err = socket_waitfd(&ssl->sock, WAITFD_W, tm);
137 if (err == IO_TIMEOUT) return LSEC_IO_SSL;
138 if (err != IO_DONE) return err;
139 break;
140 case SSL_ERROR_SYSCALL:
141 if (ERR_peek_error()) {
142 ssl->error = SSL_ERROR_SSL;
143 return LSEC_IO_SSL;
144 }
145 if (err == 0)
146 return IO_CLOSED;
147 return lsec_socket_error();
148 default:
149 return LSEC_IO_SSL;
150 }
151 }
152 return IO_UNKNOWN;
153}
154
155/**
156 * Send data
157 */
158static int ssl_send(void *ctx, const char *data, size_t count, size_t *sent,
159 p_timeout tm)
160{
161 int err;
162 p_ssl ssl = (p_ssl)ctx;
163 if (ssl->state != LSEC_STATE_CONNECTED)
164 return IO_CLOSED;
165 *sent = 0;
166 for ( ; ; ) {
167 ERR_clear_error();
168 err = SSL_write(ssl->ssl, data, (int)count);
169 ssl->error = SSL_get_error(ssl->ssl, err);
170 switch (ssl->error) {
171 case SSL_ERROR_NONE:
172 *sent = err;
173 return IO_DONE;
174 case SSL_ERROR_WANT_READ:
175 err = socket_waitfd(&ssl->sock, WAITFD_R, tm);
176 if (err == IO_TIMEOUT) return LSEC_IO_SSL;
177 if (err != IO_DONE) return err;
178 break;
179 case SSL_ERROR_WANT_WRITE:
180 err = socket_waitfd(&ssl->sock, WAITFD_W, tm);
181 if (err == IO_TIMEOUT) return LSEC_IO_SSL;
182 if (err != IO_DONE) return err;
183 break;
184 case SSL_ERROR_SYSCALL:
185 if (ERR_peek_error()) {
186 ssl->error = SSL_ERROR_SSL;
187 return LSEC_IO_SSL;
188 }
189 if (err == 0)
190 return IO_CLOSED;
191 return lsec_socket_error();
192 default:
193 return LSEC_IO_SSL;
194 }
195 }
196 return IO_UNKNOWN;
197}
198
199/**
200 * Receive data
201 */
202static int ssl_recv(void *ctx, char *data, size_t count, size_t *got,
203 p_timeout tm)
204{
205 int err;
206 p_ssl ssl = (p_ssl)ctx;
207 *got = 0;
208 if (ssl->state != LSEC_STATE_CONNECTED)
209 return IO_CLOSED;
210 for ( ; ; ) {
211 ERR_clear_error();
212 err = SSL_read(ssl->ssl, data, (int)count);
213 ssl->error = SSL_get_error(ssl->ssl, err);
214 switch (ssl->error) {
215 case SSL_ERROR_NONE:
216 *got = err;
217 return IO_DONE;
218 case SSL_ERROR_ZERO_RETURN:
219 return IO_CLOSED;
220 case SSL_ERROR_WANT_READ:
221 err = socket_waitfd(&ssl->sock, WAITFD_R, tm);
222 if (err == IO_TIMEOUT) return LSEC_IO_SSL;
223 if (err != IO_DONE) return err;
224 break;
225 case SSL_ERROR_WANT_WRITE:
226 err = socket_waitfd(&ssl->sock, WAITFD_W, tm);
227 if (err == IO_TIMEOUT) return LSEC_IO_SSL;
228 if (err != IO_DONE) return err;
229 break;
230 case SSL_ERROR_SYSCALL:
231 if (ERR_peek_error()) {
232 ssl->error = SSL_ERROR_SSL;
233 return LSEC_IO_SSL;
234 }
235 if (err == 0)
236 return IO_CLOSED;
237 return lsec_socket_error();
238 default:
239 return LSEC_IO_SSL;
240 }
241 }
242 return IO_UNKNOWN;
243}
244
245static SSL_CTX* luaossl_testcontext(lua_State *L, int arg) {
246 SSL_CTX **ctx = luaL_testudata(L, arg, "SSL_CTX*");
247 if (ctx)
248 return *ctx;
249 return NULL;
250}
251
252static SSL* luaossl_testssl(lua_State *L, int arg) {
253 SSL **ssl = luaL_testudata(L, arg, "SSL*");
254 if (ssl)
255 return *ssl;
256 return NULL;
257}
258
259/**
260 * Create a new TLS/SSL object and mark it as new.
261 */
262static int meth_create(lua_State *L)
263{
264 p_ssl ssl;
265 int mode;
266 SSL_CTX *ctx;
267
268 lua_settop(L, 1);
269
270 ssl = (p_ssl)lua_newuserdata(L, sizeof(t_ssl));
271 if (!ssl) {
272 lua_pushnil(L);
273 lua_pushstring(L, "error creating SSL object");
274 return 2;
275 }
276
277 if ((ctx = lsec_testcontext(L, 1))) {
278 mode = lsec_getmode(L, 1);
279 if (mode == LSEC_MODE_INVALID) {
280 lua_pushnil(L);
281 lua_pushstring(L, "invalid mode");
282 return 2;
283 }
284 ssl->ssl = SSL_new(ctx);
285 if (!ssl->ssl) {
286 lua_pushnil(L);
287 lua_pushfstring(L, "error creating SSL object (%s)",
288 ERR_reason_error_string(ERR_get_error()));
289 return 2;
290 }
291 } else if ((ctx = luaossl_testcontext(L, 1))) {
292 ssl->ssl = SSL_new(ctx);
293 if (!ssl->ssl) {
294 lua_pushnil(L);
295 lua_pushfstring(L, "error creating SSL object (%s)",
296 ERR_reason_error_string(ERR_get_error()));
297 return 2;
298 }
299 mode = SSL_is_server(ssl->ssl) ? LSEC_MODE_SERVER : LSEC_MODE_CLIENT;
300 } else if ((ssl->ssl = luaossl_testssl(L, 1))) {
301 SSL_up_ref(ssl->ssl);
302 mode = SSL_is_server(ssl->ssl) ? LSEC_MODE_SERVER : LSEC_MODE_CLIENT;
303 } else {
304 return luaL_argerror(L, 1, "invalid context");
305 }
306 ssl->state = LSEC_STATE_NEW;
307 SSL_set_fd(ssl->ssl, (int)SOCKET_INVALID);
308 SSL_set_mode(ssl->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE |
309 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
310 SSL_set_mode(ssl->ssl, SSL_MODE_RELEASE_BUFFERS);
311 if (mode == LSEC_MODE_SERVER)
312 SSL_set_accept_state(ssl->ssl);
313 else
314 SSL_set_connect_state(ssl->ssl);
315
316 io_init(&ssl->io, (p_send)ssl_send, (p_recv)ssl_recv,
317 (p_error) ssl_ioerror, ssl);
318 timeout_init(&ssl->tm, -1, -1);
319 buffer_init(&ssl->buf, &ssl->io, &ssl->tm);
320
321 luaL_getmetatable(L, "SSL:Connection");
322 lua_setmetatable(L, -2);
323 return 1;
324}
325
326/**
327 * Buffer send function
328 */
329static int meth_send(lua_State *L) {
330 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
331 return buffer_meth_send(L, &ssl->buf);
332}
333
334/**
335 * Buffer receive function
336 */
337static int meth_receive(lua_State *L) {
338 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
339 return buffer_meth_receive(L, &ssl->buf);
340}
341
342/**
343 * Get the buffer's statistics.
344 */
345static int meth_getstats(lua_State *L) {
346 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
347 return buffer_meth_getstats(L, &ssl->buf);
348}
349
350/**
351 * Set the buffer's statistics.
352 */
353static int meth_setstats(lua_State *L) {
354 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
355 return buffer_meth_setstats(L, &ssl->buf);
356}
357
358/**
359 * Select support methods
360 */
361static int meth_getfd(lua_State *L)
362{
363 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
364 lua_pushnumber(L, ssl->sock);
365 return 1;
366}
367
368/**
369 * Set the TLS/SSL file descriptor.
370 * Call it *before* the handshake.
371 */
372static int meth_setfd(lua_State *L)
373{
374 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
375 if (ssl->state != LSEC_STATE_NEW)
376 luaL_argerror(L, 1, "invalid SSL object state");
377 ssl->sock = (t_socket)luaL_checkinteger(L, 2);
378 socket_setnonblocking(&ssl->sock);
379 SSL_set_fd(ssl->ssl, (int)ssl->sock);
380 return 0;
381}
382
383/**
384 * Lua handshake function.
385 */
386static int meth_handshake(lua_State *L)
387{
388 int err;
389 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
390 p_context ctx = (p_context)SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl->ssl));
391 ctx->L = L;
392 err = handshake(ssl);
393 if (ctx->dh_param) {
394 DH_free(ctx->dh_param);
395 ctx->dh_param = NULL;
396 }
397 if (ctx->alpn) {
398 free(ctx->alpn);
399 ctx->alpn = NULL;
400 }
401 if (err == IO_DONE) {
402 lua_pushboolean(L, 1);
403 return 1;
404 }
405 lua_pushboolean(L, 0);
406 lua_pushstring(L, ssl_ioerror((void*)ssl, err));
407 return 2;
408}
409
410/**
411 * Close the connection.
412 */
413static int meth_close(lua_State *L)
414{
415 meth_destroy(L);
416 return 0;
417}
418
419/**
420 * Set timeout.
421 */
422static int meth_settimeout(lua_State *L)
423{
424 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
425 return timeout_meth_settimeout(L, &ssl->tm);
426}
427
428/**
429 * Check if there is data in the buffer.
430 */
431static int meth_dirty(lua_State *L)
432{
433 int res = 0;
434 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
435 if (ssl->state != LSEC_STATE_CLOSED)
436 res = !buffer_isempty(&ssl->buf) || SSL_pending(ssl->ssl);
437 lua_pushboolean(L, res);
438 return 1;
439}
440
441/**
442 * Return the state information about the SSL object.
443 */
444static int meth_want(lua_State *L)
445{
446 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
447 int code = (ssl->state == LSEC_STATE_CLOSED)
448 ? SSL_NOTHING
449 : SSL_want(ssl->ssl);
450 switch(code) {
451 case SSL_NOTHING: lua_pushstring(L, "nothing"); break;
452 case SSL_READING: lua_pushstring(L, "read"); break;
453 case SSL_WRITING: lua_pushstring(L, "write"); break;
454 case SSL_X509_LOOKUP: lua_pushstring(L, "x509lookup"); break;
455 }
456 return 1;
457}
458
459/**
460 * Return the compression method used.
461 */
462static int meth_compression(lua_State *L)
463{
464#ifdef OPENSSL_NO_COMP
465 const void *comp;
466#else
467 const COMP_METHOD *comp;
468#endif
469 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
470 if (ssl->state != LSEC_STATE_CONNECTED) {
471 lua_pushnil(L);
472 lua_pushstring(L, "closed");
473 return 2;
474 }
475 comp = SSL_get_current_compression(ssl->ssl);
476 if (comp)
477 lua_pushstring(L, SSL_COMP_get_name(comp));
478 else
479 lua_pushnil(L);
480 return 1;
481}
482
483/**
484 * Return the nth certificate of the peer's chain.
485 */
486static int meth_getpeercertificate(lua_State *L)
487{
488 int n;
489 X509 *cert;
490 STACK_OF(X509) *certs;
491 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
492 if (ssl->state != LSEC_STATE_CONNECTED) {
493 lua_pushnil(L);
494 lua_pushstring(L, "closed");
495 return 2;
496 }
497 /* Default to the first cert */
498 n = (int)luaL_optinteger(L, 2, 1);
499 /* This function is 1-based, but OpenSSL is 0-based */
500 --n;
501 if (n < 0) {
502 lua_pushnil(L);
503 lua_pushliteral(L, "invalid certificate index");
504 return 2;
505 }
506 if (n == 0) {
507 cert = SSL_get_peer_certificate(ssl->ssl);
508 if (cert)
509 lsec_pushx509(L, cert);
510 else
511 lua_pushnil(L);
512 return 1;
513 }
514 /* In a server-context, the stack doesn't contain the peer cert,
515 * so adjust accordingly.
516 */
517 if (SSL_is_server(ssl->ssl))
518 --n;
519 certs = SSL_get_peer_cert_chain(ssl->ssl);
520 if (n >= sk_X509_num(certs)) {
521 lua_pushnil(L);
522 return 1;
523 }
524 cert = sk_X509_value(certs, n);
525 /* Increment the reference counting of the object. */
526 /* See SSL_get_peer_certificate() source code. */
527 X509_up_ref(cert);
528 lsec_pushx509(L, cert);
529 return 1;
530}
531
532/**
533 * Return the nth certificate of the chain sent to our peer.
534 */
535static int meth_getlocalcertificate(lua_State *L)
536{
537 int n;
538 X509 *cert;
539 STACK_OF(X509) *certs;
540 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
541 if (ssl->state != LSEC_STATE_CONNECTED) {
542 lua_pushnil(L);
543 lua_pushstring(L, "closed");
544 return 2;
545 }
546 /* Default to the first cert */
547 n = (int)luaL_optinteger(L, 2, 1);
548 /* This function is 1-based, but OpenSSL is 0-based */
549 --n;
550 if (n < 0) {
551 lua_pushnil(L);
552 lua_pushliteral(L, "invalid certificate index");
553 return 2;
554 }
555 if (n == 0) {
556 cert = SSL_get_certificate(ssl->ssl);
557 if (cert)
558 lsec_pushx509(L, cert);
559 else
560 lua_pushnil(L);
561 return 1;
562 }
563 /* In a server-context, the stack doesn't contain the peer cert,
564 * so adjust accordingly.
565 */
566 if (SSL_is_server(ssl->ssl))
567 --n;
568 if(SSL_get0_chain_certs(ssl->ssl, &certs) != 1) {
569 lua_pushnil(L);
570 } else {
571 if (n >= sk_X509_num(certs)) {
572 lua_pushnil(L);
573 return 1;
574 }
575 cert = sk_X509_value(certs, n);
576 /* Increment the reference counting of the object. */
577 /* See SSL_get_peer_certificate() source code. */
578 X509_up_ref(cert);
579 lsec_pushx509(L, cert);
580 }
581 return 1;
582}
583
584/**
585 * Return the chain of certificate of the peer.
586 */
587static int meth_getpeerchain(lua_State *L)
588{
589 int i;
590 int idx = 1;
591 int n_certs;
592 X509 *cert;
593 STACK_OF(X509) *certs;
594 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
595 if (ssl->state != LSEC_STATE_CONNECTED) {
596 lua_pushnil(L);
597 lua_pushstring(L, "closed");
598 return 2;
599 }
600 lua_newtable(L);
601 if (SSL_is_server(ssl->ssl)) {
602 lsec_pushx509(L, SSL_get_peer_certificate(ssl->ssl));
603 lua_rawseti(L, -2, idx++);
604 }
605 certs = SSL_get_peer_cert_chain(ssl->ssl);
606 n_certs = sk_X509_num(certs);
607 for (i = 0; i < n_certs; i++) {
608 cert = sk_X509_value(certs, i);
609 /* Increment the reference counting of the object. */
610 /* See SSL_get_peer_certificate() source code. */
611 X509_up_ref(cert);
612 lsec_pushx509(L, cert);
613 lua_rawseti(L, -2, idx++);
614 }
615 return 1;
616}
617
618/**
619 * Return the chain of certificates sent to the peer.
620 */
621static int meth_getlocalchain(lua_State *L)
622{
623 int i;
624 int idx = 1;
625 int n_certs;
626 X509 *cert;
627 STACK_OF(X509) *certs;
628 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
629 if (ssl->state != LSEC_STATE_CONNECTED) {
630 lua_pushnil(L);
631 lua_pushstring(L, "closed");
632 return 2;
633 }
634 lua_newtable(L);
635 if (SSL_is_server(ssl->ssl)) {
636 lsec_pushx509(L, SSL_get_certificate(ssl->ssl));
637 lua_rawseti(L, -2, idx++);
638 }
639 if(SSL_get0_chain_certs(ssl->ssl, &certs)) {
640 n_certs = sk_X509_num(certs);
641 for (i = 0; i < n_certs; i++) {
642 cert = sk_X509_value(certs, i);
643 /* Increment the reference counting of the object. */
644 /* See SSL_get_peer_certificate() source code. */
645 X509_up_ref(cert);
646 lsec_pushx509(L, cert);
647 lua_rawseti(L, -2, idx++);
648 }
649 }
650 return 1;
651}
652
653/**
654 * Copy the table src to the table dst.
655 */
656static void copy_error_table(lua_State *L, int src, int dst)
657{
658 lua_pushnil(L);
659 while (lua_next(L, src) != 0) {
660 if (lua_istable(L, -1)) {
661 /* Replace the table with its copy */
662 lua_newtable(L);
663 copy_error_table(L, dst+2, dst+3);
664 lua_remove(L, dst+2);
665 }
666 lua_pushvalue(L, -2);
667 lua_pushvalue(L, -2);
668 lua_rawset(L, dst);
669 /* Remove the value and leave the key */
670 lua_pop(L, 1);
671 }
672}
673
674/**
675 * Return the verification state of the peer chain.
676 */
677static int meth_getpeerverification(lua_State *L)
678{
679 long err;
680 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
681 if (ssl->state != LSEC_STATE_CONNECTED) {
682 lua_pushboolean(L, 0);
683 lua_pushstring(L, "closed");
684 return 2;
685 }
686 err = SSL_get_verify_result(ssl->ssl);
687 if (err == X509_V_OK) {
688 lua_pushboolean(L, 1);
689 return 1;
690 }
691 luaL_getmetatable(L, "SSL:Verify:Registry");
692 lua_pushlightuserdata(L, (void*)ssl->ssl);
693 lua_gettable(L, -2);
694 if (lua_isnil(L, -1))
695 lua_pushstring(L, X509_verify_cert_error_string(err));
696 else {
697 /* Copy the table of errors to avoid modifications */
698 lua_newtable(L);
699 copy_error_table(L, lua_gettop(L)-1, lua_gettop(L));
700 }
701 lua_pushboolean(L, 0);
702 lua_pushvalue(L, -2);
703 return 2;
704}
705
706/**
707 * Get the latest "Finished" message sent out.
708 */
709static int meth_getfinished(lua_State *L)
710{
711 size_t len = 0;
712 char *buffer = NULL;
713 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
714 if (ssl->state != LSEC_STATE_CONNECTED) {
715 lua_pushnil(L);
716 lua_pushstring(L, "closed");
717 return 2;
718 }
719 if ((len = SSL_get_finished(ssl->ssl, NULL, 0)) == 0)
720 return 0;
721 buffer = (char*)malloc(len);
722 if (!buffer) {
723 lua_pushnil(L);
724 lua_pushstring(L, "out of memory");
725 return 2;
726 }
727 SSL_get_finished(ssl->ssl, buffer, len);
728 lua_pushlstring(L, buffer, len);
729 free(buffer);
730 return 1;
731}
732
733/**
734 * Gets the latest "Finished" message received.
735 */
736static int meth_getpeerfinished(lua_State *L)
737{
738 size_t len = 0;
739 char *buffer = NULL;
740 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
741 if (ssl->state != LSEC_STATE_CONNECTED) {
742 lua_pushnil(L);
743 lua_pushstring(L, "closed");
744 return 0;
745 }
746 if ((len = SSL_get_peer_finished(ssl->ssl, NULL, 0)) == 0)
747 return 0;
748 buffer = (char*)malloc(len);
749 if (!buffer) {
750 lua_pushnil(L);
751 lua_pushstring(L, "out of memory");
752 return 2;
753 }
754 SSL_get_peer_finished(ssl->ssl, buffer, len);
755 lua_pushlstring(L, buffer, len);
756 free(buffer);
757 return 1;
758}
759
760/**
761 * Get some shared keying material
762 */
763static int meth_exportkeyingmaterial(lua_State *L)
764{
765 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
766
767 if(ssl->state != LSEC_STATE_CONNECTED) {
768 lua_pushnil(L);
769 lua_pushstring(L, "closed");
770 return 0;
771 }
772
773 size_t llen = 0;
774 size_t contextlen = 0;
775 const unsigned char *context = NULL;
776 const char *label = (const char*)luaL_checklstring(L, 2, &llen);
777 size_t olen = (size_t)luaL_checkinteger(L, 3);
778
779 if (!lua_isnoneornil(L, 4))
780 context = (const unsigned char*)luaL_checklstring(L, 4, &contextlen);
781
782 /* Temporary buffer memory-managed by Lua itself */
783 unsigned char *out = (unsigned char*)lua_newuserdata(L, olen);
784
785 if(SSL_export_keying_material(ssl->ssl, out, olen, label, llen, context, contextlen, context != NULL) != 1) {
786 lua_pushnil(L);
787 lua_pushstring(L, "error exporting keying material");
788 return 2;
789 }
790
791 lua_pushlstring(L, (char*)out, olen);
792 return 1;
793}
794
795/**
796 * Object information -- tostring metamethod
797 */
798static int meth_tostring(lua_State *L)
799{
800 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
801 lua_pushfstring(L, "SSL connection: %p%s", ssl,
802 ssl->state == LSEC_STATE_CLOSED ? " (closed)" : "");
803 return 1;
804}
805
806/**
807 * Add a method in the SSL metatable.
808 */
809static int meth_setmethod(lua_State *L)
810{
811 luaL_getmetatable(L, "SSL:Connection");
812 lua_pushstring(L, "__index");
813 lua_gettable(L, -2);
814 lua_pushvalue(L, 1);
815 lua_pushvalue(L, 2);
816 lua_settable(L, -3);
817 return 0;
818}
819
820/**
821 * Return information about the connection.
822 */
823static int meth_info(lua_State *L)
824{
825 int bits = 0;
826 int algbits = 0;
827 char buf[256] = {0};
828 const SSL_CIPHER *cipher;
829 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
830 cipher = SSL_get_current_cipher(ssl->ssl);
831 if (!cipher)
832 return 0;
833 SSL_CIPHER_description(cipher, buf, sizeof(buf));
834 bits = SSL_CIPHER_get_bits(cipher, &algbits);
835 lua_pushstring(L, buf);
836 lua_pushnumber(L, bits);
837 lua_pushnumber(L, algbits);
838 lua_pushstring(L, SSL_get_version(ssl->ssl));
839 return 4;
840}
841
842static int sni_cb(SSL *ssl, int *ad, void *arg)
843{
844 int strict;
845 SSL_CTX *newctx = NULL;
846 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
847 lua_State *L = ((p_context)SSL_CTX_get_app_data(ctx))->L;
848 const char *name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
849 /* No name, use default context */
850 if (!name)
851 return SSL_TLSEXT_ERR_NOACK;
852 /* Retrieve struct from registry */
853 luaL_getmetatable(L, "SSL:SNI:Registry");
854 lua_pushlightuserdata(L, (void*)ssl);
855 lua_gettable(L, -2);
856 /* Strict search? */
857 lua_pushstring(L, "strict");
858 lua_gettable(L, -2);
859 strict = lua_toboolean(L, -1);
860 lua_pop(L, 1);
861 /* Search for the name in the map */
862 lua_pushstring(L, "map");
863 lua_gettable(L, -2);
864 lua_pushstring(L, name);
865 lua_gettable(L, -2);
866 if (lua_isuserdata(L, -1))
867 newctx = lsec_checkcontext(L, -1);
868 lua_pop(L, 4);
869 /* Found, use this context */
870 if (newctx) {
871 p_context pctx = (p_context)SSL_CTX_get_app_data(newctx);
872 pctx->L = L;
873 SSL_set_SSL_CTX(ssl, newctx);
874 return SSL_TLSEXT_ERR_OK;
875 }
876 /* Not found, but use initial context */
877 if (!strict)
878 return SSL_TLSEXT_ERR_OK;
879 return SSL_TLSEXT_ERR_ALERT_FATAL;
880}
881
882static int meth_sni(lua_State *L)
883{
884 int strict;
885 SSL_CTX *aux;
886 const char *name;
887 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
888 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl->ssl);
889 p_context pctx = (p_context)SSL_CTX_get_app_data(ctx);
890 if (pctx->mode == LSEC_MODE_CLIENT) {
891 name = luaL_checkstring(L, 2);
892 SSL_set_tlsext_host_name(ssl->ssl, name);
893 return 0;
894 } else if (pctx->mode == LSEC_MODE_SERVER) {
895 luaL_checktype(L, 2, LUA_TTABLE);
896 strict = lua_toboolean(L, 3);
897 /* Check if the table contains only (string -> context) */
898 lua_pushnil(L);
899 while (lua_next(L, 2)) {
900 luaL_checkstring(L, -2);
901 aux = lsec_checkcontext(L, -1);
902 /* Set callback in every context */
903 SSL_CTX_set_tlsext_servername_callback(aux, sni_cb);
904 /* leave the next key on the stack */
905 lua_pop(L, 1);
906 }
907 /* Save table in the register */
908 luaL_getmetatable(L, "SSL:SNI:Registry");
909 lua_pushlightuserdata(L, (void*)ssl->ssl);
910 lua_newtable(L);
911 lua_pushstring(L, "map");
912 lua_pushvalue(L, 2);
913 lua_settable(L, -3);
914 lua_pushstring(L, "strict");
915 lua_pushboolean(L, strict);
916 lua_settable(L, -3);
917 lua_settable(L, -3);
918 /* Set callback in the default context */
919 SSL_CTX_set_tlsext_servername_callback(ctx, sni_cb);
920 }
921 return 0;
922}
923
924static int meth_getsniname(lua_State *L)
925{
926 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
927 const char *name = SSL_get_servername(ssl->ssl, TLSEXT_NAMETYPE_host_name);
928 if (name)
929 lua_pushstring(L, name);
930 else
931 lua_pushnil(L);
932 return 1;
933}
934
935static int meth_getalpn(lua_State *L)
936{
937 unsigned len;
938 const unsigned char *data;
939 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
940 SSL_get0_alpn_selected(ssl->ssl, &data, &len);
941 if (data == NULL && len == 0)
942 lua_pushnil(L);
943 else
944 lua_pushlstring(L, (const char*)data, len);
945 return 1;
946}
947
948static int meth_copyright(lua_State *L)
949{
950 lua_pushstring(L, "LuaSec 1.3.2 - Copyright (C) 2006-2023 Bruno Silvestre, UFG"
951#if defined(WITH_LUASOCKET)
952 "\nLuaSocket 3.0-RC1 - Copyright (C) 2004-2013 Diego Nehab"
953#endif
954 );
955 return 1;
956}
957
958#if defined(LSEC_ENABLE_DANE)
959static int meth_dane(lua_State *L)
960{
961 int ret;
962 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
963 ret = SSL_dane_enable(ssl->ssl, luaL_checkstring(L, 2));
964 lua_pushboolean(L, (ret > 0));
965 return 1;
966}
967
968static int meth_tlsa(lua_State *L)
969{
970 int ret;
971 size_t len;
972 p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
973 uint8_t usage = (uint8_t)luaL_checkinteger(L, 2);
974 uint8_t selector = (uint8_t)luaL_checkinteger(L, 3);
975 uint8_t mtype = (uint8_t)luaL_checkinteger(L, 4);
976 unsigned char *data = (unsigned char*)luaL_checklstring(L, 5, &len);
977
978 ERR_clear_error();
979 ret = SSL_dane_tlsa_add(ssl->ssl, usage, selector, mtype, data, len);
980 lua_pushboolean(L, (ret > 0));
981
982 return 1;
983}
984#endif
985
986/*---------------------------------------------------------------------------*/
987
988/**
989 * SSL methods
990 */
991static luaL_Reg methods[] = {
992 {"close", meth_close},
993 {"getalpn", meth_getalpn},
994 {"getfd", meth_getfd},
995 {"getfinished", meth_getfinished},
996 {"getpeercertificate", meth_getpeercertificate},
997 {"getlocalcertificate", meth_getlocalcertificate},
998 {"getpeerchain", meth_getpeerchain},
999 {"getlocalchain", meth_getlocalchain},
1000 {"getpeerverification", meth_getpeerverification},
1001 {"getpeerfinished", meth_getpeerfinished},
1002 {"exportkeyingmaterial",meth_exportkeyingmaterial},
1003 {"getsniname", meth_getsniname},
1004 {"getstats", meth_getstats},
1005 {"setstats", meth_setstats},
1006 {"dirty", meth_dirty},
1007 {"dohandshake", meth_handshake},
1008 {"receive", meth_receive},
1009 {"send", meth_send},
1010 {"settimeout", meth_settimeout},
1011 {"sni", meth_sni},
1012 {"want", meth_want},
1013#if defined(LSEC_ENABLE_DANE)
1014 {"setdane", meth_dane},
1015 {"settlsa", meth_tlsa},
1016#endif
1017 {NULL, NULL}
1018};
1019
1020/**
1021 * SSL metamethods.
1022 */
1023static luaL_Reg meta[] = {
1024 {"__close", meth_destroy},
1025 {"__gc", meth_destroy},
1026 {"__tostring", meth_tostring},
1027 {NULL, NULL}
1028};
1029
1030/**
1031 * SSL functions.
1032 */
1033static luaL_Reg funcs[] = {
1034 {"compression", meth_compression},
1035 {"create", meth_create},
1036 {"info", meth_info},
1037 {"setfd", meth_setfd},
1038 {"setmethod", meth_setmethod},
1039 {"copyright", meth_copyright},
1040 {NULL, NULL}
1041};
1042
1043/**
1044 * Initialize modules.
1045 */
1046LSEC_API int luaopen_ssl_core(lua_State *L)
1047{
1048#ifndef LSEC_API_OPENSSL_1_1_0
1049 /* Initialize SSL */
1050 if (!SSL_library_init()) {
1051 lua_pushstring(L, "unable to initialize SSL library");
1052 lua_error(L);
1053 }
1054 OpenSSL_add_all_algorithms();
1055 SSL_load_error_strings();
1056#endif
1057
1058#if defined(WITH_LUASOCKET)
1059 /* Initialize internal library */
1060 socket_open();
1061#endif
1062
1063 luaL_newmetatable(L, "SSL:SNI:Registry");
1064
1065 /* Register the functions and tables */
1066 luaL_newmetatable(L, "SSL:Connection");
1067 setfuncs(L, meta);
1068
1069 luaL_newlib(L, methods);
1070 lua_setfield(L, -2, "__index");
1071
1072 luaL_newlib(L, funcs);
1073
1074 lua_pushstring(L, "SOCKET_INVALID");
1075 lua_pushinteger(L, SOCKET_INVALID);
1076 lua_rawset(L, -3);
1077
1078 return 1;
1079}
1080
1081//------------------------------------------------------------------------------
1082
1083#if defined(_MSC_VER)
1084
1085/* Empty implementation to allow building with LuaRocks and MS compilers */
1086LSEC_API int luaopen_ssl(lua_State *L) {
1087 lua_pushstring(L, "you should not call this function");
1088 lua_error(L);
1089 return 0;
1090}
1091
1092#endif
diff --git a/vendor/luasec/src/ssl.h b/vendor/luasec/src/ssl.h
new file mode 100644
index 00000000..2362ffe5
--- /dev/null
+++ b/vendor/luasec/src/ssl.h
@@ -0,0 +1,41 @@
1#ifndef LSEC_SSL_H
2#define LSEC_SSL_H
3
4/*--------------------------------------------------------------------------
5 * LuaSec 1.3.2
6 *
7 * Copyright (C) 2006-2023 Bruno Silvestre
8 *
9 *--------------------------------------------------------------------------*/
10
11#include <openssl/ssl.h>
12#include <lua.h>
13
14#include <luasocket/io.h>
15#include <luasocket/buffer.h>
16#include <luasocket/timeout.h>
17#include <luasocket/socket.h>
18
19#include "compat.h"
20#include "context.h"
21
22#define LSEC_STATE_NEW 1
23#define LSEC_STATE_CONNECTED 2
24#define LSEC_STATE_CLOSED 3
25
26#define LSEC_IO_SSL -100
27
28typedef struct t_ssl_ {
29 t_socket sock;
30 t_io io;
31 t_buffer buf;
32 t_timeout tm;
33 SSL *ssl;
34 int state;
35 int error;
36} t_ssl;
37typedef t_ssl* p_ssl;
38
39LSEC_API int luaopen_ssl_core(lua_State *L);
40
41#endif
diff --git a/vendor/luasec/src/ssl.lua b/vendor/luasec/src/ssl.lua
new file mode 100644
index 00000000..e22c047e
--- /dev/null
+++ b/vendor/luasec/src/ssl.lua
@@ -0,0 +1,313 @@
1------------------------------------------------------------------------------
2-- LuaSec 1.3.2
3--
4-- Copyright (C) 2006-2023 Bruno Silvestre
5--
6------------------------------------------------------------------------------
7
8local core = require("ssl.core")
9local context = require("ssl.context")
10local x509 = require("ssl.x509")
11local config = require("ssl.config")
12
13local unpack = table.unpack or unpack
14
15-- We must prevent the contexts to be collected before the connections,
16-- otherwise the C registry will be cleared.
17local registry = setmetatable({}, {__mode="k"})
18
19--
20--
21--
22local function optexec(func, param, ctx)
23 if param then
24 if type(param) == "table" then
25 return func(ctx, unpack(param))
26 else
27 return func(ctx, param)
28 end
29 end
30 return true
31end
32
33--
34-- Convert an array of strings to wire-format
35--
36local function array2wireformat(array)
37 local str = ""
38 for k, v in ipairs(array) do
39 if type(v) ~= "string" then return nil end
40 local len = #v
41 if len == 0 then
42 return nil, "invalid ALPN name (empty string)"
43 elseif len > 255 then
44 return nil, "invalid ALPN name (length > 255)"
45 end
46 str = str .. string.char(len) .. v
47 end
48 if str == "" then return nil, "invalid ALPN list (empty)" end
49 return str
50end
51
52--
53-- Convert wire-string format to array
54--
55local function wireformat2array(str)
56 local i = 1
57 local array = {}
58 while i < #str do
59 local len = str:byte(i)
60 array[#array + 1] = str:sub(i + 1, i + len)
61 i = i + len + 1
62 end
63 return array
64end
65
66--
67--
68--
69local function newcontext(cfg)
70 local succ, msg, ctx
71 -- Create the context
72 ctx, msg = context.create(cfg.protocol)
73 if not ctx then return nil, msg end
74 -- Mode
75 succ, msg = context.setmode(ctx, cfg.mode)
76 if not succ then return nil, msg end
77 local certificates = cfg.certificates
78 if not certificates then
79 certificates = {
80 { certificate = cfg.certificate, key = cfg.key, password = cfg.password }
81 }
82 end
83 for _, certificate in ipairs(certificates) do
84 -- Load the key
85 if certificate.key then
86 if certificate.password and
87 type(certificate.password) ~= "function" and
88 type(certificate.password) ~= "string"
89 then
90 return nil, "invalid password type"
91 end
92 succ, msg = context.loadkey(ctx, certificate.key, certificate.password)
93 if not succ then return nil, msg end
94 end
95 -- Load the certificate(s)
96 if certificate.certificate then
97 succ, msg = context.loadcert(ctx, certificate.certificate)
98 if not succ then return nil, msg end
99 if certificate.key and context.checkkey then
100 succ = context.checkkey(ctx)
101 if not succ then return nil, "private key does not match public key" end
102 end
103 end
104 end
105 -- Load the CA certificates
106 if cfg.cafile or cfg.capath then
107 succ, msg = context.locations(ctx, cfg.cafile, cfg.capath)
108 if not succ then return nil, msg end
109 end
110 -- Set SSL ciphers
111 if cfg.ciphers then
112 succ, msg = context.setcipher(ctx, cfg.ciphers)
113 if not succ then return nil, msg end
114 end
115 -- Set SSL cipher suites
116 if cfg.ciphersuites then
117 succ, msg = context.setciphersuites(ctx, cfg.ciphersuites)
118 if not succ then return nil, msg end
119 end
120 -- Set the verification options
121 succ, msg = optexec(context.setverify, cfg.verify, ctx)
122 if not succ then return nil, msg end
123 -- Set SSL options
124 succ, msg = optexec(context.setoptions, cfg.options, ctx)
125 if not succ then return nil, msg end
126 -- Set the depth for certificate verification
127 if cfg.depth then
128 succ, msg = context.setdepth(ctx, cfg.depth)
129 if not succ then return nil, msg end
130 end
131
132 -- NOTE: Setting DH parameters and elliptic curves needs to come after
133 -- setoptions(), in case the user has specified the single_{dh,ecdh}_use
134 -- options.
135
136 -- Set DH parameters
137 if cfg.dhparam then
138 if type(cfg.dhparam) ~= "function" then
139 return nil, "invalid DH parameter type"
140 end
141 context.setdhparam(ctx, cfg.dhparam)
142 end
143
144 -- Set elliptic curves
145 if (not config.algorithms.ec) and (cfg.curve or cfg.curveslist) then
146 return false, "elliptic curves not supported"
147 end
148 if config.capabilities.curves_list and cfg.curveslist then
149 succ, msg = context.setcurveslist(ctx, cfg.curveslist)
150 if not succ then return nil, msg end
151 elseif cfg.curve then
152 succ, msg = context.setcurve(ctx, cfg.curve)
153 if not succ then return nil, msg end
154 end
155
156 -- Set extra verification options
157 if cfg.verifyext and ctx.setverifyext then
158 succ, msg = optexec(ctx.setverifyext, cfg.verifyext, ctx)
159 if not succ then return nil, msg end
160 end
161
162 -- ALPN
163 if cfg.mode == "server" and cfg.alpn then
164 if type(cfg.alpn) == "function" then
165 local alpncb = cfg.alpn
166 -- This callback function has to return one value only
167 succ, msg = context.setalpncb(ctx, function(str)
168 local protocols = alpncb(wireformat2array(str))
169 if type(protocols) == "string" then
170 protocols = { protocols }
171 elseif type(protocols) ~= "table" then
172 return nil
173 end
174 return (array2wireformat(protocols)) -- use "()" to drop error message
175 end)
176 if not succ then return nil, msg end
177 elseif type(cfg.alpn) == "table" then
178 local protocols = cfg.alpn
179 -- check if array is valid before use it
180 succ, msg = array2wireformat(protocols)
181 if not succ then return nil, msg end
182 -- This callback function has to return one value only
183 succ, msg = context.setalpncb(ctx, function()
184 return (array2wireformat(protocols)) -- use "()" to drop error message
185 end)
186 if not succ then return nil, msg end
187 else
188 return nil, "invalid ALPN parameter"
189 end
190 elseif cfg.mode == "client" and cfg.alpn then
191 local alpn
192 if type(cfg.alpn) == "string" then
193 alpn, msg = array2wireformat({ cfg.alpn })
194 elseif type(cfg.alpn) == "table" then
195 alpn, msg = array2wireformat(cfg.alpn)
196 else
197 return nil, "invalid ALPN parameter"
198 end
199 if not alpn then return nil, msg end
200 succ, msg = context.setalpn(ctx, alpn)
201 if not succ then return nil, msg end
202 end
203
204 -- PSK
205 if config.capabilities.psk and cfg.psk then
206 if cfg.mode == "client" then
207 if type(cfg.psk) ~= "function" then
208 return nil, "invalid PSK configuration"
209 end
210 succ = context.setclientpskcb(ctx, cfg.psk)
211 if not succ then return nil, msg end
212 elseif cfg.mode == "server" then
213 if type(cfg.psk) == "function" then
214 succ, msg = context.setserverpskcb(ctx, cfg.psk)
215 if not succ then return nil, msg end
216 elseif type(cfg.psk) == "table" then
217 if type(cfg.psk.hint) == "string" and type(cfg.psk.callback) == "function" then
218 succ, msg = context.setpskhint(ctx, cfg.psk.hint)
219 if not succ then return succ, msg end
220 succ = context.setserverpskcb(ctx, cfg.psk.callback)
221 if not succ then return succ, msg end
222 else
223 return nil, "invalid PSK configuration"
224 end
225 else
226 return nil, "invalid PSK configuration"
227 end
228 end
229 end
230
231 if config.capabilities.dane and cfg.dane then
232 if type(cfg.dane) == "table" then
233 context.setdane(ctx, unpack(cfg.dane))
234 else
235 context.setdane(ctx)
236 end
237 end
238
239 return ctx
240end
241
242--
243--
244--
245local function wrap(sock, cfg)
246 local ctx, msg
247 if type(cfg) == "table" then
248 ctx, msg = newcontext(cfg)
249 if not ctx then return nil, msg end
250 else
251 ctx = cfg
252 end
253 local s, msg = core.create(ctx)
254 if s then
255 core.setfd(s, sock:getfd())
256 sock:setfd(core.SOCKET_INVALID)
257 registry[s] = ctx
258 return s
259 end
260 return nil, msg
261end
262
263--
264-- Extract connection information.
265--
266local function info(ssl, field)
267 local str, comp, err, protocol
268 comp, err = core.compression(ssl)
269 if err then
270 return comp, err
271 end
272 -- Avoid parser
273 if field == "compression" then
274 return comp
275 end
276 local info = {compression = comp}
277 str, info.bits, info.algbits, protocol = core.info(ssl)
278 if str then
279 info.cipher, info.protocol, info.key,
280 info.authentication, info.encryption, info.mac =
281 string.match(str,
282 "^(%S+)%s+(%S+)%s+Kx=(%S+)%s+Au=(%S+)%s+Enc=(%S+)%s+Mac=(%S+)")
283 info.export = (string.match(str, "%sexport%s*$") ~= nil)
284 end
285 if protocol then
286 info.protocol = protocol
287 end
288 if field then
289 return info[field]
290 end
291 -- Empty?
292 return ( (next(info)) and info )
293end
294
295--
296-- Set method for SSL connections.
297--
298core.setmethod("info", info)
299
300--------------------------------------------------------------------------------
301-- Export module
302--
303
304local _M = {
305 _VERSION = "1.3.2",
306 _COPYRIGHT = core.copyright(),
307 config = config,
308 loadcertificate = x509.load,
309 newcontext = newcontext,
310 wrap = wrap,
311}
312
313return _M
diff --git a/vendor/luasec/src/x509.c b/vendor/luasec/src/x509.c
new file mode 100644
index 00000000..6833d46f
--- /dev/null
+++ b/vendor/luasec/src/x509.c
@@ -0,0 +1,750 @@
1/*--------------------------------------------------------------------------
2 * LuaSec 1.3.2
3 *
4 * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild
5 * Copyright (C) 2014-2023 Bruno Silvestre
6 *
7 *--------------------------------------------------------------------------*/
8
9#include <stdio.h>
10#include <string.h>
11
12#if defined(WIN32)
13#include <ws2tcpip.h>
14#include <windows.h>
15#else
16#include <sys/types.h>
17#include <sys/socket.h>
18#include <netinet/in.h>
19#include <arpa/inet.h>
20#endif
21
22#include <openssl/ssl.h>
23#include <openssl/x509v3.h>
24#include <openssl/evp.h>
25#include <openssl/err.h>
26#include <openssl/asn1.h>
27#include <openssl/bio.h>
28#include <openssl/bn.h>
29
30#include <lua.h>
31#include <lauxlib.h>
32
33#include "x509.h"
34
35
36#ifndef LSEC_API_OPENSSL_1_1_0
37#define X509_get0_notBefore X509_get_notBefore
38#define X509_get0_notAfter X509_get_notAfter
39#define ASN1_STRING_get0_data ASN1_STRING_data
40#endif
41
42static const char* hex_tab = "0123456789abcdef";
43
44/**
45 * Push the certificate on the stack.
46 */
47void lsec_pushx509(lua_State* L, X509 *cert)
48{
49 p_x509 cert_obj = (p_x509)lua_newuserdata(L, sizeof(t_x509));
50 cert_obj->cert = cert;
51 cert_obj->encode = LSEC_AI5_STRING;
52 luaL_getmetatable(L, "SSL:Certificate");
53 lua_setmetatable(L, -2);
54}
55
56/**
57 * Return the OpenSSL certificate X509.
58 */
59X509* lsec_checkx509(lua_State* L, int idx)
60{
61 return ((p_x509)luaL_checkudata(L, idx, "SSL:Certificate"))->cert;
62}
63
64/**
65 * Return LuaSec certificate X509 representation.
66 */
67p_x509 lsec_checkp_x509(lua_State* L, int idx)
68{
69 return (p_x509)luaL_checkudata(L, idx, "SSL:Certificate");
70}
71
72/*---------------------------------------------------------------------------*/
73
74#if defined(LUASEC_INET_NTOP)
75/*
76 * For WinXP (SP3), set the following preprocessor macros:
77 * LUASEC_INET_NTOP
78 * WINVER=0x0501
79 * _WIN32_WINNT=0x0501
80 * NTDDI_VERSION=0x05010300
81 *
82 * For IPv6 addresses, you need to add IPv6 Protocol to your interface.
83 *
84 */
85static const char *inet_ntop(int af, const char *src, char *dst, socklen_t size)
86{
87 int addrsize;
88 struct sockaddr *addr;
89 struct sockaddr_in addr4;
90 struct sockaddr_in6 addr6;
91
92 switch (af) {
93 case AF_INET:
94 memset((void*)&addr4, 0, sizeof(addr4));
95 addr4.sin_family = AF_INET;
96 memcpy((void*)&addr4.sin_addr, src, sizeof(struct in_addr));
97 addr = (struct sockaddr*)&addr4;
98 addrsize = sizeof(struct sockaddr_in);
99 break;
100 case AF_INET6:
101 memset((void*)&addr6, 0, sizeof(addr6));
102 addr6.sin6_family = AF_INET6;
103 memcpy((void*)&addr6.sin6_addr, src, sizeof(struct in6_addr));
104 addr = (struct sockaddr*)&addr6;
105 addrsize = sizeof(struct sockaddr_in6);
106 break;
107 default:
108 return NULL;
109 }
110
111 if(getnameinfo(addr, addrsize, dst, size, NULL, 0, NI_NUMERICHOST) != 0)
112 return NULL;
113 return dst;
114}
115#endif
116
117/*---------------------------------------------------------------------------*/
118
119/**
120 * Convert the buffer 'in' to hexadecimal.
121 */
122static void to_hex(const char* in, int length, char* out)
123{
124 int i;
125 for (i = 0; i < length; i++) {
126 out[i*2] = hex_tab[(in[i] >> 4) & 0xF];
127 out[i*2+1] = hex_tab[(in[i]) & 0xF];
128 }
129}
130
131/**
132 * Converts the ASN1_OBJECT into a textual representation and put it
133 * on the Lua stack.
134 */
135static void push_asn1_objname(lua_State* L, ASN1_OBJECT *object, int no_name)
136{
137 char buffer[256];
138 int len = OBJ_obj2txt(buffer, sizeof(buffer), object, no_name);
139 len = (len < sizeof(buffer)) ? len : sizeof(buffer);
140 lua_pushlstring(L, buffer, len);
141}
142
143/**
144 * Push the ASN1 string on the stack.
145 */
146static void push_asn1_string(lua_State* L, ASN1_STRING *string, int encode)
147{
148 int len;
149 unsigned char *data;
150 if (!string) {
151 lua_pushnil(L);
152 return;
153 }
154 switch (encode) {
155 case LSEC_AI5_STRING:
156 lua_pushlstring(L, (char*)ASN1_STRING_get0_data(string), ASN1_STRING_length(string));
157 break;
158 case LSEC_UTF8_STRING:
159 len = ASN1_STRING_to_UTF8(&data, string);
160 if (len >= 0) {
161 lua_pushlstring(L, (char*)data, len);
162 OPENSSL_free(data);
163 }
164 else
165 lua_pushnil(L);
166 }
167}
168
169/**
170 * Return a human readable time.
171 */
172static int push_asn1_time(lua_State *L, const ASN1_UTCTIME *tm)
173{
174 char *tmp;
175 long size;
176 BIO *out = BIO_new(BIO_s_mem());
177 ASN1_TIME_print(out, tm);
178 size = BIO_get_mem_data(out, &tmp);
179 lua_pushlstring(L, tmp, size);
180 BIO_free(out);
181 return 1;
182}
183
184/**
185 * Return a human readable IP address.
186 */
187static void push_asn1_ip(lua_State *L, ASN1_STRING *string)
188{
189 int af;
190 char dst[INET6_ADDRSTRLEN];
191 unsigned char *ip = (unsigned char*)ASN1_STRING_get0_data(string);
192 switch(ASN1_STRING_length(string)) {
193 case 4:
194 af = AF_INET;
195 break;
196 case 16:
197 af = AF_INET6;
198 break;
199 default:
200 lua_pushnil(L);
201 return;
202 }
203 if(inet_ntop(af, ip, dst, INET6_ADDRSTRLEN))
204 lua_pushstring(L, dst);
205 else
206 lua_pushnil(L);
207}
208
209/**
210 *
211 */
212static int push_subtable(lua_State* L, int idx)
213{
214 lua_pushvalue(L, -1);
215 lua_gettable(L, idx-1);
216 if (lua_isnil(L, -1)) {
217 lua_pop(L, 1);
218 lua_newtable(L);
219 lua_pushvalue(L, -2);
220 lua_pushvalue(L, -2);
221 lua_settable(L, idx-3);
222 lua_replace(L, -2); /* Replace key with table */
223 return 1;
224 }
225 lua_replace(L, -2); /* Replace key with table */
226 return 0;
227}
228
229/**
230 * Retrieve the general names from the object.
231 */
232static int push_x509_name(lua_State* L, X509_NAME *name, int encode)
233{
234 int i;
235 int n_entries;
236 ASN1_OBJECT *object;
237 X509_NAME_ENTRY *entry;
238 lua_newtable(L);
239 n_entries = X509_NAME_entry_count(name);
240 for (i = 0; i < n_entries; i++) {
241 entry = X509_NAME_get_entry(name, i);
242 object = X509_NAME_ENTRY_get_object(entry);
243 lua_newtable(L);
244 push_asn1_objname(L, object, 1);
245 lua_setfield(L, -2, "oid");
246 push_asn1_objname(L, object, 0);
247 lua_setfield(L, -2, "name");
248 push_asn1_string(L, X509_NAME_ENTRY_get_data(entry), encode);
249 lua_setfield(L, -2, "value");
250 lua_rawseti(L, -2, i+1);
251 }
252 return 1;
253}
254
255/*---------------------------------------------------------------------------*/
256
257/**
258 * Retrieve the Subject from the certificate.
259 */
260static int meth_subject(lua_State* L)
261{
262 p_x509 px = lsec_checkp_x509(L, 1);
263 return push_x509_name(L, X509_get_subject_name(px->cert), px->encode);
264}
265
266/**
267 * Retrieve the Issuer from the certificate.
268 */
269static int meth_issuer(lua_State* L)
270{
271 p_x509 px = lsec_checkp_x509(L, 1);
272 return push_x509_name(L, X509_get_issuer_name(px->cert), px->encode);
273}
274
275/**
276 * Retrieve the extensions from the certificate.
277 */
278int meth_extensions(lua_State* L)
279{
280 int j;
281 int i = -1;
282 int n_general_names;
283 OTHERNAME *otherName;
284 X509_EXTENSION *extension;
285 GENERAL_NAME *general_name;
286 STACK_OF(GENERAL_NAME) *values;
287 p_x509 px = lsec_checkp_x509(L, 1);
288 X509 *peer = px->cert;
289
290 /* Return (ret) */
291 lua_newtable(L);
292
293 while ((i = X509_get_ext_by_NID(peer, NID_subject_alt_name, i)) != -1) {
294 extension = X509_get_ext(peer, i);
295 if (extension == NULL)
296 break;
297 values = X509V3_EXT_d2i(extension);
298 if (values == NULL)
299 break;
300
301 /* Push ret[oid] */
302 push_asn1_objname(L, X509_EXTENSION_get_object(extension), 1);
303 push_subtable(L, -2);
304
305 /* Set ret[oid].name = name */
306 push_asn1_objname(L, X509_EXTENSION_get_object(extension), 0);
307 lua_setfield(L, -2, "name");
308
309 n_general_names = sk_GENERAL_NAME_num(values);
310 for (j = 0; j < n_general_names; j++) {
311 general_name = sk_GENERAL_NAME_value(values, j);
312 switch (general_name->type) {
313 case GEN_OTHERNAME:
314 otherName = general_name->d.otherName;
315 push_asn1_objname(L, otherName->type_id, 1);
316 if (push_subtable(L, -2)) {
317 push_asn1_objname(L, otherName->type_id, 0);
318 lua_setfield(L, -2, "name");
319 }
320 push_asn1_string(L, otherName->value->value.asn1_string, px->encode);
321 lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
322 lua_pop(L, 1);
323 break;
324 case GEN_DNS:
325 lua_pushstring(L, "dNSName");
326 push_subtable(L, -2);
327 push_asn1_string(L, general_name->d.dNSName, px->encode);
328 lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
329 lua_pop(L, 1);
330 break;
331 case GEN_EMAIL:
332 lua_pushstring(L, "rfc822Name");
333 push_subtable(L, -2);
334 push_asn1_string(L, general_name->d.rfc822Name, px->encode);
335 lua_rawseti(L, -2, lua_rawlen(L, -2) + 1);
336 lua_pop(L, 1);
337 break;
338 case GEN_URI:
339 lua_pushstring(L, "uniformResourceIdentifier");
340 push_subtable(L, -2);
341 push_asn1_string(L, general_name->d.uniformResourceIdentifier, px->encode);
342 lua_rawseti(L, -2, lua_rawlen(L, -2)+1);
343 lua_pop(L, 1);
344 break;
345 case GEN_IPADD:
346 lua_pushstring(L, "iPAddress");
347 push_subtable(L, -2);
348 push_asn1_ip(L, general_name->d.iPAddress);
349 lua_rawseti(L, -2, lua_rawlen(L, -2)+1);
350 lua_pop(L, 1);
351 break;
352 case GEN_X400:
353 /* x400Address */
354 /* not supported */
355 break;
356 case GEN_DIRNAME:
357 /* directoryName */
358 /* not supported */
359 break;
360 case GEN_EDIPARTY:
361 /* ediPartyName */
362 /* not supported */
363 break;
364 case GEN_RID:
365 /* registeredID */
366 /* not supported */
367 break;
368 }
369 GENERAL_NAME_free(general_name);
370 }
371 sk_GENERAL_NAME_free(values);
372 lua_pop(L, 1); /* ret[oid] */
373 i++; /* Next extension */
374 }
375 return 1;
376}
377
378/**
379 * Convert the certificate to PEM format.
380 */
381static int meth_pem(lua_State* L)
382{
383 char* data;
384 long bytes;
385 X509* cert = lsec_checkx509(L, 1);
386 BIO *bio = BIO_new(BIO_s_mem());
387 if (!PEM_write_bio_X509(bio, cert)) {
388 lua_pushnil(L);
389 return 1;
390 }
391 bytes = BIO_get_mem_data(bio, &data);
392 if (bytes > 0)
393 lua_pushlstring(L, data, bytes);
394 else
395 lua_pushnil(L);
396 BIO_free(bio);
397 return 1;
398}
399
400/**
401 * Extract public key in PEM format.
402 */
403static int meth_pubkey(lua_State* L)
404{
405 char* data;
406 long bytes;
407 int ret = 1;
408 X509* cert = lsec_checkx509(L, 1);
409 BIO *bio = BIO_new(BIO_s_mem());
410 EVP_PKEY *pkey = X509_get_pubkey(cert);
411 if(PEM_write_bio_PUBKEY(bio, pkey)) {
412 bytes = BIO_get_mem_data(bio, &data);
413 if (bytes > 0) {
414 lua_pushlstring(L, data, bytes);
415 switch(EVP_PKEY_base_id(pkey)) {
416 case EVP_PKEY_RSA:
417 lua_pushstring(L, "RSA");
418 break;
419 case EVP_PKEY_DSA:
420 lua_pushstring(L, "DSA");
421 break;
422 case EVP_PKEY_DH:
423 lua_pushstring(L, "DH");
424 break;
425 case EVP_PKEY_EC:
426 lua_pushstring(L, "EC");
427 break;
428 default:
429 lua_pushstring(L, "Unknown");
430 break;
431 }
432 lua_pushinteger(L, EVP_PKEY_bits(pkey));
433 ret = 3;
434 }
435 else
436 lua_pushnil(L);
437 }
438 else
439 lua_pushnil(L);
440 /* Cleanup */
441 BIO_free(bio);
442 EVP_PKEY_free(pkey);
443 return ret;
444}
445
446/**
447 * Compute the fingerprint.
448 */
449static int meth_digest(lua_State* L)
450{
451 unsigned int bytes;
452 const EVP_MD *digest = NULL;
453 unsigned char buffer[EVP_MAX_MD_SIZE];
454 char hex_buffer[EVP_MAX_MD_SIZE*2];
455 X509 *cert = lsec_checkx509(L, 1);
456 const char *str = luaL_optstring(L, 2, NULL);
457 if (!str)
458 digest = EVP_sha1();
459 else {
460 if (!strcmp(str, "sha1"))
461 digest = EVP_sha1();
462 else if (!strcmp(str, "sha256"))
463 digest = EVP_sha256();
464 else if (!strcmp(str, "sha512"))
465 digest = EVP_sha512();
466 }
467 if (!digest) {
468 lua_pushnil(L);
469 lua_pushfstring(L, "digest algorithm not supported (%s)", str);
470 return 2;
471 }
472 if (!X509_digest(cert, digest, buffer, &bytes)) {
473 lua_pushnil(L);
474 lua_pushfstring(L, "error processing the certificate (%s)",
475 ERR_reason_error_string(ERR_get_error()));
476 return 2;
477 }
478 to_hex((char*)buffer, bytes, hex_buffer);
479 lua_pushlstring(L, hex_buffer, bytes*2);
480 return 1;
481}
482
483/**
484 * Check if the certificate is valid in a given time.
485 */
486static int meth_valid_at(lua_State* L)
487{
488 int nb, na;
489 X509* cert = lsec_checkx509(L, 1);
490 time_t time = luaL_checkinteger(L, 2);
491 nb = X509_cmp_time(X509_get0_notBefore(cert), &time);
492 time -= 1;
493 na = X509_cmp_time(X509_get0_notAfter(cert), &time);
494 lua_pushboolean(L, nb == -1 && na == 1);
495 return 1;
496}
497
498/**
499 * Return the serial number.
500 */
501static int meth_serial(lua_State *L)
502{
503 char *tmp;
504 BIGNUM *bn;
505 ASN1_INTEGER *serial;
506 X509* cert = lsec_checkx509(L, 1);
507 serial = X509_get_serialNumber(cert);
508 bn = ASN1_INTEGER_to_BN(serial, NULL);
509 tmp = BN_bn2hex(bn);
510 lua_pushstring(L, tmp);
511 BN_free(bn);
512 OPENSSL_free(tmp);
513 return 1;
514}
515
516/**
517 * Return not before date.
518 */
519static int meth_notbefore(lua_State *L)
520{
521 X509* cert = lsec_checkx509(L, 1);
522 return push_asn1_time(L, X509_get0_notBefore(cert));
523}
524
525/**
526 * Return not after date.
527 */
528static int meth_notafter(lua_State *L)
529{
530 X509* cert = lsec_checkx509(L, 1);
531 return push_asn1_time(L, X509_get0_notAfter(cert));
532}
533
534/**
535 * Check if this certificate issued some other certificate
536 */
537static int meth_issued(lua_State* L)
538{
539 int ret, i, len;
540
541 X509_STORE_CTX* ctx = NULL;
542 X509_STORE* root = NULL;
543 STACK_OF(X509)* chain = NULL;
544
545 X509* issuer = lsec_checkx509(L, 1);
546 X509* subject = lsec_checkx509(L, 2);
547 X509* cert = NULL;
548
549 len = lua_gettop(L);
550
551 /* Check that all arguments are certificates */
552
553 for (i = 3; i <= len; i++) {
554 lsec_checkx509(L, i);
555 }
556
557 /* Before allocating things that require freeing afterwards */
558
559 chain = sk_X509_new_null();
560 ctx = X509_STORE_CTX_new();
561 root = X509_STORE_new();
562
563 if (ctx == NULL || root == NULL) {
564 lua_pushnil(L);
565 lua_pushstring(L, "X509_STORE_new() or X509_STORE_CTX_new() error");
566 ret = 2;
567 goto cleanup;
568 }
569
570 ret = X509_STORE_add_cert(root, issuer);
571
572 if(!ret) {
573 lua_pushnil(L);
574 lua_pushstring(L, "X509_STORE_add_cert() error");
575 ret = 2;
576 goto cleanup;
577 }
578
579 for (i = 3; i <= len && lua_isuserdata(L, i); i++) {
580 cert = lsec_checkx509(L, i);
581 sk_X509_push(chain, cert);
582 }
583
584 ret = X509_STORE_CTX_init(ctx, root, subject, chain);
585
586 if(!ret) {
587 lua_pushnil(L);
588 lua_pushstring(L, "X509_STORE_CTX_init() error");
589 ret = 2;
590 goto cleanup;
591 }
592
593 /* Actual verification */
594 if (X509_verify_cert(ctx) <= 0) {
595 ret = X509_STORE_CTX_get_error(ctx);
596 lua_pushnil(L);
597 lua_pushstring(L, X509_verify_cert_error_string(ret));
598 ret = 2;
599 } else {
600 lua_pushboolean(L, 1);
601 ret = 1;
602 }
603
604cleanup:
605
606 if (ctx != NULL) {
607 X509_STORE_CTX_free(ctx);
608 }
609
610 if (chain != NULL) {
611 X509_STORE_free(root);
612 }
613
614 sk_X509_free(chain);
615
616 return ret;
617}
618
619/**
620 * Collect X509 objects.
621 */
622static int meth_destroy(lua_State* L)
623{
624 p_x509 px = lsec_checkp_x509(L, 1);
625 if (px->cert) {
626 X509_free(px->cert);
627 px->cert = NULL;
628 }
629 return 0;
630}
631
632static int meth_tostring(lua_State *L)
633{
634 X509* cert = lsec_checkx509(L, 1);
635 lua_pushfstring(L, "X509 certificate: %p", cert);
636 return 1;
637}
638
639/**
640 * Set the encode for ASN.1 string.
641 */
642static int meth_set_encode(lua_State* L)
643{
644 int succ = 0;
645 p_x509 px = lsec_checkp_x509(L, 1);
646 const char *enc = luaL_checkstring(L, 2);
647 if (strncmp(enc, "ai5", 3) == 0) {
648 succ = 1;
649 px->encode = LSEC_AI5_STRING;
650 } else if (strncmp(enc, "utf8", 4) == 0) {
651 succ = 1;
652 px->encode = LSEC_UTF8_STRING;
653 }
654 lua_pushboolean(L, succ);
655 return 1;
656}
657
658#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
659/**
660 * Get signature name.
661 */
662static int meth_get_signature_name(lua_State* L)
663{
664 p_x509 px = lsec_checkp_x509(L, 1);
665 int nid = X509_get_signature_nid(px->cert);
666 const char *name = OBJ_nid2sn(nid);
667 if (!name)
668 lua_pushnil(L);
669 else
670 lua_pushstring(L, name);
671 return 1;
672}
673#endif
674
675/*---------------------------------------------------------------------------*/
676
677static int load_cert(lua_State* L)
678{
679 X509 *cert;
680 size_t bytes;
681 const char* data;
682 BIO *bio = BIO_new(BIO_s_mem());
683 data = luaL_checklstring(L, 1, &bytes);
684 BIO_write(bio, data, bytes);
685 cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
686 if (cert)
687 lsec_pushx509(L, cert);
688 else
689 lua_pushnil(L);
690 BIO_free(bio);
691 return 1;
692}
693
694/*---------------------------------------------------------------------------*/
695
696/**
697 * Certificate methods.
698 */
699static luaL_Reg methods[] = {
700 {"digest", meth_digest},
701 {"setencode", meth_set_encode},
702 {"extensions", meth_extensions},
703#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
704 {"getsignaturename", meth_get_signature_name},
705#endif
706 {"issuer", meth_issuer},
707 {"notbefore", meth_notbefore},
708 {"notafter", meth_notafter},
709 {"issued", meth_issued},
710 {"pem", meth_pem},
711 {"pubkey", meth_pubkey},
712 {"serial", meth_serial},
713 {"subject", meth_subject},
714 {"validat", meth_valid_at},
715 {NULL, NULL}
716};
717
718/**
719 * X509 metamethods.
720 */
721static luaL_Reg meta[] = {
722 {"__close", meth_destroy},
723 {"__gc", meth_destroy},
724 {"__tostring", meth_tostring},
725 {NULL, NULL}
726};
727
728/**
729 * X509 functions.
730 */
731static luaL_Reg funcs[] = {
732 {"load", load_cert},
733 {NULL, NULL}
734};
735
736/*--------------------------------------------------------------------------*/
737
738LSEC_API int luaopen_ssl_x509(lua_State *L)
739{
740 /* Register the functions and tables */
741 luaL_newmetatable(L, "SSL:Certificate");
742 setfuncs(L, meta);
743
744 luaL_newlib(L, methods);
745 lua_setfield(L, -2, "__index");
746
747 luaL_newlib(L, funcs);
748
749 return 1;
750}
diff --git a/vendor/luasec/src/x509.h b/vendor/luasec/src/x509.h
new file mode 100644
index 00000000..acdbe6c0
--- /dev/null
+++ b/vendor/luasec/src/x509.h
@@ -0,0 +1,31 @@
1/*--------------------------------------------------------------------------
2 * LuaSec 1.3.2
3 *
4 * Copyright (C) 2014-2023 Kim Alvefur, Paul Aurich, Tobias Markmann, Matthew Wild
5 * Copyright (C) 2013-2023 Bruno Silvestre
6 *
7 *--------------------------------------------------------------------------*/
8
9#ifndef LSEC_X509_H
10#define LSEC_X509_H
11
12#include <openssl/x509v3.h>
13#include <lua.h>
14
15#include "compat.h"
16
17/* We do not support UniversalString nor BMPString as ASN.1 String types */
18enum { LSEC_AI5_STRING, LSEC_UTF8_STRING };
19
20typedef struct t_x509_ {
21 X509 *cert;
22 int encode;
23} t_x509;
24typedef t_x509* p_x509;
25
26void lsec_pushx509(lua_State* L, X509* cert);
27X509* lsec_checkx509(lua_State* L, int idx);
28
29LSEC_API int luaopen_ssl_x509(lua_State *L);
30
31#endif
diff --git a/vendor/luasocket/.editorconfig b/vendor/luasocket/.editorconfig
new file mode 100644
index 00000000..56ad87df
--- /dev/null
+++ b/vendor/luasocket/.editorconfig
@@ -0,0 +1,23 @@
1root = true
2
3[*]
4end_of_line = lf
5insert_final_newline = true
6trim_trailing_whitespace = true
7charset = utf-8
8
9[{*.lua,*.rockspec,.luacheckrc}]
10indent_style = space
11indent_size = 4
12
13[Makefile]
14indent_style = tab
15indent_size = 4
16
17[*.html]
18indent_style = space
19indent_size = 4
20
21[*.{c,h}]
22indent_style = space
23indent_size = 4
diff --git a/vendor/luasocket/.gitignore b/vendor/luasocket/.gitignore
new file mode 100644
index 00000000..9ed661cf
--- /dev/null
+++ b/vendor/luasocket/.gitignore
@@ -0,0 +1,15 @@
1*.o
2*.so
3*.so.*
4*.obj
5*.lib
6*.dll*
7*.user
8*.sdf
9Debug
10Release
11*.manifest
12*.swp
13*.suo
14x64
15
diff --git a/vendor/luasocket/.luacheckrc b/vendor/luasocket/.luacheckrc
new file mode 100644
index 00000000..8b25dd7a
--- /dev/null
+++ b/vendor/luasocket/.luacheckrc
@@ -0,0 +1,31 @@
1unused_args = false
2redefined = false
3max_line_length = false
4
5not_globals = {
6 "string.len",
7 "table.getn",
8}
9
10include_files = {
11 "**/*.lua",
12 "**/*.rockspec",
13 ".busted",
14 ".luacheckrc",
15}
16
17exclude_files = {
18 "etc/*.lua",
19 "etc/**/*.lua",
20 "test/*.lua",
21 "test/**/*.lua",
22 "samples/*.lua",
23 "samples/**/*.lua",
24 "gem/*.lua",
25 "gem/**/*.lua",
26 -- GH Actions Lua Environment
27 ".lua",
28 ".luarocks",
29 ".install",
30}
31
diff --git a/vendor/luasocket/CHANGELOG.md b/vendor/luasocket/CHANGELOG.md
new file mode 100644
index 00000000..3a25186b
--- /dev/null
+++ b/vendor/luasocket/CHANGELOG.md
@@ -0,0 +1,65 @@
1# Changelog
2
3## [v3.1.0](https://github.com/lunarmodules/luasocket/releases/v3.1.0) — 2022-07-27
4
5* Add support for TCP Defer Accept – @Zash
6* Add support for TCP Fast Open – @Zash
7* Fix Windows (mingw32) builds – @goldenstein64
8* Avoid build warnings on 64-bit Windows – @rpatters1
9
10## [v3.0.0](https://github.com/lunarmodules/luasocket/releases/v3.0.0) — 2022-03-25
11
12The last time LuaSocket had a stable release tag was 14 years ago when 2.0.2 was tagged.
13A v3 release candidate was tagged 9 years ago.
14Since then it has been downloaded over 3 million times.
15Additionally the Git repository regularly gets several hundred clones a day.
16But 9 years is a long time and even the release candidate has grown a bit long in the tooth.
17Many Linux distros have packaged the current Git HEAD or some specific tested point as dated or otherwise labeled releases.
18256 commits later and having been migrated to the @lunarmodules org namespace on GitHub, please welcome v3.
19
20This release is a "safe-harbor" tag that represents a minimal amount of changes to get a release tagged.
21Beyond some CI tooling, very little code has changed since migration to @lunarmodules ([5b18e47..e47d98f](https://github.com/lunarmodules/luasocket/compare/5b18e47..e47d98f?w=1)):
22
23* Lua 5.4.3+ support – @pkulchenko, @Zash
24* Cleanup minor issues to get a code linter to pass – @Tieske, @jyoui, @alerque
25* Update Visual Studio build rules for Lua 5.1 – @ewestbrook
26* Set http transfer-encoding even without content-length – @tokenrove
27
28Prior to migration to @lunarmodules ([v3.0-rc1..5b18e47](https://github.com/lunarmodules/luasocket/compare/v3.0-rc1..5b18e47?w=1)) many things happened of which the author of this changelog is not fully apprised.
29Your best bet if it affects your project somehow is to read the commit log & diffs yourself.
30
31## [v3.0-rc1](https://github.com/lunarmodules/luasocket/releases/v3.0-rc1) — 2013-06-14
32
33Main changes for LuaSocket 3.0-rc1 are IPv6 support and Lua 5.2 compatibility.
34
35* Added: Compatible with Lua 5.2
36 - Note that unless you define LUA_COMPAT_MODULE, package tables will not be exported as globals!
37* Added: IPv6 support;
38 - Socket.connect and socket.bind support IPv6 addresses;
39 - Getpeername and getsockname support IPv6 addresses, and return the socket family as a third value;
40 - URL module updated to support IPv6 host names;
41 - New socket.tcp6 and socket.udp6 functions;
42 - New socket.dns.getaddrinfo and socket.dns.getnameinfo functions;
43* Added: getoption method;
44* Fixed: url.unescape was returning additional values;
45* Fixed: mime.qp, mime.unqp, mime.b64, and mime.unb64 could mistaking their own stack slots for functions arguments;
46* Fixed: Receiving zero-length datagram is now possible;
47* Improved: Hidden all internal library symbols;
48* Improved: Better error messages;
49* Improved: Better documentation of socket options.
50* Fixed: manual sample of HTTP authentication now uses correct "authorization" header (Alexandre Ittner);
51* Fixed: failure on bind() was destroying the socket (Sam Roberts);
52* Fixed: receive() returns immediatelly if prefix can satisfy bytes requested (M Joonas Pihlaja);
53* Fixed: multicast didn't work on Windows, or anywhere else for that matter (Herbert Leuwer, Adrian Sietsma);
54* Fixed: select() now reports an error when called with more sockets than FD_SETSIZE (Lorenzo Leonini);
55* Fixed: manual links to home.html changed to index.html (Robert Hahn);
56* Fixed: mime.unb64() would return an empty string on results that started with a null character (Robert Raschke);
57* Fixed: HTTP now automatically redirects on 303 and 307 (Jonathan Gray);
58* Fixed: calling sleep() with negative numbers could block forever, wasting CPU. Now it returns immediately (MPB);
59* Improved: FTP commands are now sent in upper case to help buggy servers (Anders Eurenius);
60* Improved: known headers now sent in canonic capitalization to help buggy servers (Joseph Stewart);
61* Improved: Clarified tcp:receive() in the manual (MPB);
62* Improved: Decent makefiles (LHF).
63* Fixed: RFC links in documentation now point to IETF (Cosmin Apreutesei).
64
65## [v2.0.2](https://github.com/lunarmodules/luasocket/releases/v2.0.2) — 2007-09-11
diff --git a/vendor/luasocket/FIX b/vendor/luasocket/FIX
new file mode 100644
index 00000000..40f30a15
--- /dev/null
+++ b/vendor/luasocket/FIX
@@ -0,0 +1,28 @@
1
2
3
4
5
6
7http was preserving old host header during redirects
8fix smtp.send hang on source error
9add create field to FTP and SMTP and fix HTTP ugliness
10clean timeout argument to open functions in SMTP, HTTP and FTP
11eliminate globals from namespaces created by module().
12url.absolute was not working when base_url was already parsed
13http.request was redirecting even when the location header was empty
14tcp{client}:shutdown() was checking for group instead of class.
15tcp{client}:send() now returns i+sent-1...
16get rid of a = socket.try() in the manual, except for protected cases. replace it with assert.
17get rid of "base." kludge in package.loaded
18check all "require("http")" etc in the manual.
19make sure sock_gethostname.* only return success if the hp is not null!
20change 'l' prefix in C libraries to 'c' to avoid clash with LHF libraries
21 don't forget the declarations in luasocket.h and mime.h!!!
22setpeername was using udp{unconnected}
23fixed a bug in http.lua that caused some requests to fail (Florian Berger)
24fixed a bug in select.c that prevented sockets with descriptor 0 from working (Renato Maia)
25fixed a "bug" that caused dns.toip to crash under uLinux
26fixed a "bug" that caused a crash in gethostbyname under VMS
27DEBUG and VERSION became _DEBUG and _VERSION
28send returns the right value if input is "". Alexander Marinov
diff --git a/vendor/luasocket/LICENSE b/vendor/luasocket/LICENSE
new file mode 100644
index 00000000..a8ed03ea
--- /dev/null
+++ b/vendor/luasocket/LICENSE
@@ -0,0 +1,19 @@
1Copyright (C) 2004-2022 Diego Nehab
2
3Permission is hereby granted, free of charge, to any person obtaining a
4copy of this software and associated documentation files (the "Software"),
5to deal in the Software without restriction, including without limitation
6the rights to use, copy, modify, merge, publish, distribute, sublicense,
7and/or sell copies of the Software, and to permit persons to whom the
8Software is furnished to do so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in
11all copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19DEALINGS IN THE SOFTWARE.
diff --git a/vendor/luasocket/README.md b/vendor/luasocket/README.md
new file mode 100644
index 00000000..af722be6
--- /dev/null
+++ b/vendor/luasocket/README.md
@@ -0,0 +1,12 @@
1# LuaSocket
2
3
4[![Build](https://img.shields.io/github/workflow/status/lunarmodules/luasocket/Build?label=Build=Lua)](https://github.com/lunarmodules/luasocket/actions?workflow=Build)
5[![Luacheck](https://img.shields.io/github/workflow/status/lunarmodules/luasocket/Luacheck?label=Luacheck&logo=Lua)](https://github.com/lunarmodules/luasocket/actions?workflow=Luacheck)
6[![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/lunarmodules/luasocket?label=Tag&logo=GitHub)](https://github.com/lunarmodules/luasocket/releases)
7[![Luarocks](https://img.shields.io/luarocks/v/lunarmodules/luasocket?label=Luarocks&logo=Lua)](https://luarocks.org/modules/lunarmodules/luasocket)
8
9LuaSocket is a Lua extension library composed of two parts:
10
111. a set of C modules that provide support for the TCP and UDP transport layers, and
122. a set of Lua modules that provide functions commonly needed by applications that deal with the Internet.
diff --git a/vendor/luasocket/TODO b/vendor/luasocket/TODO
new file mode 100644
index 00000000..a838fc02
--- /dev/null
+++ b/vendor/luasocket/TODO
@@ -0,0 +1,81 @@
1- bizarre default values for getnameinfo should throw error instead!
2
3> It's just too bad it can't talk to gmail -
4> reason 1: they absolutely want TLS
5> reason 2: unlike all the other SMTP implementations, they
6> don't
7> tolerate missing < > around adresses
8
9- document the new bind and connect behavior.
10- shouldn't we instead make the code compatible to Lua 5.2
11 without any compat stuff, and use a compatibility layer to
12 make it work on 5.1?
13- add what's new to manual
14- should there be an equivalent to tohostname for IPv6?
15- should we add service name resolution as well to getaddrinfo?
16- Maybe the sockaddr to presentation conversion should be done with getnameinfo()?
17
18- add http POST sample to manual
19 people keep asking stupid questions
20- documentation of dirty/getfd/setfd is problematic because of portability
21 same for unix and serial.
22 what to do about this? add a stronger disclaimer?
23- fix makefile with decent defaults?
24
25Done:
26
27- added IPv6 support to getsockname
28- simplified getpeername implementation
29- added family to return of getsockname and getpeername
30 and added modification to the manual to describe
31
32- connect and bind try all adresses returned by getaddrinfo
33- document headers.lua?
34- update copyright date everywhere?
35- remove RCSID from files?
36- move version to 2.1 rather than 2.1.1?
37- fixed url package to support ipv6 hosts
38- changed domain to family
39- implement getfamily methods.
40
41- remove references to Lua 5.0 from documentation, add 5.2?
42- update lua and luasocket version in samples in documentation
43- document ipv5_v6only default option being set?
44- document tcp6 and udp6
45- document dns.getaddrinfo
46- documented zero-sized datagram change?
47 no.
48- document unix socket and serial socket? add raw support?
49 no.
50- document getoption
51- merge luaL_typeerror into auxiliar to avoid using luaL prefix?
52
53
54
55
56
57
58
59
60
61
62replace \r\n with \0xD\0xA in everything
63New mime support
64
65ftp send should return server replies?
66make sure there are no object files in the distribution tarball
67http handling of 100-continue, see DB patch
68DB ftp.lua bug.
69test unix.c to return just a function and works with require"unix"
70get rid of setmetatable(, nil) since packages don't need this anymore in 5.1
71compat-5.1 novo
72ajeitar pra lua-5.1
73
74adicionar exemplos de expansão: pipe, local, named pipe
75testar os options!
76
77
78- Thread-unsafe functions to protect
79 gethostbyname(), gethostbyaddr(), gethostent(),
80inet_ntoa(), strerror(),
81
diff --git a/vendor/luasocket/WISH b/vendor/luasocket/WISH
new file mode 100644
index 00000000..e7e9c076
--- /dev/null
+++ b/vendor/luasocket/WISH
@@ -0,0 +1,22 @@
1... as an l-value to get all results of a function call?
2at least ...[i] and #...
3extend to full tuples?
4
5__and __or __not metamethods
6
7lua_tostring, lua_tonumber, lua_touseradta etc push values in stack
8__tostring,__tonumber, __touserdata metamethods are checked
9and expected to push an object of correct type on stack
10
11lua_rawtostring, lua_rawtonumber, lua_rawtouserdata don't
12push anything on stack, return data of appropriate type,
13skip metamethods and throw error if object not of exact type
14
15package.findfile exported
16module not polluting the global namespace
17
18coxpcall with a coroutine pool for efficiency (reusing coroutines)
19
20exception mechanism formalized? just like the package system was.
21
22a nice bitlib in the core
diff --git a/vendor/luasocket/logo.ps b/vendor/luasocket/logo.ps
new file mode 100644
index 00000000..8b5809ab
--- /dev/null
+++ b/vendor/luasocket/logo.ps
@@ -0,0 +1,210 @@
1%!PS-Adobe-2.0 EPSF-2.0
2%%Title: Lua logo
3%%Creator: lua@tecgraf.puc-rio.br
4%%CreationDate: Wed Nov 29 19:04:04 EDT 2000
5%%BoundingBox: -45 0 1035 1080
6%%Pages: 1
7%%EndComments
8%%EndProlog
9
10%------------------------------------------------------------------------------
11%
12% Copyright (C) 1998-2000. All rights reserved.
13% Graphic design by Alexandre Nakonechny (nako@openlink.com.br).
14% PostScript programming by the Lua team (lua@tecgraf.puc-rio.br).
15%
16% Permission is hereby granted, without written agreement and without license
17% or royalty fees, to use, copy, and distribute this logo for any purpose,
18% including commercial applications, subject to the following conditions:
19%
20% * The origin of this logo must not be misrepresented; you must not
21% claim that you drew the original logo. We recommend that you give credit
22% to the graphics designer in all printed matter that includes the logo.
23%
24% * The only modification you can make is to adapt the orbiting text to
25% your product name.
26%
27% * The logo can be used in any scale as long as the relative proportions
28% of its elements are maintained.
29%
30%------------------------------------------------------------------------------
31
32/LABEL (tekcoS) def
33
34%-- DO NOT CHANGE ANYTHING BELOW THIS LINE ------------------------------------
35
36/PLANETCOLOR {0 0 0.5 setrgbcolor} bind def
37/HOLECOLOR {1.0 setgray} bind def
38/ORBITCOLOR {0.5 setgray} bind def
39/LOGOFONT {/Helvetica 0.90} def
40/LABELFONT {/Helvetica 0.36} def
41
42%------------------------------------------------------------------------------
43
44/MOONCOLOR {PLANETCOLOR} bind def
45/LOGOCOLOR {HOLECOLOR} bind def
46/LABELCOLOR {ORBITCOLOR} bind def
47
48/LABELANGLE 325 def
49/LOGO (Lua) def
50
51/DASHANGLE 10 def
52/HALFDASHANGLE DASHANGLE 2 div def
53
54% moon radius. planet radius is 1.
55/r 1 2 sqrt 2 div sub def
56
57/D {0 360 arc fill} bind def
58/F {exch findfont exch scalefont setfont} bind def
59
60% place it nicely on the paper
61/RESOLUTION 1024 def
62RESOLUTION 2 div dup translate
63RESOLUTION 2 div 2 sqrt div dup scale
64
65%-------------------------------------------------------------------- planet --
66PLANETCOLOR
670 0 1 D
68
69%---------------------------------------------------------------------- hole --
70HOLECOLOR
711 2 r mul sub dup r D
72
73%---------------------------------------------------------------------- moon --
74MOONCOLOR
751 1 r D
76
77%---------------------------------------------------------------------- logo --
78LOGOCOLOR
79LOGOFONT
80F
81LOGO stringwidth pop 2 div neg
82-0.5 moveto
83LOGO show
84
85%------------------------------------------------------------------------------
86% based on code from Blue Book Program 10, on pages 167--169
87% available at ftp://ftp.adobe.com/pub/adobe/displaypostscript/bluebook.shar
88
89% str ptsize centerangle radius outsidecircletext --
90/outsidecircletext {
91 circtextdict begin
92 /radius exch def
93 /centerangle exch def
94 /ptsize exch def
95 /str exch def
96
97 gsave
98 str radius ptsize findhalfangle
99 centerangle
100 add rotate
101 str
102 { /charcode exch def
103 ( ) dup 0 charcode put outsideplacechar
104 } forall
105
106 grestore
107 end
108} def
109
110% string radius ptsize findhalfangle halfangle
111/findhalfangle {
112 4 div add
113 exch
114 stringwidth pop 2 div
115 exch
116 2 mul 3.1415926535 mul div 360 mul
117} def
118
119/circtextdict 16 dict def
120circtextdict begin
121
122 /outsideplacechar {
123 /char exch def
124 /halfangle char radius ptsize findhalfangle def
125 gsave
126 halfangle neg rotate
127 1.4 0 translate
128 90 rotate
129 char stringwidth pop 2 div neg 0 moveto
130 char show
131 grestore
132 halfangle 2 mul neg rotate
133 } def
134
135end
136
137%--------------------------------------------------------------------- label --
138LABELFONT
139F
140
141/LABELSIZE LABELFONT exch pop def
142/LABELRADIUS LABELSIZE 3 div 1 r add sub neg 1.02 mul def
143
144
145/HALFANGLE
146 LABEL LABELRADIUS LABELSIZE findhalfangle
147 HALFDASHANGLE div ceiling HALFDASHANGLE mul
148def
149
150/LABELANGLE
151 60 LABELANGLE HALFANGLE sub
152 lt
153 {
154 HALFANGLE
155 HALFANGLE DASHANGLE div floor DASHANGLE mul
156 eq
157 {LABELANGLE DASHANGLE div ceiling DASHANGLE mul}
158 {LABELANGLE HALFDASHANGLE sub DASHANGLE div round DASHANGLE mul HALFDASHANGLE add}
159 ifelse
160 }
161 {HALFANGLE 60 add}
162 ifelse
163def
164
165LABELCOLOR
166LABEL
167LABELSIZE
168LABELANGLE
169LABELRADIUS
170outsidecircletext
171
172%--------------------------------------------------------------------- orbit --
173ORBITCOLOR
1740.03 setlinewidth
175[1 r add 3.1415926535 180 div HALFDASHANGLE mul mul] 0 setdash
176newpath
1770 0
1781 r add
1793 copy
18030
181LABELANGLE HALFANGLE add
182arcn
183stroke
18460
185LABELANGLE HALFANGLE sub
1862 copy
187lt {arc stroke} {4 {pop} repeat} ifelse
188
189%------------------------------------------------------------------ copyright --
190/COPYRIGHT
191(Graphic design by A. Nakonechny. Copyright (c) 1998, All rights reserved.)
192def
193
194LABELCOLOR
195LOGOFONT
19632 div
197F
1982 sqrt 0.99 mul
199dup
200neg
201moveto
202COPYRIGHT
20390 rotate
204%show
205
206%---------------------------------------------------------------------- done --
207showpage
208
209%%Trailer
210%%EOF
diff --git a/vendor/luasocket/luasocket-scm-3.rockspec b/vendor/luasocket/luasocket-scm-3.rockspec
new file mode 100644
index 00000000..10452510
--- /dev/null
+++ b/vendor/luasocket/luasocket-scm-3.rockspec
@@ -0,0 +1,135 @@
1package = "LuaSocket"
2version = "scm-3"
3source = {
4 url = "git+https://github.com/lunarmodules/luasocket.git",
5 branch = "master"
6}
7description = {
8 summary = "Network support for the Lua language",
9 detailed = [[
10 LuaSocket is a Lua extension library composed of two parts: a set of C
11 modules that provide support for the TCP and UDP transport layers, and a
12 set of Lua modules that provide functions commonly needed by applications
13 that deal with the Internet.
14 ]],
15 homepage = "https://github.com/lunarmodules/luasocket",
16 license = "MIT"
17}
18dependencies = {
19 "lua >= 5.1"
20}
21
22local function make_plat(plat)
23 local defines = {
24 unix = {
25 "LUASOCKET_DEBUG"
26 },
27 macosx = {
28 "LUASOCKET_DEBUG",
29 "UNIX_HAS_SUN_LEN"
30 },
31 win32 = {
32 "LUASOCKET_DEBUG",
33 "NDEBUG"
34 },
35 mingw32 = {
36 "LUASOCKET_DEBUG",
37 -- "LUASOCKET_INET_PTON",
38 "WINVER=0x0501"
39 }
40 }
41 local modules = {
42 ["socket.core"] = {
43 sources = {
44 "src/luasocket.c"
45 , "src/timeout.c"
46 , "src/buffer.c"
47 , "src/io.c"
48 , "src/auxiliar.c"
49 , "src/options.c"
50 , "src/inet.c"
51 , "src/except.c"
52 , "src/select.c"
53 , "src/tcp.c"
54 , "src/udp.c"
55 , "src/compat.c" },
56 defines = defines[plat],
57 incdir = "/src"
58 },
59 ["mime.core"] = {
60 sources = { "src/mime.c", "src/compat.c" },
61 defines = defines[plat],
62 incdir = "/src"
63 },
64 ["socket.http"] = "src/http.lua",
65 ["socket.url"] = "src/url.lua",
66 ["socket.tp"] = "src/tp.lua",
67 ["socket.ftp"] = "src/ftp.lua",
68 ["socket.headers"] = "src/headers.lua",
69 ["socket.smtp"] = "src/smtp.lua",
70 ltn12 = "src/ltn12.lua",
71 socket = "src/socket.lua",
72 mime = "src/mime.lua"
73 }
74 if plat == "unix"
75 or plat == "macosx"
76 or plat == "haiku"
77 then
78 modules["socket.core"].sources[#modules["socket.core"].sources+1] = "src/usocket.c"
79 if plat == "haiku" then
80 modules["socket.core"].libraries = {"network"}
81 end
82 modules["socket.unix"] = {
83 sources = {
84 "src/buffer.c"
85 , "src/compat.c"
86 , "src/auxiliar.c"
87 , "src/options.c"
88 , "src/timeout.c"
89 , "src/io.c"
90 , "src/usocket.c"
91 , "src/unix.c"
92 , "src/unixdgram.c"
93 , "src/unixstream.c" },
94 defines = defines[plat],
95 incdir = "/src"
96 }
97 modules["socket.serial"] = {
98 sources = {
99 "src/buffer.c"
100 , "src/compat.c"
101 , "src/auxiliar.c"
102 , "src/options.c"
103 , "src/timeout.c"
104 , "src/io.c"
105 , "src/usocket.c"
106 , "src/serial.c" },
107 defines = defines[plat],
108 incdir = "/src"
109 }
110 end
111 if plat == "win32"
112 or plat == "mingw32"
113 then
114 modules["socket.core"].sources[#modules["socket.core"].sources+1] = "src/wsocket.c"
115 modules["socket.core"].libraries = { "ws2_32" }
116 modules["socket.core"].libdirs = {}
117 end
118 return { modules = modules }
119end
120
121build = {
122 type = "builtin",
123 platforms = {
124 unix = make_plat("unix"),
125 macosx = make_plat("macosx"),
126 haiku = make_plat("haiku"),
127 win32 = make_plat("win32"),
128 mingw32 = make_plat("mingw32")
129 },
130 copy_directories = {
131 "docs"
132 , "samples"
133 , "etc"
134 , "test" }
135}
diff --git a/vendor/luasocket/luasocket.sln b/vendor/luasocket/luasocket.sln
new file mode 100644
index 00000000..0e5cdc73
--- /dev/null
+++ b/vendor/luasocket/luasocket.sln
@@ -0,0 +1,35 @@
1Microsoft Visual Studio Solution File, Format Version 12.00
2# Visual Studio 2012
3Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "socket", "socket.vcxproj", "{66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}"
4EndProject
5Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mime", "mime.vcxproj", "{128E8BD0-174A-48F0-8771-92B1E8D18713}"
6EndProject
7Global
8 GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 Debug|Win32 = Debug|Win32
10 Debug|x64 = Debug|x64
11 Release|Win32 = Release|Win32
12 Release|x64 = Release|x64
13 EndGlobalSection
14 GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug|Win32.ActiveCfg = Debug|Win32
16 {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug|Win32.Build.0 = Debug|Win32
17 {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug|x64.ActiveCfg = Debug|x64
18 {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Debug|x64.Build.0 = Debug|x64
19 {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release|Win32.ActiveCfg = Release|Win32
20 {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release|Win32.Build.0 = Release|Win32
21 {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release|x64.ActiveCfg = Release|x64
22 {66E3CE14-884D-4AEA-9F20-15A0BEAF8C5A}.Release|x64.Build.0 = Release|x64
23 {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug|Win32.ActiveCfg = Debug|Win32
24 {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug|Win32.Build.0 = Debug|Win32
25 {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug|x64.ActiveCfg = Debug|x64
26 {128E8BD0-174A-48F0-8771-92B1E8D18713}.Debug|x64.Build.0 = Debug|x64
27 {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release|Win32.ActiveCfg = Release|Win32
28 {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release|Win32.Build.0 = Release|Win32
29 {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release|x64.ActiveCfg = Release|x64
30 {128E8BD0-174A-48F0-8771-92B1E8D18713}.Release|x64.Build.0 = Release|x64
31 EndGlobalSection
32 GlobalSection(SolutionProperties) = preSolution
33 HideSolutionNode = FALSE
34 EndGlobalSection
35EndGlobal
diff --git a/vendor/luasocket/src/auxiliar.c b/vendor/luasocket/src/auxiliar.c
new file mode 100644
index 00000000..93a66a09
--- /dev/null
+++ b/vendor/luasocket/src/auxiliar.c
@@ -0,0 +1,154 @@
1/*=========================================================================*\
2* Auxiliar routines for class hierarchy manipulation
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6#include "auxiliar.h"
7#include <string.h>
8#include <stdio.h>
9
10/*-------------------------------------------------------------------------*\
11* Initializes the module
12\*-------------------------------------------------------------------------*/
13int auxiliar_open(lua_State *L) {
14 (void) L;
15 return 0;
16}
17
18/*-------------------------------------------------------------------------*\
19* Creates a new class with given methods
20* Methods whose names start with __ are passed directly to the metatable.
21\*-------------------------------------------------------------------------*/
22void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func) {
23 luaL_newmetatable(L, classname); /* mt */
24 /* create __index table to place methods */
25 lua_pushstring(L, "__index"); /* mt,"__index" */
26 lua_newtable(L); /* mt,"__index",it */
27 /* put class name into class metatable */
28 lua_pushstring(L, "class"); /* mt,"__index",it,"class" */
29 lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */
30 lua_rawset(L, -3); /* mt,"__index",it */
31 /* pass all methods that start with _ to the metatable, and all others
32 * to the index table */
33 for (; func->name; func++) { /* mt,"__index",it */
34 lua_pushstring(L, func->name);
35 lua_pushcfunction(L, func->func);
36 lua_rawset(L, func->name[0] == '_' ? -5: -3);
37 }
38 lua_rawset(L, -3); /* mt */
39 lua_pop(L, 1);
40}
41
42/*-------------------------------------------------------------------------*\
43* Prints the value of a class in a nice way
44\*-------------------------------------------------------------------------*/
45int auxiliar_tostring(lua_State *L) {
46 char buf[32];
47 if (!lua_getmetatable(L, 1)) goto error;
48 lua_pushstring(L, "__index");
49 lua_gettable(L, -2);
50 if (!lua_istable(L, -1)) goto error;
51 lua_pushstring(L, "class");
52 lua_gettable(L, -2);
53 if (!lua_isstring(L, -1)) goto error;
54 sprintf(buf, "%p", lua_touserdata(L, 1));
55 lua_pushfstring(L, "%s: %s", lua_tostring(L, -1), buf);
56 return 1;
57error:
58 lua_pushstring(L, "invalid object passed to 'auxiliar.c:__tostring'");
59 lua_error(L);
60 return 1;
61}
62
63/*-------------------------------------------------------------------------*\
64* Insert class into group
65\*-------------------------------------------------------------------------*/
66void auxiliar_add2group(lua_State *L, const char *classname, const char *groupname) {
67 luaL_getmetatable(L, classname);
68 lua_pushstring(L, groupname);
69 lua_pushboolean(L, 1);
70 lua_rawset(L, -3);
71 lua_pop(L, 1);
72}
73
74/*-------------------------------------------------------------------------*\
75* Make sure argument is a boolean
76\*-------------------------------------------------------------------------*/
77int auxiliar_checkboolean(lua_State *L, int objidx) {
78 if (!lua_isboolean(L, objidx))
79 auxiliar_typeerror(L, objidx, lua_typename(L, LUA_TBOOLEAN));
80 return lua_toboolean(L, objidx);
81}
82
83/*-------------------------------------------------------------------------*\
84* Return userdata pointer if object belongs to a given class, abort with
85* error otherwise
86\*-------------------------------------------------------------------------*/
87void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) {
88 void *data = auxiliar_getclassudata(L, classname, objidx);
89 if (!data) {
90 char msg[45];
91 sprintf(msg, "%.35s expected", classname);
92 luaL_argerror(L, objidx, msg);
93 }
94 return data;
95}
96
97/*-------------------------------------------------------------------------*\
98* Return userdata pointer if object belongs to a given group, abort with
99* error otherwise
100\*-------------------------------------------------------------------------*/
101void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx) {
102 void *data = auxiliar_getgroupudata(L, groupname, objidx);
103 if (!data) {
104 char msg[45];
105 sprintf(msg, "%.35s expected", groupname);
106 luaL_argerror(L, objidx, msg);
107 }
108 return data;
109}
110
111/*-------------------------------------------------------------------------*\
112* Set object class
113\*-------------------------------------------------------------------------*/
114void auxiliar_setclass(lua_State *L, const char *classname, int objidx) {
115 luaL_getmetatable(L, classname);
116 if (objidx < 0) objidx--;
117 lua_setmetatable(L, objidx);
118}
119
120/*-------------------------------------------------------------------------*\
121* Get a userdata pointer if object belongs to a given group. Return NULL
122* otherwise
123\*-------------------------------------------------------------------------*/
124void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) {
125 if (!lua_getmetatable(L, objidx))
126 return NULL;
127 lua_pushstring(L, groupname);
128 lua_rawget(L, -2);
129 if (lua_isnil(L, -1)) {
130 lua_pop(L, 2);
131 return NULL;
132 } else {
133 lua_pop(L, 2);
134 return lua_touserdata(L, objidx);
135 }
136}
137
138/*-------------------------------------------------------------------------*\
139* Get a userdata pointer if object belongs to a given class. Return NULL
140* otherwise
141\*-------------------------------------------------------------------------*/
142void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) {
143 return luaL_testudata(L, objidx, classname);
144}
145
146/*-------------------------------------------------------------------------*\
147* Throws error when argument does not have correct type.
148* Used to be part of lauxlib in Lua 5.1, was dropped from 5.2.
149\*-------------------------------------------------------------------------*/
150int auxiliar_typeerror (lua_State *L, int narg, const char *tname) {
151 const char *msg = lua_pushfstring(L, "%s expected, got %s", tname,
152 luaL_typename(L, narg));
153 return luaL_argerror(L, narg, msg);
154}
diff --git a/vendor/luasocket/src/auxiliar.h b/vendor/luasocket/src/auxiliar.h
new file mode 100644
index 00000000..e8c3ead8
--- /dev/null
+++ b/vendor/luasocket/src/auxiliar.h
@@ -0,0 +1,54 @@
1#ifndef AUXILIAR_H
2#define AUXILIAR_H
3/*=========================================================================*\
4* Auxiliar routines for class hierarchy manipulation
5* LuaSocket toolkit (but completely independent of other LuaSocket modules)
6*
7* A LuaSocket class is a name associated with Lua metatables. A LuaSocket
8* group is a name associated with a class. A class can belong to any number
9* of groups. This module provides the functionality to:
10*
11* - create new classes
12* - add classes to groups
13* - set the class of objects
14* - check if an object belongs to a given class or group
15* - get the userdata associated to objects
16* - print objects in a pretty way
17*
18* LuaSocket class names follow the convention <module>{<class>}. Modules
19* can define any number of classes and groups. The module tcp.c, for
20* example, defines the classes tcp{master}, tcp{client} and tcp{server} and
21* the groups tcp{client,server} and tcp{any}. Module functions can then
22* perform type-checking on their arguments by either class or group.
23*
24* LuaSocket metatables define the __index metamethod as being a table. This
25* table has one field for each method supported by the class, and a field
26* "class" with the class name.
27*
28* The mapping from class name to the corresponding metatable and the
29* reverse mapping are done using lauxlib.
30\*=========================================================================*/
31
32#include "luasocket.h"
33
34#ifndef _WIN32
35#pragma GCC visibility push(hidden)
36#endif
37
38int auxiliar_open(lua_State *L);
39void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func);
40int auxiliar_tostring(lua_State *L);
41void auxiliar_add2group(lua_State *L, const char *classname, const char *group);
42int auxiliar_checkboolean(lua_State *L, int objidx);
43void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx);
44void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx);
45void auxiliar_setclass(lua_State *L, const char *classname, int objidx);
46void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx);
47void *auxiliar_getclassudata(lua_State *L, const char *groupname, int objidx);
48int auxiliar_typeerror(lua_State *L, int narg, const char *tname);
49
50#ifndef _WIN32
51#pragma GCC visibility pop
52#endif
53
54#endif /* AUXILIAR_H */
diff --git a/vendor/luasocket/src/buffer.c b/vendor/luasocket/src/buffer.c
new file mode 100644
index 00000000..7148be34
--- /dev/null
+++ b/vendor/luasocket/src/buffer.c
@@ -0,0 +1,273 @@
1/*=========================================================================*\
2* Input/Output interface for Lua programs
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6#include "buffer.h"
7
8/*=========================================================================*\
9* Internal function prototypes
10\*=========================================================================*/
11static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b);
12static int recvline(p_buffer buf, luaL_Buffer *b);
13static int recvall(p_buffer buf, luaL_Buffer *b);
14static int buffer_get(p_buffer buf, const char **data, size_t *count);
15static void buffer_skip(p_buffer buf, size_t count);
16static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent);
17
18/* min and max macros */
19#ifndef MIN
20#define MIN(x, y) ((x) < (y) ? x : y)
21#endif
22#ifndef MAX
23#define MAX(x, y) ((x) > (y) ? x : y)
24#endif
25
26/*=========================================================================*\
27* Exported functions
28\*=========================================================================*/
29/*-------------------------------------------------------------------------*\
30* Initializes module
31\*-------------------------------------------------------------------------*/
32int buffer_open(lua_State *L) {
33 (void) L;
34 return 0;
35}
36
37/*-------------------------------------------------------------------------*\
38* Initializes C structure
39\*-------------------------------------------------------------------------*/
40void buffer_init(p_buffer buf, p_io io, p_timeout tm) {
41 buf->first = buf->last = 0;
42 buf->io = io;
43 buf->tm = tm;
44 buf->received = buf->sent = 0;
45 buf->birthday = timeout_gettime();
46}
47
48/*-------------------------------------------------------------------------*\
49* object:getstats() interface
50\*-------------------------------------------------------------------------*/
51int buffer_meth_getstats(lua_State *L, p_buffer buf) {
52 lua_pushnumber(L, (lua_Number) buf->received);
53 lua_pushnumber(L, (lua_Number) buf->sent);
54 lua_pushnumber(L, timeout_gettime() - buf->birthday);
55 return 3;
56}
57
58/*-------------------------------------------------------------------------*\
59* object:setstats() interface
60\*-------------------------------------------------------------------------*/
61int buffer_meth_setstats(lua_State *L, p_buffer buf) {
62 buf->received = (long) luaL_optnumber(L, 2, (lua_Number) buf->received);
63 buf->sent = (long) luaL_optnumber(L, 3, (lua_Number) buf->sent);
64 if (lua_isnumber(L, 4)) buf->birthday = timeout_gettime() - lua_tonumber(L, 4);
65 lua_pushnumber(L, 1);
66 return 1;
67}
68
69/*-------------------------------------------------------------------------*\
70* object:send() interface
71\*-------------------------------------------------------------------------*/
72int buffer_meth_send(lua_State *L, p_buffer buf) {
73 int top = lua_gettop(L);
74 int err = IO_DONE;
75 size_t size = 0, sent = 0;
76 const char *data = luaL_checklstring(L, 2, &size);
77 long start = (long) luaL_optnumber(L, 3, 1);
78 long end = (long) luaL_optnumber(L, 4, -1);
79 timeout_markstart(buf->tm);
80 if (start < 0) start = (long) (size+start+1);
81 if (end < 0) end = (long) (size+end+1);
82 if (start < 1) start = (long) 1;
83 if (end > (long) size) end = (long) size;
84 if (start <= end) err = sendraw(buf, data+start-1, end-start+1, &sent);
85 /* check if there was an error */
86 if (err != IO_DONE) {
87 lua_pushnil(L);
88 lua_pushstring(L, buf->io->error(buf->io->ctx, err));
89 lua_pushnumber(L, (lua_Number) (sent+start-1));
90 } else {
91 lua_pushnumber(L, (lua_Number) (sent+start-1));
92 lua_pushnil(L);
93 lua_pushnil(L);
94 }
95#ifdef LUASOCKET_DEBUG
96 /* push time elapsed during operation as the last return value */
97 lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
98#endif
99 return lua_gettop(L) - top;
100}
101
102/*-------------------------------------------------------------------------*\
103* object:receive() interface
104\*-------------------------------------------------------------------------*/
105int buffer_meth_receive(lua_State *L, p_buffer buf) {
106 int err = IO_DONE, top;
107 luaL_Buffer b;
108 size_t size;
109 const char *part = luaL_optlstring(L, 3, "", &size);
110 timeout_markstart(buf->tm);
111 /* make sure we don't confuse buffer stuff with arguments */
112 lua_settop(L, 3);
113 top = lua_gettop(L);
114 /* initialize buffer with optional extra prefix
115 * (useful for concatenating previous partial results) */
116 luaL_buffinit(L, &b);
117 luaL_addlstring(&b, part, size);
118 /* receive new patterns */
119 if (!lua_isnumber(L, 2)) {
120 const char *p= luaL_optstring(L, 2, "*l");
121 if (p[0] == '*' && p[1] == 'l') err = recvline(buf, &b);
122 else if (p[0] == '*' && p[1] == 'a') err = recvall(buf, &b);
123 else luaL_argcheck(L, 0, 2, "invalid receive pattern");
124 /* get a fixed number of bytes (minus what was already partially
125 * received) */
126 } else {
127 double n = lua_tonumber(L, 2);
128 size_t wanted = (size_t) n;
129 luaL_argcheck(L, n >= 0, 2, "invalid receive pattern");
130 if (size == 0 || wanted > size)
131 err = recvraw(buf, wanted-size, &b);
132 }
133 /* check if there was an error */
134 if (err != IO_DONE) {
135 /* we can't push anyting in the stack before pushing the
136 * contents of the buffer. this is the reason for the complication */
137 luaL_pushresult(&b);
138 lua_pushstring(L, buf->io->error(buf->io->ctx, err));
139 lua_pushvalue(L, -2);
140 lua_pushnil(L);
141 lua_replace(L, -4);
142 } else {
143 luaL_pushresult(&b);
144 lua_pushnil(L);
145 lua_pushnil(L);
146 }
147#ifdef LUASOCKET_DEBUG
148 /* push time elapsed during operation as the last return value */
149 lua_pushnumber(L, timeout_gettime() - timeout_getstart(buf->tm));
150#endif
151 return lua_gettop(L) - top;
152}
153
154/*-------------------------------------------------------------------------*\
155* Determines if there is any data in the read buffer
156\*-------------------------------------------------------------------------*/
157int buffer_isempty(p_buffer buf) {
158 return buf->first >= buf->last;
159}
160
161/*=========================================================================*\
162* Internal functions
163\*=========================================================================*/
164/*-------------------------------------------------------------------------*\
165* Sends a block of data (unbuffered)
166\*-------------------------------------------------------------------------*/
167#define STEPSIZE 8192
168static int sendraw(p_buffer buf, const char *data, size_t count, size_t *sent) {
169 p_io io = buf->io;
170 p_timeout tm = buf->tm;
171 size_t total = 0;
172 int err = IO_DONE;
173 while (total < count && err == IO_DONE) {
174 size_t done = 0;
175 size_t step = (count-total <= STEPSIZE)? count-total: STEPSIZE;
176 err = io->send(io->ctx, data+total, step, &done, tm);
177 total += done;
178 }
179 *sent = total;
180 buf->sent += total;
181 return err;
182}
183
184/*-------------------------------------------------------------------------*\
185* Reads a fixed number of bytes (buffered)
186\*-------------------------------------------------------------------------*/
187static int recvraw(p_buffer buf, size_t wanted, luaL_Buffer *b) {
188 int err = IO_DONE;
189 size_t total = 0;
190 while (err == IO_DONE) {
191 size_t count; const char *data;
192 err = buffer_get(buf, &data, &count);
193 count = MIN(count, wanted - total);
194 luaL_addlstring(b, data, count);
195 buffer_skip(buf, count);
196 total += count;
197 if (total >= wanted) break;
198 }
199 return err;
200}
201
202/*-------------------------------------------------------------------------*\
203* Reads everything until the connection is closed (buffered)
204\*-------------------------------------------------------------------------*/
205static int recvall(p_buffer buf, luaL_Buffer *b) {
206 int err = IO_DONE;
207 size_t total = 0;
208 while (err == IO_DONE) {
209 const char *data; size_t count;
210 err = buffer_get(buf, &data, &count);
211 total += count;
212 luaL_addlstring(b, data, count);
213 buffer_skip(buf, count);
214 }
215 if (err == IO_CLOSED) {
216 if (total > 0) return IO_DONE;
217 else return IO_CLOSED;
218 } else return err;
219}
220
221/*-------------------------------------------------------------------------*\
222* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
223* are not returned by the function and are discarded from the buffer
224\*-------------------------------------------------------------------------*/
225static int recvline(p_buffer buf, luaL_Buffer *b) {
226 int err = IO_DONE;
227 while (err == IO_DONE) {
228 size_t count, pos; const char *data;
229 err = buffer_get(buf, &data, &count);
230 pos = 0;
231 while (pos < count && data[pos] != '\n') {
232 /* we ignore all \r's */
233 if (data[pos] != '\r') luaL_addchar(b, data[pos]);
234 pos++;
235 }
236 if (pos < count) { /* found '\n' */
237 buffer_skip(buf, pos+1); /* skip '\n' too */
238 break; /* we are done */
239 } else /* reached the end of the buffer */
240 buffer_skip(buf, pos);
241 }
242 return err;
243}
244
245/*-------------------------------------------------------------------------*\
246* Skips a given number of bytes from read buffer. No data is read from the
247* transport layer
248\*-------------------------------------------------------------------------*/
249static void buffer_skip(p_buffer buf, size_t count) {
250 buf->received += count;
251 buf->first += count;
252 if (buffer_isempty(buf))
253 buf->first = buf->last = 0;
254}
255
256/*-------------------------------------------------------------------------*\
257* Return any data available in buffer, or get more data from transport layer
258* if buffer is empty
259\*-------------------------------------------------------------------------*/
260static int buffer_get(p_buffer buf, const char **data, size_t *count) {
261 int err = IO_DONE;
262 p_io io = buf->io;
263 p_timeout tm = buf->tm;
264 if (buffer_isempty(buf)) {
265 size_t got;
266 err = io->recv(io->ctx, buf->data, BUF_SIZE, &got, tm);
267 buf->first = 0;
268 buf->last = got;
269 }
270 *count = buf->last - buf->first;
271 *data = buf->data + buf->first;
272 return err;
273}
diff --git a/vendor/luasocket/src/buffer.h b/vendor/luasocket/src/buffer.h
new file mode 100644
index 00000000..a0901fcc
--- /dev/null
+++ b/vendor/luasocket/src/buffer.h
@@ -0,0 +1,52 @@
1#ifndef BUF_H
2#define BUF_H
3/*=========================================================================*\
4* Input/Output interface for Lua programs
5* LuaSocket toolkit
6*
7* Line patterns require buffering. Reading one character at a time involves
8* too many system calls and is very slow. This module implements the
9* LuaSocket interface for input/output on connected objects, as seen by
10* Lua programs.
11*
12* Input is buffered. Output is *not* buffered because there was no simple
13* way of making sure the buffered output data would ever be sent.
14*
15* The module is built on top of the I/O abstraction defined in io.h and the
16* timeout management is done with the timeout.h interface.
17\*=========================================================================*/
18#include "luasocket.h"
19#include "io.h"
20#include "timeout.h"
21
22/* buffer size in bytes */
23#define BUF_SIZE 8192
24
25/* buffer control structure */
26typedef struct t_buffer_ {
27 double birthday; /* throttle support info: creation time, */
28 size_t sent, received; /* bytes sent, and bytes received */
29 p_io io; /* IO driver used for this buffer */
30 p_timeout tm; /* timeout management for this buffer */
31 size_t first, last; /* index of first and last bytes of stored data */
32 char data[BUF_SIZE]; /* storage space for buffer data */
33} t_buffer;
34typedef t_buffer *p_buffer;
35
36#ifndef _WIN32
37#pragma GCC visibility push(hidden)
38#endif
39
40int buffer_open(lua_State *L);
41void buffer_init(p_buffer buf, p_io io, p_timeout tm);
42int buffer_meth_getstats(lua_State *L, p_buffer buf);
43int buffer_meth_setstats(lua_State *L, p_buffer buf);
44int buffer_meth_send(lua_State *L, p_buffer buf);
45int buffer_meth_receive(lua_State *L, p_buffer buf);
46int buffer_isempty(p_buffer buf);
47
48#ifndef _WIN32
49#pragma GCC visibility pop
50#endif
51
52#endif /* BUF_H */
diff --git a/vendor/luasocket/src/compat.c b/vendor/luasocket/src/compat.c
new file mode 100644
index 00000000..34ffdaf7
--- /dev/null
+++ b/vendor/luasocket/src/compat.c
@@ -0,0 +1,39 @@
1#include "luasocket.h"
2#include "compat.h"
3
4#if LUA_VERSION_NUM==501
5
6/*
7** Adapted from Lua 5.2
8*/
9void luasocket_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
10 luaL_checkstack(L, nup+1, "too many upvalues");
11 for (; l->name != NULL; l++) { /* fill the table with given functions */
12 int i;
13 lua_pushstring(L, l->name);
14 for (i = 0; i < nup; i++) /* copy upvalues to the top */
15 lua_pushvalue(L, -(nup+1));
16 lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
17 lua_settable(L, -(nup + 3));
18 }
19 lua_pop(L, nup); /* remove upvalues */
20}
21
22/*
23** Duplicated from Lua 5.2
24*/
25void *luasocket_testudata (lua_State *L, int ud, const char *tname) {
26 void *p = lua_touserdata(L, ud);
27 if (p != NULL) { /* value is a userdata? */
28 if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
29 luaL_getmetatable(L, tname); /* get correct metatable */
30 if (!lua_rawequal(L, -1, -2)) /* not the same? */
31 p = NULL; /* value is a userdata with wrong metatable */
32 lua_pop(L, 2); /* remove both metatables */
33 return p;
34 }
35 }
36 return NULL; /* value is not a userdata with a metatable */
37}
38
39#endif
diff --git a/vendor/luasocket/src/compat.h b/vendor/luasocket/src/compat.h
new file mode 100644
index 00000000..fa2d7d7c
--- /dev/null
+++ b/vendor/luasocket/src/compat.h
@@ -0,0 +1,22 @@
1#ifndef COMPAT_H
2#define COMPAT_H
3
4#if LUA_VERSION_NUM==501
5
6#ifndef _WIN32
7#pragma GCC visibility push(hidden)
8#endif
9
10void luasocket_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
11void *luasocket_testudata ( lua_State *L, int arg, const char *tname);
12
13#ifndef _WIN32
14#pragma GCC visibility pop
15#endif
16
17#define luaL_setfuncs luasocket_setfuncs
18#define luaL_testudata luasocket_testudata
19
20#endif
21
22#endif
diff --git a/vendor/luasocket/src/except.c b/vendor/luasocket/src/except.c
new file mode 100644
index 00000000..9c3317f2
--- /dev/null
+++ b/vendor/luasocket/src/except.c
@@ -0,0 +1,129 @@
1/*=========================================================================*\
2* Simple exception support
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6#include "except.h"
7#include <stdio.h>
8
9#if LUA_VERSION_NUM < 502
10#define lua_pcallk(L, na, nr, err, ctx, cont) \
11 (((void)ctx),((void)cont),lua_pcall(L, na, nr, err))
12#endif
13
14#if LUA_VERSION_NUM < 503
15typedef int lua_KContext;
16#endif
17
18/*=========================================================================*\
19* Internal function prototypes.
20\*=========================================================================*/
21static int global_protect(lua_State *L);
22static int global_newtry(lua_State *L);
23static int protected_(lua_State *L);
24static int finalize(lua_State *L);
25static int do_nothing(lua_State *L);
26
27/* except functions */
28static luaL_Reg func[] = {
29 {"newtry", global_newtry},
30 {"protect", global_protect},
31 {NULL, NULL}
32};
33
34/*-------------------------------------------------------------------------*\
35* Try factory
36\*-------------------------------------------------------------------------*/
37static void wrap(lua_State *L) {
38 lua_createtable(L, 1, 0);
39 lua_pushvalue(L, -2);
40 lua_rawseti(L, -2, 1);
41 lua_pushvalue(L, lua_upvalueindex(1));
42 lua_setmetatable(L, -2);
43}
44
45static int finalize(lua_State *L) {
46 if (!lua_toboolean(L, 1)) {
47 lua_pushvalue(L, lua_upvalueindex(2));
48 lua_call(L, 0, 0);
49 lua_settop(L, 2);
50 wrap(L);
51 lua_error(L);
52 return 0;
53 } else return lua_gettop(L);
54}
55
56static int do_nothing(lua_State *L) {
57 (void) L;
58 return 0;
59}
60
61static int global_newtry(lua_State *L) {
62 lua_settop(L, 1);
63 if (lua_isnil(L, 1)) lua_pushcfunction(L, do_nothing);
64 lua_pushvalue(L, lua_upvalueindex(1));
65 lua_insert(L, -2);
66 lua_pushcclosure(L, finalize, 2);
67 return 1;
68}
69
70/*-------------------------------------------------------------------------*\
71* Protect factory
72\*-------------------------------------------------------------------------*/
73static int unwrap(lua_State *L) {
74 if (lua_istable(L, -1) && lua_getmetatable(L, -1)) {
75 int r = lua_rawequal(L, -1, lua_upvalueindex(1));
76 lua_pop(L, 1);
77 if (r) {
78 lua_pushnil(L);
79 lua_rawgeti(L, -2, 1);
80 return 1;
81 }
82 }
83 return 0;
84}
85
86static int protected_finish(lua_State *L, int status, lua_KContext ctx) {
87 (void)ctx;
88 if (status != 0 && status != LUA_YIELD) {
89 if (unwrap(L)) return 2;
90 else return lua_error(L);
91 } else return lua_gettop(L);
92}
93
94#if LUA_VERSION_NUM == 502
95static int protected_cont(lua_State *L) {
96 int ctx = 0;
97 int status = lua_getctx(L, &ctx);
98 return protected_finish(L, status, ctx);
99}
100#else
101#define protected_cont protected_finish
102#endif
103
104static int protected_(lua_State *L) {
105 int status;
106 lua_pushvalue(L, lua_upvalueindex(2));
107 lua_insert(L, 1);
108 status = lua_pcallk(L, lua_gettop(L) - 1, LUA_MULTRET, 0, 0, protected_cont);
109 return protected_finish(L, status, 0);
110}
111
112static int global_protect(lua_State *L) {
113 lua_settop(L, 1);
114 lua_pushvalue(L, lua_upvalueindex(1));
115 lua_insert(L, 1);
116 lua_pushcclosure(L, protected_, 2);
117 return 1;
118}
119
120/*-------------------------------------------------------------------------*\
121* Init module
122\*-------------------------------------------------------------------------*/
123int except_open(lua_State *L) {
124 lua_newtable(L); /* metatable for wrapped exceptions */
125 lua_pushboolean(L, 0);
126 lua_setfield(L, -2, "__metatable");
127 luaL_setfuncs(L, func, 1);
128 return 0;
129}
diff --git a/vendor/luasocket/src/except.h b/vendor/luasocket/src/except.h
new file mode 100644
index 00000000..71c31fd4
--- /dev/null
+++ b/vendor/luasocket/src/except.h
@@ -0,0 +1,46 @@
1#ifndef EXCEPT_H
2#define EXCEPT_H
3/*=========================================================================*\
4* Exception control
5* LuaSocket toolkit (but completely independent from other modules)
6*
7* This provides support for simple exceptions in Lua. During the
8* development of the HTTP/FTP/SMTP support, it became aparent that
9* error checking was taking a substantial amount of the coding. These
10* function greatly simplify the task of checking errors.
11*
12* The main idea is that functions should return nil as their first return
13* values when they find an error, and return an error message (or value)
14* following nil. In case of success, as long as the first value is not nil,
15* the other values don't matter.
16*
17* The idea is to nest function calls with the "try" function. This function
18* checks the first value, and, if it's falsy, wraps the second value in a
19* table with metatable and calls "error" on it. Otherwise, it returns all
20* values it received. Basically, it works like the Lua "assert" function,
21* but it creates errors targeted specifically at "protect".
22*
23* The "newtry" function is a factory for "try" functions that call a
24* finalizer in protected mode before calling "error".
25*
26* The "protect" function returns a new function that behaves exactly like
27* the function it receives, but the new function catches exceptions thrown
28* by "try" functions and returns nil followed by the error message instead.
29*
30* With these three functions, it's easy to write functions that throw
31* exceptions on error, but that don't interrupt the user script.
32\*=========================================================================*/
33
34#include "luasocket.h"
35
36#ifndef _WIN32
37#pragma GCC visibility push(hidden)
38#endif
39
40int except_open(lua_State *L);
41
42#ifndef _WIN32
43#pragma GCC visibility pop
44#endif
45
46#endif
diff --git a/vendor/luasocket/src/ftp.lua b/vendor/luasocket/src/ftp.lua
new file mode 100644
index 00000000..0ebc5086
--- /dev/null
+++ b/vendor/luasocket/src/ftp.lua
@@ -0,0 +1,329 @@
1-----------------------------------------------------------------------------
2-- FTP support for the Lua language
3-- LuaSocket toolkit.
4-- Author: Diego Nehab
5-----------------------------------------------------------------------------
6
7-----------------------------------------------------------------------------
8-- Declare module and import dependencies
9-----------------------------------------------------------------------------
10local base = _G
11local table = require("table")
12local string = require("string")
13local math = require("math")
14local socket = require("socket")
15local url = require("socket.url")
16local tp = require("socket.tp")
17local ltn12 = require("ltn12")
18socket.ftp = {}
19local _M = socket.ftp
20-----------------------------------------------------------------------------
21-- Program constants
22-----------------------------------------------------------------------------
23-- timeout in seconds before the program gives up on a connection
24_M.TIMEOUT = 60
25-- default port for ftp service
26local PORT = 21
27-- this is the default anonymous password. used when no password is
28-- provided in url. should be changed to your e-mail.
29_M.USER = "ftp"
30_M.PASSWORD = "anonymous@anonymous.org"
31
32-----------------------------------------------------------------------------
33-- Low level FTP API
34-----------------------------------------------------------------------------
35local metat = { __index = {} }
36
37function _M.open(server, port, create)
38 local tp = socket.try(tp.connect(server, port or PORT, _M.TIMEOUT, create))
39 local f = base.setmetatable({ tp = tp }, metat)
40 -- make sure everything gets closed in an exception
41 f.try = socket.newtry(function() f:close() end)
42 return f
43end
44
45function metat.__index:portconnect()
46 self.try(self.server:settimeout(_M.TIMEOUT))
47 self.data = self.try(self.server:accept())
48 self.try(self.data:settimeout(_M.TIMEOUT))
49end
50
51function metat.__index:pasvconnect()
52 self.data = self.try(socket.tcp())
53 self.try(self.data:settimeout(_M.TIMEOUT))
54 self.try(self.data:connect(self.pasvt.address, self.pasvt.port))
55end
56
57function metat.__index:login(user, password)
58 self.try(self.tp:command("user", user or _M.USER))
59 local code, _ = self.try(self.tp:check{"2..", 331})
60 if code == 331 then
61 self.try(self.tp:command("pass", password or _M.PASSWORD))
62 self.try(self.tp:check("2.."))
63 end
64 return 1
65end
66
67function metat.__index:pasv()
68 self.try(self.tp:command("pasv"))
69 local _, reply = self.try(self.tp:check("2.."))
70 local pattern = "(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)"
71 local a, b, c, d, p1, p2 = socket.skip(2, string.find(reply, pattern))
72 self.try(a and b and c and d and p1 and p2, reply)
73 self.pasvt = {
74 address = string.format("%d.%d.%d.%d", a, b, c, d),
75 port = p1*256 + p2
76 }
77 if self.server then
78 self.server:close()
79 self.server = nil
80 end
81 return self.pasvt.address, self.pasvt.port
82end
83
84function metat.__index:epsv()
85 self.try(self.tp:command("epsv"))
86 local _, reply = self.try(self.tp:check("229"))
87 local pattern = "%((.)(.-)%1(.-)%1(.-)%1%)"
88 local _, _, _, port = string.match(reply, pattern)
89 self.try(port, "invalid epsv response")
90 self.pasvt = {
91 address = self.tp:getpeername(),
92 port = port
93 }
94 if self.server then
95 self.server:close()
96 self.server = nil
97 end
98 return self.pasvt.address, self.pasvt.port
99end
100
101
102function metat.__index:port(address, port)
103 self.pasvt = nil
104 if not address then
105 address = self.try(self.tp:getsockname())
106 self.server = self.try(socket.bind(address, 0))
107 address, port = self.try(self.server:getsockname())
108 self.try(self.server:settimeout(_M.TIMEOUT))
109 end
110 local pl = math.mod(port, 256)
111 local ph = (port - pl)/256
112 local arg = string.gsub(string.format("%s,%d,%d", address, ph, pl), "%.", ",")
113 self.try(self.tp:command("port", arg))
114 self.try(self.tp:check("2.."))
115 return 1
116end
117
118function metat.__index:eprt(family, address, port)
119 self.pasvt = nil
120 if not address then
121 address = self.try(self.tp:getsockname())
122 self.server = self.try(socket.bind(address, 0))
123 address, port = self.try(self.server:getsockname())
124 self.try(self.server:settimeout(_M.TIMEOUT))
125 end
126 local arg = string.format("|%s|%s|%d|", family, address, port)
127 self.try(self.tp:command("eprt", arg))
128 self.try(self.tp:check("2.."))
129 return 1
130end
131
132
133function metat.__index:send(sendt)
134 self.try(self.pasvt or self.server, "need port or pasv first")
135 -- if there is a pasvt table, we already sent a PASV command
136 -- we just get the data connection into self.data
137 if self.pasvt then self:pasvconnect() end
138 -- get the transfer argument and command
139 local argument = sendt.argument or
140 url.unescape(string.gsub(sendt.path or "", "^[/\\]", ""))
141 if argument == "" then argument = nil end
142 local command = sendt.command or "stor"
143 -- send the transfer command and check the reply
144 self.try(self.tp:command(command, argument))
145 local code, _ = self.try(self.tp:check{"2..", "1.."})
146 -- if there is not a pasvt table, then there is a server
147 -- and we already sent a PORT command
148 if not self.pasvt then self:portconnect() end
149 -- get the sink, source and step for the transfer
150 local step = sendt.step or ltn12.pump.step
151 local readt = { self.tp }
152 local checkstep = function(src, snk)
153 -- check status in control connection while downloading
154 local readyt = socket.select(readt, nil, 0)
155 if readyt[tp] then code = self.try(self.tp:check("2..")) end
156 return step(src, snk)
157 end
158 local sink = socket.sink("close-when-done", self.data)
159 -- transfer all data and check error
160 self.try(ltn12.pump.all(sendt.source, sink, checkstep))
161 if string.find(code, "1..") then self.try(self.tp:check("2..")) end
162 -- done with data connection
163 self.data:close()
164 -- find out how many bytes were sent
165 local sent = socket.skip(1, self.data:getstats())
166 self.data = nil
167 return sent
168end
169
170function metat.__index:receive(recvt)
171 self.try(self.pasvt or self.server, "need port or pasv first")
172 if self.pasvt then self:pasvconnect() end
173 local argument = recvt.argument or
174 url.unescape(string.gsub(recvt.path or "", "^[/\\]", ""))
175 if argument == "" then argument = nil end
176 local command = recvt.command or "retr"
177 self.try(self.tp:command(command, argument))
178 local code,reply = self.try(self.tp:check{"1..", "2.."})
179 if (code >= 200) and (code <= 299) then
180 recvt.sink(reply)
181 return 1
182 end
183 if not self.pasvt then self:portconnect() end
184 local source = socket.source("until-closed", self.data)
185 local step = recvt.step or ltn12.pump.step
186 self.try(ltn12.pump.all(source, recvt.sink, step))
187 if string.find(code, "1..") then self.try(self.tp:check("2..")) end
188 self.data:close()
189 self.data = nil
190 return 1
191end
192
193function metat.__index:cwd(dir)
194 self.try(self.tp:command("cwd", dir))
195 self.try(self.tp:check(250))
196 return 1
197end
198
199function metat.__index:type(type)
200 self.try(self.tp:command("type", type))
201 self.try(self.tp:check(200))
202 return 1
203end
204
205function metat.__index:greet()
206 local code = self.try(self.tp:check{"1..", "2.."})
207 if string.find(code, "1..") then self.try(self.tp:check("2..")) end
208 return 1
209end
210
211function metat.__index:quit()
212 self.try(self.tp:command("quit"))
213 self.try(self.tp:check("2.."))
214 return 1
215end
216
217function metat.__index:close()
218 if self.data then self.data:close() end
219 if self.server then self.server:close() end
220 return self.tp:close()
221end
222
223-----------------------------------------------------------------------------
224-- High level FTP API
225-----------------------------------------------------------------------------
226local function override(t)
227 if t.url then
228 local u = url.parse(t.url)
229 for i,v in base.pairs(t) do
230 u[i] = v
231 end
232 return u
233 else return t end
234end
235
236local function tput(putt)
237 putt = override(putt)
238 socket.try(putt.host, "missing hostname")
239 local f = _M.open(putt.host, putt.port, putt.create)
240 f:greet()
241 f:login(putt.user, putt.password)
242 if putt.type then f:type(putt.type) end
243 f:epsv()
244 local sent = f:send(putt)
245 f:quit()
246 f:close()
247 return sent
248end
249
250local default = {
251 path = "/",
252 scheme = "ftp"
253}
254
255local function genericform(u)
256 local t = socket.try(url.parse(u, default))
257 socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
258 socket.try(t.host, "missing hostname")
259 local pat = "^type=(.)$"
260 if t.params then
261 t.type = socket.skip(2, string.find(t.params, pat))
262 socket.try(t.type == "a" or t.type == "i",
263 "invalid type '" .. t.type .. "'")
264 end
265 return t
266end
267
268_M.genericform = genericform
269
270local function sput(u, body)
271 local putt = genericform(u)
272 putt.source = ltn12.source.string(body)
273 return tput(putt)
274end
275
276_M.put = socket.protect(function(putt, body)
277 if base.type(putt) == "string" then return sput(putt, body)
278 else return tput(putt) end
279end)
280
281local function tget(gett)
282 gett = override(gett)
283 socket.try(gett.host, "missing hostname")
284 local f = _M.open(gett.host, gett.port, gett.create)
285 f:greet()
286 f:login(gett.user, gett.password)
287 if gett.type then f:type(gett.type) end
288 f:epsv()
289 f:receive(gett)
290 f:quit()
291 return f:close()
292end
293
294local function sget(u)
295 local gett = genericform(u)
296 local t = {}
297 gett.sink = ltn12.sink.table(t)
298 tget(gett)
299 return table.concat(t)
300end
301
302_M.command = socket.protect(function(cmdt)
303 cmdt = override(cmdt)
304 socket.try(cmdt.host, "missing hostname")
305 socket.try(cmdt.command, "missing command")
306 local f = _M.open(cmdt.host, cmdt.port, cmdt.create)
307 f:greet()
308 f:login(cmdt.user, cmdt.password)
309 if type(cmdt.command) == "table" then
310 local argument = cmdt.argument or {}
311 local check = cmdt.check or {}
312 for i,cmd in ipairs(cmdt.command) do
313 f.try(f.tp:command(cmd, argument[i]))
314 if check[i] then f.try(f.tp:check(check[i])) end
315 end
316 else
317 f.try(f.tp:command(cmdt.command, cmdt.argument))
318 if cmdt.check then f.try(f.tp:check(cmdt.check)) end
319 end
320 f:quit()
321 return f:close()
322end)
323
324_M.get = socket.protect(function(gett)
325 if base.type(gett) == "string" then return sget(gett)
326 else return tget(gett) end
327end)
328
329return _M
diff --git a/vendor/luasocket/src/headers.lua b/vendor/luasocket/src/headers.lua
new file mode 100644
index 00000000..1eb8223b
--- /dev/null
+++ b/vendor/luasocket/src/headers.lua
@@ -0,0 +1,104 @@
1-----------------------------------------------------------------------------
2-- Canonic header field capitalization
3-- LuaSocket toolkit.
4-- Author: Diego Nehab
5-----------------------------------------------------------------------------
6local socket = require("socket")
7socket.headers = {}
8local _M = socket.headers
9
10_M.canonic = {
11 ["accept"] = "Accept",
12 ["accept-charset"] = "Accept-Charset",
13 ["accept-encoding"] = "Accept-Encoding",
14 ["accept-language"] = "Accept-Language",
15 ["accept-ranges"] = "Accept-Ranges",
16 ["action"] = "Action",
17 ["alternate-recipient"] = "Alternate-Recipient",
18 ["age"] = "Age",
19 ["allow"] = "Allow",
20 ["arrival-date"] = "Arrival-Date",
21 ["authorization"] = "Authorization",
22 ["bcc"] = "Bcc",
23 ["cache-control"] = "Cache-Control",
24 ["cc"] = "Cc",
25 ["comments"] = "Comments",
26 ["connection"] = "Connection",
27 ["content-description"] = "Content-Description",
28 ["content-disposition"] = "Content-Disposition",
29 ["content-encoding"] = "Content-Encoding",
30 ["content-id"] = "Content-ID",
31 ["content-language"] = "Content-Language",
32 ["content-length"] = "Content-Length",
33 ["content-location"] = "Content-Location",
34 ["content-md5"] = "Content-MD5",
35 ["content-range"] = "Content-Range",
36 ["content-transfer-encoding"] = "Content-Transfer-Encoding",
37 ["content-type"] = "Content-Type",
38 ["cookie"] = "Cookie",
39 ["date"] = "Date",
40 ["diagnostic-code"] = "Diagnostic-Code",
41 ["dsn-gateway"] = "DSN-Gateway",
42 ["etag"] = "ETag",
43 ["expect"] = "Expect",
44 ["expires"] = "Expires",
45 ["final-log-id"] = "Final-Log-ID",
46 ["final-recipient"] = "Final-Recipient",
47 ["from"] = "From",
48 ["host"] = "Host",
49 ["if-match"] = "If-Match",
50 ["if-modified-since"] = "If-Modified-Since",
51 ["if-none-match"] = "If-None-Match",
52 ["if-range"] = "If-Range",
53 ["if-unmodified-since"] = "If-Unmodified-Since",
54 ["in-reply-to"] = "In-Reply-To",
55 ["keywords"] = "Keywords",
56 ["last-attempt-date"] = "Last-Attempt-Date",
57 ["last-modified"] = "Last-Modified",
58 ["location"] = "Location",
59 ["max-forwards"] = "Max-Forwards",
60 ["message-id"] = "Message-ID",
61 ["mime-version"] = "MIME-Version",
62 ["original-envelope-id"] = "Original-Envelope-ID",
63 ["original-recipient"] = "Original-Recipient",
64 ["pragma"] = "Pragma",
65 ["proxy-authenticate"] = "Proxy-Authenticate",
66 ["proxy-authorization"] = "Proxy-Authorization",
67 ["range"] = "Range",
68 ["received"] = "Received",
69 ["received-from-mta"] = "Received-From-MTA",
70 ["references"] = "References",
71 ["referer"] = "Referer",
72 ["remote-mta"] = "Remote-MTA",
73 ["reply-to"] = "Reply-To",
74 ["reporting-mta"] = "Reporting-MTA",
75 ["resent-bcc"] = "Resent-Bcc",
76 ["resent-cc"] = "Resent-Cc",
77 ["resent-date"] = "Resent-Date",
78 ["resent-from"] = "Resent-From",
79 ["resent-message-id"] = "Resent-Message-ID",
80 ["resent-reply-to"] = "Resent-Reply-To",
81 ["resent-sender"] = "Resent-Sender",
82 ["resent-to"] = "Resent-To",
83 ["retry-after"] = "Retry-After",
84 ["return-path"] = "Return-Path",
85 ["sender"] = "Sender",
86 ["server"] = "Server",
87 ["smtp-remote-recipient"] = "SMTP-Remote-Recipient",
88 ["status"] = "Status",
89 ["subject"] = "Subject",
90 ["te"] = "TE",
91 ["to"] = "To",
92 ["trailer"] = "Trailer",
93 ["transfer-encoding"] = "Transfer-Encoding",
94 ["upgrade"] = "Upgrade",
95 ["user-agent"] = "User-Agent",
96 ["vary"] = "Vary",
97 ["via"] = "Via",
98 ["warning"] = "Warning",
99 ["will-retry-until"] = "Will-Retry-Until",
100 ["www-authenticate"] = "WWW-Authenticate",
101 ["x-mailer"] = "X-Mailer",
102}
103
104return _M \ No newline at end of file
diff --git a/vendor/luasocket/src/http.lua b/vendor/luasocket/src/http.lua
new file mode 100644
index 00000000..1330355f
--- /dev/null
+++ b/vendor/luasocket/src/http.lua
@@ -0,0 +1,424 @@
1-----------------------------------------------------------------------------
2-- HTTP/1.1 client support for the Lua language.
3-- LuaSocket toolkit.
4-- Author: Diego Nehab
5-----------------------------------------------------------------------------
6
7-----------------------------------------------------------------------------
8-- Declare module and import dependencies
9-------------------------------------------------------------------------------
10local socket = require("socket")
11local url = require("socket.url")
12local ltn12 = require("ltn12")
13local mime = require("mime")
14local string = require("string")
15local headers = require("socket.headers")
16local base = _G
17local table = require("table")
18socket.http = {}
19local _M = socket.http
20
21-----------------------------------------------------------------------------
22-- Program constants
23-----------------------------------------------------------------------------
24-- connection timeout in seconds
25_M.TIMEOUT = 60
26-- user agent field sent in request
27_M.USERAGENT = socket._VERSION
28
29-- supported schemes and their particulars
30local SCHEMES = {
31 http = {
32 port = 80
33 , create = function(t)
34 return socket.tcp end }
35 , https = {
36 port = 443
37 , create = function(t)
38 local https = assert(
39 require("ssl.https"), 'LuaSocket: LuaSec not found')
40 local tcp = assert(
41 https.tcp, 'LuaSocket: Function tcp() not available from LuaSec')
42 return tcp(t) end }}
43
44-----------------------------------------------------------------------------
45-- Reads MIME headers from a connection, unfolding where needed
46-----------------------------------------------------------------------------
47local function receiveheaders(sock, headers)
48 local line, name, value, err
49 headers = headers or {}
50 -- get first line
51 line, err = sock:receive()
52 if err then return nil, err end
53 -- headers go until a blank line is found
54 while line ~= "" do
55 -- get field-name and value
56 name, value = socket.skip(2, string.find(line, "^(.-):%s*(.*)"))
57 if not (name and value) then return nil, "malformed reponse headers" end
58 name = string.lower(name)
59 -- get next line (value might be folded)
60 line, err = sock:receive()
61 if err then return nil, err end
62 -- unfold any folded values
63 while string.find(line, "^%s") do
64 value = value .. line
65 line = sock:receive()
66 if err then return nil, err end
67 end
68 -- save pair in table
69 if headers[name] then headers[name] = headers[name] .. ", " .. value
70 else headers[name] = value end
71 end
72 return headers
73end
74
75-----------------------------------------------------------------------------
76-- Extra sources and sinks
77-----------------------------------------------------------------------------
78socket.sourcet["http-chunked"] = function(sock, headers)
79 return base.setmetatable({
80 getfd = function() return sock:getfd() end,
81 dirty = function() return sock:dirty() end
82 }, {
83 __call = function()
84 -- get chunk size, skip extention
85 local line, err = sock:receive()
86 if err then return nil, err end
87 local size = base.tonumber(string.gsub(line, ";.*", ""), 16)
88 if not size then return nil, "invalid chunk size" end
89 -- was it the last chunk?
90 if size > 0 then
91 -- if not, get chunk and skip terminating CRLF
92 local chunk, err, _ = sock:receive(size)
93 if chunk then sock:receive() end
94 return chunk, err
95 else
96 -- if it was, read trailers into headers table
97 headers, err = receiveheaders(sock, headers)
98 if not headers then return nil, err end
99 end
100 end
101 })
102end
103
104socket.sinkt["http-chunked"] = function(sock)
105 return base.setmetatable({
106 getfd = function() return sock:getfd() end,
107 dirty = function() return sock:dirty() end
108 }, {
109 __call = function(self, chunk, err)
110 if not chunk then return sock:send("0\r\n\r\n") end
111 local size = string.format("%X\r\n", string.len(chunk))
112 return sock:send(size .. chunk .. "\r\n")
113 end
114 })
115end
116
117-----------------------------------------------------------------------------
118-- Low level HTTP API
119-----------------------------------------------------------------------------
120local metat = { __index = {} }
121
122function _M.open(host, port, create)
123 -- create socket with user connect function, or with default
124 local c = socket.try(create())
125 local h = base.setmetatable({ c = c }, metat)
126 -- create finalized try
127 h.try = socket.newtry(function() h:close() end)
128 -- set timeout before connecting
129 h.try(c:settimeout(_M.TIMEOUT))
130 h.try(c:connect(host, port))
131 -- here everything worked
132 return h
133end
134
135function metat.__index:sendrequestline(method, uri)
136 local reqline = string.format("%s %s HTTP/1.1\r\n", method or "GET", uri)
137 return self.try(self.c:send(reqline))
138end
139
140function metat.__index:sendheaders(tosend)
141 local canonic = headers.canonic
142 local h = "\r\n"
143 for f, v in base.pairs(tosend) do
144 h = (canonic[f] or f) .. ": " .. v .. "\r\n" .. h
145 end
146 self.try(self.c:send(h))
147 return 1
148end
149
150function metat.__index:sendbody(headers, source, step)
151 source = source or ltn12.source.empty()
152 step = step or ltn12.pump.step
153 -- if we don't know the size in advance, send chunked and hope for the best
154 local mode = "http-chunked"
155 if headers["content-length"] then mode = "keep-open" end
156 return self.try(ltn12.pump.all(source, socket.sink(mode, self.c), step))
157end
158
159function metat.__index:receivestatusline()
160 local status,ec = self.try(self.c:receive(5))
161 -- identify HTTP/0.9 responses, which do not contain a status line
162 -- this is just a heuristic, but is what the RFC recommends
163 if status ~= "HTTP/" then
164 if ec == "timeout" then
165 return 408
166 end
167 return nil, status
168 end
169 -- otherwise proceed reading a status line
170 status = self.try(self.c:receive("*l", status))
171 local code = socket.skip(2, string.find(status, "HTTP/%d*%.%d* (%d%d%d)"))
172 return self.try(base.tonumber(code), status)
173end
174
175function metat.__index:receiveheaders()
176 return self.try(receiveheaders(self.c))
177end
178
179function metat.__index:receivebody(headers, sink, step)
180 sink = sink or ltn12.sink.null()
181 step = step or ltn12.pump.step
182 local length = base.tonumber(headers["content-length"])
183 local t = headers["transfer-encoding"] -- shortcut
184 local mode = "default" -- connection close
185 if t and t ~= "identity" then mode = "http-chunked"
186 elseif base.tonumber(headers["content-length"]) then mode = "by-length" end
187 return self.try(ltn12.pump.all(socket.source(mode, self.c, length),
188 sink, step))
189end
190
191function metat.__index:receive09body(status, sink, step)
192 local source = ltn12.source.rewind(socket.source("until-closed", self.c))
193 source(status)
194 return self.try(ltn12.pump.all(source, sink, step))
195end
196
197function metat.__index:close()
198 return self.c:close()
199end
200
201-----------------------------------------------------------------------------
202-- High level HTTP API
203-----------------------------------------------------------------------------
204local function adjusturi(reqt)
205 local u = reqt
206 -- if there is a proxy, we need the full url. otherwise, just a part.
207 if not reqt.proxy and not _M.PROXY then
208 u = {
209 path = socket.try(reqt.path, "invalid path 'nil'"),
210 params = reqt.params,
211 query = reqt.query,
212 fragment = reqt.fragment
213 }
214 end
215 return url.build(u)
216end
217
218local function adjustproxy(reqt)
219 local proxy = reqt.proxy or _M.PROXY
220 if proxy then
221 proxy = url.parse(proxy)
222 return proxy.host, proxy.port or 3128
223 else
224 return reqt.host, reqt.port
225 end
226end
227
228local function adjustheaders(reqt)
229 -- default headers
230 local host = reqt.host
231 local port = tostring(reqt.port)
232 if port ~= tostring(SCHEMES[reqt.scheme].port) then
233 host = host .. ':' .. port end
234 local lower = {
235 ["user-agent"] = _M.USERAGENT,
236 ["host"] = host,
237 ["connection"] = "close, TE",
238 ["te"] = "trailers"
239 }
240 -- if we have authentication information, pass it along
241 if reqt.user and reqt.password then
242 lower["authorization"] =
243 "Basic " .. (mime.b64(reqt.user .. ":" ..
244 url.unescape(reqt.password)))
245 end
246 -- if we have proxy authentication information, pass it along
247 local proxy = reqt.proxy or _M.PROXY
248 if proxy then
249 proxy = url.parse(proxy)
250 if proxy.user and proxy.password then
251 lower["proxy-authorization"] =
252 "Basic " .. (mime.b64(proxy.user .. ":" .. proxy.password))
253 end
254 end
255 -- override with user headers
256 for i,v in base.pairs(reqt.headers or lower) do
257 lower[string.lower(i)] = v
258 end
259 return lower
260end
261
262-- default url parts
263local default = {
264 path ="/"
265 , scheme = "http"
266}
267
268local function adjustrequest(reqt)
269 -- parse url if provided
270 local nreqt = reqt.url and url.parse(reqt.url, default) or {}
271 -- explicit components override url
272 for i,v in base.pairs(reqt) do nreqt[i] = v end
273 -- default to scheme particulars
274 local schemedefs, host, port, method
275 = SCHEMES[nreqt.scheme], nreqt.host, nreqt.port, nreqt.method
276 if not nreqt.create then nreqt.create = schemedefs.create(nreqt) end
277 if not (port and port ~= '') then nreqt.port = schemedefs.port end
278 if not (method and method ~= '') then nreqt.method = 'GET' end
279 if not (host and host ~= "") then
280 socket.try(nil, "invalid host '" .. base.tostring(nreqt.host) .. "'")
281 end
282 -- compute uri if user hasn't overriden
283 nreqt.uri = reqt.uri or adjusturi(nreqt)
284 -- adjust headers in request
285 nreqt.headers = adjustheaders(nreqt)
286 if nreqt.source
287 and not nreqt.headers["content-length"]
288 and not nreqt.headers["transfer-encoding"]
289 then
290 nreqt.headers["transfer-encoding"] = "chunked"
291 end
292
293 -- ajust host and port if there is a proxy
294 nreqt.host, nreqt.port = adjustproxy(nreqt)
295 return nreqt
296end
297
298local function shouldredirect(reqt, code, headers)
299 local location = headers.location
300 if not location then return false end
301 location = string.gsub(location, "%s", "")
302 if location == "" then return false end
303 local scheme = url.parse(location).scheme
304 if scheme and (not SCHEMES[scheme]) then return false end
305 -- avoid https downgrades
306 if ('https' == reqt.scheme) and ('https' ~= scheme) then return false end
307 return (reqt.redirect ~= false) and
308 (code == 301 or code == 302 or code == 303 or code == 307) and
309 (not reqt.method or reqt.method == "GET" or reqt.method == "HEAD")
310 and ((false == reqt.maxredirects)
311 or ((reqt.nredirects or 0)
312 < (reqt.maxredirects or 5)))
313end
314
315local function shouldreceivebody(reqt, code)
316 if reqt.method == "HEAD" then return nil end
317 if code == 204 or code == 304 then return nil end
318 if code >= 100 and code < 200 then return nil end
319 return 1
320end
321
322-- forward declarations
323local trequest, tredirect
324
325--[[local]] function tredirect(reqt, location)
326 -- the RFC says the redirect URL has to be absolute, but some
327 -- servers do not respect that
328 local newurl = url.absolute(reqt.url, location)
329 -- if switching schemes, reset port and create function
330 if url.parse(newurl).scheme ~= reqt.scheme then
331 reqt.port = nil
332 reqt.create = nil end
333 -- make new request
334 local result, code, headers, status = trequest {
335 url = newurl,
336 source = reqt.source,
337 sink = reqt.sink,
338 headers = reqt.headers,
339 proxy = reqt.proxy,
340 maxredirects = reqt.maxredirects,
341 nredirects = (reqt.nredirects or 0) + 1,
342 create = reqt.create
343 }
344 -- pass location header back as a hint we redirected
345 headers = headers or {}
346 headers.location = headers.location or location
347 return result, code, headers, status
348end
349
350--[[local]] function trequest(reqt)
351 -- we loop until we get what we want, or
352 -- until we are sure there is no way to get it
353 local nreqt = adjustrequest(reqt)
354 local h = _M.open(nreqt.host, nreqt.port, nreqt.create)
355 -- send request line and headers
356 h:sendrequestline(nreqt.method, nreqt.uri)
357 h:sendheaders(nreqt.headers)
358 -- if there is a body, send it
359 if nreqt.source then
360 h:sendbody(nreqt.headers, nreqt.source, nreqt.step)
361 end
362 local code, status = h:receivestatusline()
363 -- if it is an HTTP/0.9 server, simply get the body and we are done
364 if not code then
365 h:receive09body(status, nreqt.sink, nreqt.step)
366 return 1, 200
367 elseif code == 408 then
368 return 1, code
369 end
370 local headers
371 -- ignore any 100-continue messages
372 while code == 100 do
373 h:receiveheaders()
374 code, status = h:receivestatusline()
375 end
376 headers = h:receiveheaders()
377 -- at this point we should have a honest reply from the server
378 -- we can't redirect if we already used the source, so we report the error
379 if shouldredirect(nreqt, code, headers) and not nreqt.source then
380 h:close()
381 return tredirect(reqt, headers.location)
382 end
383 -- here we are finally done
384 if shouldreceivebody(nreqt, code) then
385 h:receivebody(headers, nreqt.sink, nreqt.step)
386 end
387 h:close()
388 return 1, code, headers, status
389end
390
391-- turns an url and a body into a generic request
392local function genericform(u, b)
393 local t = {}
394 local reqt = {
395 url = u,
396 sink = ltn12.sink.table(t),
397 target = t
398 }
399 if b then
400 reqt.source = ltn12.source.string(b)
401 reqt.headers = {
402 ["content-length"] = string.len(b),
403 ["content-type"] = "application/x-www-form-urlencoded"
404 }
405 reqt.method = "POST"
406 end
407 return reqt
408end
409
410_M.genericform = genericform
411
412local function srequest(u, b)
413 local reqt = genericform(u, b)
414 local _, code, headers, status = trequest(reqt)
415 return table.concat(reqt.target), code, headers, status
416end
417
418_M.request = socket.protect(function(reqt, body)
419 if base.type(reqt) == "string" then return srequest(reqt, body)
420 else return trequest(reqt) end
421end)
422
423_M.schemes = SCHEMES
424return _M
diff --git a/vendor/luasocket/src/inet.c b/vendor/luasocket/src/inet.c
new file mode 100755
index 00000000..138c9abe
--- /dev/null
+++ b/vendor/luasocket/src/inet.c
@@ -0,0 +1,537 @@
1/*=========================================================================*\
2* Internet domain functions
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6#include "inet.h"
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12/*=========================================================================*\
13* Internal function prototypes.
14\*=========================================================================*/
15static int inet_global_toip(lua_State *L);
16static int inet_global_getaddrinfo(lua_State *L);
17static int inet_global_tohostname(lua_State *L);
18static int inet_global_getnameinfo(lua_State *L);
19static void inet_pushresolved(lua_State *L, struct hostent *hp);
20static int inet_global_gethostname(lua_State *L);
21
22/* DNS functions */
23static luaL_Reg func[] = {
24 { "toip", inet_global_toip},
25 { "getaddrinfo", inet_global_getaddrinfo},
26 { "tohostname", inet_global_tohostname},
27 { "getnameinfo", inet_global_getnameinfo},
28 { "gethostname", inet_global_gethostname},
29 { NULL, NULL}
30};
31
32/*-------------------------------------------------------------------------*\
33* Initializes module
34\*-------------------------------------------------------------------------*/
35int inet_open(lua_State *L)
36{
37 lua_pushstring(L, "dns");
38 lua_newtable(L);
39 luaL_setfuncs(L, func, 0);
40 lua_settable(L, -3);
41 return 0;
42}
43
44/*=========================================================================*\
45* Global Lua functions
46\*=========================================================================*/
47/*-------------------------------------------------------------------------*\
48* Returns all information provided by the resolver given a host name
49* or ip address
50\*-------------------------------------------------------------------------*/
51static int inet_gethost(const char *address, struct hostent **hp) {
52 struct in_addr addr;
53 if (inet_aton(address, &addr))
54 return socket_gethostbyaddr((char *) &addr, sizeof(addr), hp);
55 else
56 return socket_gethostbyname(address, hp);
57}
58
59/*-------------------------------------------------------------------------*\
60* Returns all information provided by the resolver given a host name
61* or ip address
62\*-------------------------------------------------------------------------*/
63static int inet_global_tohostname(lua_State *L) {
64 const char *address = luaL_checkstring(L, 1);
65 struct hostent *hp = NULL;
66 int err = inet_gethost(address, &hp);
67 if (err != IO_DONE) {
68 lua_pushnil(L);
69 lua_pushstring(L, socket_hoststrerror(err));
70 return 2;
71 }
72 lua_pushstring(L, hp->h_name);
73 inet_pushresolved(L, hp);
74 return 2;
75}
76
77static int inet_global_getnameinfo(lua_State *L) {
78 char hbuf[NI_MAXHOST];
79 char sbuf[NI_MAXSERV];
80 int i, ret;
81 struct addrinfo hints;
82 struct addrinfo *resolved, *iter;
83 const char *host = luaL_optstring(L, 1, NULL);
84 const char *serv = luaL_optstring(L, 2, NULL);
85
86 if (!(host || serv))
87 luaL_error(L, "host and serv cannot be both nil");
88
89 memset(&hints, 0, sizeof(hints));
90 hints.ai_socktype = SOCK_STREAM;
91 hints.ai_family = AF_UNSPEC;
92
93 ret = getaddrinfo(host, serv, &hints, &resolved);
94 if (ret != 0) {
95 lua_pushnil(L);
96 lua_pushstring(L, socket_gaistrerror(ret));
97 return 2;
98 }
99
100 lua_newtable(L);
101 for (i = 1, iter = resolved; iter; i++, iter = iter->ai_next) {
102 getnameinfo(iter->ai_addr, (socklen_t) iter->ai_addrlen,
103 hbuf, host? (socklen_t) sizeof(hbuf): 0,
104 sbuf, serv? (socklen_t) sizeof(sbuf): 0, 0);
105 if (host) {
106 lua_pushnumber(L, i);
107 lua_pushstring(L, hbuf);
108 lua_settable(L, -3);
109 }
110 }
111 freeaddrinfo(resolved);
112
113 if (serv) {
114 lua_pushstring(L, sbuf);
115 return 2;
116 } else {
117 return 1;
118 }
119}
120
121/*-------------------------------------------------------------------------*\
122* Returns all information provided by the resolver given a host name
123* or ip address
124\*-------------------------------------------------------------------------*/
125static int inet_global_toip(lua_State *L)
126{
127 const char *address = luaL_checkstring(L, 1);
128 struct hostent *hp = NULL;
129 int err = inet_gethost(address, &hp);
130 if (err != IO_DONE) {
131 lua_pushnil(L);
132 lua_pushstring(L, socket_hoststrerror(err));
133 return 2;
134 }
135 lua_pushstring(L, inet_ntoa(*((struct in_addr *) hp->h_addr)));
136 inet_pushresolved(L, hp);
137 return 2;
138}
139
140int inet_optfamily(lua_State* L, int narg, const char* def)
141{
142 static const char* optname[] = { "unspec", "inet", "inet6", NULL };
143 static int optvalue[] = { AF_UNSPEC, AF_INET, AF_INET6, 0 };
144
145 return optvalue[luaL_checkoption(L, narg, def, optname)];
146}
147
148int inet_optsocktype(lua_State* L, int narg, const char* def)
149{
150 static const char* optname[] = { "stream", "dgram", NULL };
151 static int optvalue[] = { SOCK_STREAM, SOCK_DGRAM, 0 };
152
153 return optvalue[luaL_checkoption(L, narg, def, optname)];
154}
155
156static int inet_global_getaddrinfo(lua_State *L)
157{
158 const char *hostname = luaL_checkstring(L, 1);
159 struct addrinfo *iterator = NULL, *resolved = NULL;
160 struct addrinfo hints;
161 int i = 1, ret = 0;
162 memset(&hints, 0, sizeof(hints));
163 hints.ai_socktype = SOCK_STREAM;
164 hints.ai_family = AF_UNSPEC;
165 ret = getaddrinfo(hostname, NULL, &hints, &resolved);
166 if (ret != 0) {
167 lua_pushnil(L);
168 lua_pushstring(L, socket_gaistrerror(ret));
169 return 2;
170 }
171 lua_newtable(L);
172 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
173 char hbuf[NI_MAXHOST];
174 ret = getnameinfo(iterator->ai_addr, (socklen_t) iterator->ai_addrlen,
175 hbuf, (socklen_t) sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
176 if (ret){
177 freeaddrinfo(resolved);
178 lua_pushnil(L);
179 lua_pushstring(L, socket_gaistrerror(ret));
180 return 2;
181 }
182 lua_pushnumber(L, i);
183 lua_newtable(L);
184 switch (iterator->ai_family) {
185 case AF_INET:
186 lua_pushliteral(L, "family");
187 lua_pushliteral(L, "inet");
188 lua_settable(L, -3);
189 break;
190 case AF_INET6:
191 lua_pushliteral(L, "family");
192 lua_pushliteral(L, "inet6");
193 lua_settable(L, -3);
194 break;
195 case AF_UNSPEC:
196 lua_pushliteral(L, "family");
197 lua_pushliteral(L, "unspec");
198 lua_settable(L, -3);
199 break;
200 default:
201 lua_pushliteral(L, "family");
202 lua_pushliteral(L, "unknown");
203 lua_settable(L, -3);
204 break;
205 }
206 lua_pushliteral(L, "addr");
207 lua_pushstring(L, hbuf);
208 lua_settable(L, -3);
209 lua_settable(L, -3);
210 i++;
211 }
212 freeaddrinfo(resolved);
213 return 1;
214}
215
216/*-------------------------------------------------------------------------*\
217* Gets the host name
218\*-------------------------------------------------------------------------*/
219static int inet_global_gethostname(lua_State *L)
220{
221 char name[257];
222 name[256] = '\0';
223 if (gethostname(name, 256) < 0) {
224 lua_pushnil(L);
225 lua_pushstring(L, socket_strerror(errno));
226 return 2;
227 } else {
228 lua_pushstring(L, name);
229 return 1;
230 }
231}
232
233/*=========================================================================*\
234* Lua methods
235\*=========================================================================*/
236/*-------------------------------------------------------------------------*\
237* Retrieves socket peer name
238\*-------------------------------------------------------------------------*/
239int inet_meth_getpeername(lua_State *L, p_socket ps, int family)
240{
241 int err;
242 struct sockaddr_storage peer;
243 socklen_t peer_len = sizeof(peer);
244 char name[INET6_ADDRSTRLEN];
245 char port[6]; /* 65535 = 5 bytes + 0 to terminate it */
246 if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) {
247 lua_pushnil(L);
248 lua_pushstring(L, socket_strerror(errno));
249 return 2;
250 }
251 err = getnameinfo((struct sockaddr *) &peer, peer_len,
252 name, INET6_ADDRSTRLEN,
253 port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
254 if (err) {
255 lua_pushnil(L);
256 lua_pushstring(L, LUA_GAI_STRERROR(err));
257 return 2;
258 }
259 lua_pushstring(L, name);
260 lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10));
261 switch (family) {
262 case AF_INET: lua_pushliteral(L, "inet"); break;
263 case AF_INET6: lua_pushliteral(L, "inet6"); break;
264 case AF_UNSPEC: lua_pushliteral(L, "unspec"); break;
265 default: lua_pushliteral(L, "unknown"); break;
266 }
267 return 3;
268}
269
270/*-------------------------------------------------------------------------*\
271* Retrieves socket local name
272\*-------------------------------------------------------------------------*/
273int inet_meth_getsockname(lua_State *L, p_socket ps, int family)
274{
275 int err;
276 struct sockaddr_storage peer;
277 socklen_t peer_len = sizeof(peer);
278 char name[INET6_ADDRSTRLEN];
279 char port[6]; /* 65535 = 5 bytes + 0 to terminate it */
280 if (getsockname(*ps, (SA *) &peer, &peer_len) < 0) {
281 lua_pushnil(L);
282 lua_pushstring(L, socket_strerror(errno));
283 return 2;
284 }
285 err=getnameinfo((struct sockaddr *)&peer, peer_len,
286 name, INET6_ADDRSTRLEN, port, 6, NI_NUMERICHOST | NI_NUMERICSERV);
287 if (err) {
288 lua_pushnil(L);
289 lua_pushstring(L, LUA_GAI_STRERROR(err));
290 return 2;
291 }
292 lua_pushstring(L, name);
293 lua_pushstring(L, port);
294 switch (family) {
295 case AF_INET: lua_pushliteral(L, "inet"); break;
296 case AF_INET6: lua_pushliteral(L, "inet6"); break;
297 case AF_UNSPEC: lua_pushliteral(L, "unspec"); break;
298 default: lua_pushliteral(L, "unknown"); break;
299 }
300 return 3;
301}
302
303/*=========================================================================*\
304* Internal functions
305\*=========================================================================*/
306/*-------------------------------------------------------------------------*\
307* Passes all resolver information to Lua as a table
308\*-------------------------------------------------------------------------*/
309static void inet_pushresolved(lua_State *L, struct hostent *hp)
310{
311 char **alias;
312 struct in_addr **addr;
313 int i, resolved;
314 lua_newtable(L); resolved = lua_gettop(L);
315 lua_pushstring(L, "name");
316 lua_pushstring(L, hp->h_name);
317 lua_settable(L, resolved);
318 lua_pushstring(L, "ip");
319 lua_pushstring(L, "alias");
320 i = 1;
321 alias = hp->h_aliases;
322 lua_newtable(L);
323 if (alias) {
324 while (*alias) {
325 lua_pushnumber(L, i);
326 lua_pushstring(L, *alias);
327 lua_settable(L, -3);
328 i++; alias++;
329 }
330 }
331 lua_settable(L, resolved);
332 i = 1;
333 lua_newtable(L);
334 addr = (struct in_addr **) hp->h_addr_list;
335 if (addr) {
336 while (*addr) {
337 lua_pushnumber(L, i);
338 lua_pushstring(L, inet_ntoa(**addr));
339 lua_settable(L, -3);
340 i++; addr++;
341 }
342 }
343 lua_settable(L, resolved);
344}
345
346/*-------------------------------------------------------------------------*\
347* Tries to create a new inet socket
348\*-------------------------------------------------------------------------*/
349const char *inet_trycreate(p_socket ps, int family, int type, int protocol) {
350 const char *err = socket_strerror(socket_create(ps, family, type, protocol));
351 if (err == NULL && family == AF_INET6) {
352 int yes = 1;
353 setsockopt(*ps, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&yes, sizeof(yes));
354 }
355 return err;
356}
357
358/*-------------------------------------------------------------------------*\
359* "Disconnects" a DGRAM socket
360\*-------------------------------------------------------------------------*/
361const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm)
362{
363 switch (family) {
364 case AF_INET: {
365 struct sockaddr_in sin;
366 memset((char *) &sin, 0, sizeof(sin));
367 sin.sin_family = AF_UNSPEC;
368 sin.sin_addr.s_addr = INADDR_ANY;
369 return socket_strerror(socket_connect(ps, (SA *) &sin,
370 sizeof(sin), tm));
371 }
372 case AF_INET6: {
373 struct sockaddr_in6 sin6;
374 struct in6_addr addrany = IN6ADDR_ANY_INIT;
375 memset((char *) &sin6, 0, sizeof(sin6));
376 sin6.sin6_family = AF_UNSPEC;
377 sin6.sin6_addr = addrany;
378 return socket_strerror(socket_connect(ps, (SA *) &sin6,
379 sizeof(sin6), tm));
380 }
381 }
382 return NULL;
383}
384
385/*-------------------------------------------------------------------------*\
386* Tries to connect to remote address (address, port)
387\*-------------------------------------------------------------------------*/
388const char *inet_tryconnect(p_socket ps, int *family, const char *address,
389 const char *serv, p_timeout tm, struct addrinfo *connecthints)
390{
391 struct addrinfo *iterator = NULL, *resolved = NULL;
392 const char *err = NULL;
393 int current_family = *family;
394 /* try resolving */
395 err = socket_gaistrerror(getaddrinfo(address, serv,
396 connecthints, &resolved));
397 if (err != NULL) {
398 if (resolved) freeaddrinfo(resolved);
399 return err;
400 }
401 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
402 timeout_markstart(tm);
403 /* create new socket if necessary. if there was no
404 * bind, we need to create one for every new family
405 * that shows up while iterating. if there was a
406 * bind, all families will be the same and we will
407 * not enter this branch. */
408 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
409 socket_destroy(ps);
410 err = inet_trycreate(ps, iterator->ai_family,
411 iterator->ai_socktype, iterator->ai_protocol);
412 if (err) continue;
413 current_family = iterator->ai_family;
414 /* set non-blocking before connect */
415 socket_setnonblocking(ps);
416 }
417 /* try connecting to remote address */
418 err = socket_strerror(socket_connect(ps, (SA *) iterator->ai_addr,
419 (socklen_t) iterator->ai_addrlen, tm));
420 /* if success or timeout is zero, break out of loop */
421 if (err == NULL || timeout_iszero(tm)) {
422 *family = current_family;
423 break;
424 }
425 }
426 freeaddrinfo(resolved);
427 /* here, if err is set, we failed */
428 return err;
429}
430
431/*-------------------------------------------------------------------------*\
432* Tries to accept a socket
433\*-------------------------------------------------------------------------*/
434const char *inet_tryaccept(p_socket server, int family, p_socket client,
435 p_timeout tm) {
436 socklen_t len;
437 t_sockaddr_storage addr;
438 switch (family) {
439 case AF_INET6: len = sizeof(struct sockaddr_in6); break;
440 case AF_INET: len = sizeof(struct sockaddr_in); break;
441 default: len = sizeof(addr); break;
442 }
443 return socket_strerror(socket_accept(server, client, (SA *) &addr,
444 &len, tm));
445}
446
447/*-------------------------------------------------------------------------*\
448* Tries to bind socket to (address, port)
449\*-------------------------------------------------------------------------*/
450const char *inet_trybind(p_socket ps, int *family, const char *address,
451 const char *serv, struct addrinfo *bindhints) {
452 struct addrinfo *iterator = NULL, *resolved = NULL;
453 const char *err = NULL;
454 int current_family = *family;
455 /* translate luasocket special values to C */
456 if (strcmp(address, "*") == 0) address = NULL;
457 if (!serv) serv = "0";
458 /* try resolving */
459 err = socket_gaistrerror(getaddrinfo(address, serv, bindhints, &resolved));
460 if (err) {
461 if (resolved) freeaddrinfo(resolved);
462 return err;
463 }
464 /* iterate over resolved addresses until one is good */
465 for (iterator = resolved; iterator; iterator = iterator->ai_next) {
466 if (current_family != iterator->ai_family || *ps == SOCKET_INVALID) {
467 socket_destroy(ps);
468 err = inet_trycreate(ps, iterator->ai_family,
469 iterator->ai_socktype, iterator->ai_protocol);
470 if (err) continue;
471 current_family = iterator->ai_family;
472 }
473 /* try binding to local address */
474 err = socket_strerror(socket_bind(ps, (SA *) iterator->ai_addr,
475 (socklen_t) iterator->ai_addrlen));
476 /* keep trying unless bind succeeded */
477 if (err == NULL) {
478 *family = current_family;
479 /* set to non-blocking after bind */
480 socket_setnonblocking(ps);
481 break;
482 }
483 }
484 /* cleanup and return error */
485 freeaddrinfo(resolved);
486 /* here, if err is set, we failed */
487 return err;
488}
489
490/*-------------------------------------------------------------------------*\
491* Some systems do not provide these so that we provide our own.
492\*-------------------------------------------------------------------------*/
493#ifdef LUASOCKET_INET_ATON
494int inet_aton(const char *cp, struct in_addr *inp)
495{
496 unsigned int a = 0, b = 0, c = 0, d = 0;
497 int n = 0, r;
498 unsigned long int addr = 0;
499 r = sscanf(cp, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n);
500 if (r == 0 || n == 0) return 0;
501 cp += n;
502 if (*cp) return 0;
503 if (a > 255 || b > 255 || c > 255 || d > 255) return 0;
504 if (inp) {
505 addr += a; addr <<= 8;
506 addr += b; addr <<= 8;
507 addr += c; addr <<= 8;
508 addr += d;
509 inp->s_addr = htonl(addr);
510 }
511 return 1;
512}
513#endif
514
515#ifdef LUASOCKET_INET_PTON
516int inet_pton(int af, const char *src, void *dst)
517{
518 struct addrinfo hints, *res;
519 int ret = 1;
520 memset(&hints, 0, sizeof(struct addrinfo));
521 hints.ai_family = af;
522 hints.ai_flags = AI_NUMERICHOST;
523 if (getaddrinfo(src, NULL, &hints, &res) != 0) return -1;
524 if (af == AF_INET) {
525 struct sockaddr_in *in = (struct sockaddr_in *) res->ai_addr;
526 memcpy(dst, &in->sin_addr, sizeof(in->sin_addr));
527 } else if (af == AF_INET6) {
528 struct sockaddr_in6 *in = (struct sockaddr_in6 *) res->ai_addr;
529 memcpy(dst, &in->sin6_addr, sizeof(in->sin6_addr));
530 } else {
531 ret = -1;
532 }
533 freeaddrinfo(res);
534 return ret;
535}
536
537#endif
diff --git a/vendor/luasocket/src/inet.h b/vendor/luasocket/src/inet.h
new file mode 100644
index 00000000..5618b61b
--- /dev/null
+++ b/vendor/luasocket/src/inet.h
@@ -0,0 +1,56 @@
1#ifndef INET_H
2#define INET_H
3/*=========================================================================*\
4* Internet domain functions
5* LuaSocket toolkit
6*
7* This module implements the creation and connection of internet domain
8* sockets, on top of the socket.h interface, and the interface of with the
9* resolver.
10*
11* The function inet_aton is provided for the platforms where it is not
12* available. The module also implements the interface of the internet
13* getpeername and getsockname functions as seen by Lua programs.
14*
15* The Lua functions toip and tohostname are also implemented here.
16\*=========================================================================*/
17#include "luasocket.h"
18#include "socket.h"
19#include "timeout.h"
20
21#ifdef _WIN32
22#define LUASOCKET_INET_ATON
23#endif
24
25#ifndef _WIN32
26#pragma GCC visibility push(hidden)
27#endif
28
29int inet_open(lua_State *L);
30
31int inet_optfamily(lua_State* L, int narg, const char* def);
32int inet_optsocktype(lua_State* L, int narg, const char* def);
33
34int inet_meth_getpeername(lua_State *L, p_socket ps, int family);
35int inet_meth_getsockname(lua_State *L, p_socket ps, int family);
36
37const char *inet_trycreate(p_socket ps, int family, int type, int protocol);
38const char *inet_trydisconnect(p_socket ps, int family, p_timeout tm);
39const char *inet_tryconnect(p_socket ps, int *family, const char *address, const char *serv, p_timeout tm, struct addrinfo *connecthints);
40const char *inet_tryaccept(p_socket server, int family, p_socket client, p_timeout tm);
41const char *inet_trybind(p_socket ps, int *family, const char *address, const char *serv, struct addrinfo *bindhints);
42
43#ifdef LUASOCKET_INET_ATON
44int inet_aton(const char *cp, struct in_addr *inp);
45#endif
46
47#ifdef LUASOCKET_INET_PTON
48const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
49int inet_pton(int af, const char *src, void *dst);
50#endif
51
52#ifndef _WIN32
53#pragma GCC visibility pop
54#endif
55
56#endif /* INET_H */
diff --git a/vendor/luasocket/src/io.c b/vendor/luasocket/src/io.c
new file mode 100644
index 00000000..5ad4b3af
--- /dev/null
+++ b/vendor/luasocket/src/io.c
@@ -0,0 +1,28 @@
1/*=========================================================================*\
2* Input/Output abstraction
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6#include "io.h"
7
8/*-------------------------------------------------------------------------*\
9* Initializes C structure
10\*-------------------------------------------------------------------------*/
11void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx) {
12 io->send = send;
13 io->recv = recv;
14 io->error = error;
15 io->ctx = ctx;
16}
17
18/*-------------------------------------------------------------------------*\
19* I/O error strings
20\*-------------------------------------------------------------------------*/
21const char *io_strerror(int err) {
22 switch (err) {
23 case IO_DONE: return NULL;
24 case IO_CLOSED: return "closed";
25 case IO_TIMEOUT: return "timeout";
26 default: return "unknown error";
27 }
28}
diff --git a/vendor/luasocket/src/io.h b/vendor/luasocket/src/io.h
new file mode 100644
index 00000000..b8a54df6
--- /dev/null
+++ b/vendor/luasocket/src/io.h
@@ -0,0 +1,70 @@
1#ifndef IO_H
2#define IO_H
3/*=========================================================================*\
4* Input/Output abstraction
5* LuaSocket toolkit
6*
7* This module defines the interface that LuaSocket expects from the
8* transport layer for streamed input/output. The idea is that if any
9* transport implements this interface, then the buffer.c functions
10* automatically work on it.
11*
12* The module socket.h implements this interface, and thus the module tcp.h
13* is very simple.
14\*=========================================================================*/
15#include "luasocket.h"
16#include "timeout.h"
17
18/* IO error codes */
19enum {
20 IO_DONE = 0, /* operation completed successfully */
21 IO_TIMEOUT = -1, /* operation timed out */
22 IO_CLOSED = -2, /* the connection has been closed */
23 IO_UNKNOWN = -3
24};
25
26/* interface to error message function */
27typedef const char *(*p_error) (
28 void *ctx, /* context needed by send */
29 int err /* error code */
30);
31
32/* interface to send function */
33typedef int (*p_send) (
34 void *ctx, /* context needed by send */
35 const char *data, /* pointer to buffer with data to send */
36 size_t count, /* number of bytes to send from buffer */
37 size_t *sent, /* number of bytes sent uppon return */
38 p_timeout tm /* timeout control */
39);
40
41/* interface to recv function */
42typedef int (*p_recv) (
43 void *ctx, /* context needed by recv */
44 char *data, /* pointer to buffer where data will be writen */
45 size_t count, /* number of bytes to receive into buffer */
46 size_t *got, /* number of bytes received uppon return */
47 p_timeout tm /* timeout control */
48);
49
50/* IO driver definition */
51typedef struct t_io_ {
52 void *ctx; /* context needed by send/recv */
53 p_send send; /* send function pointer */
54 p_recv recv; /* receive function pointer */
55 p_error error; /* strerror function */
56} t_io;
57typedef t_io *p_io;
58
59#ifndef _WIN32
60#pragma GCC visibility push(hidden)
61#endif
62
63void io_init(p_io io, p_send send, p_recv recv, p_error error, void *ctx);
64const char *io_strerror(int err);
65
66#ifndef _WIN32
67#pragma GCC visibility pop
68#endif
69
70#endif /* IO_H */
diff --git a/vendor/luasocket/src/ltn12.lua b/vendor/luasocket/src/ltn12.lua
new file mode 100644
index 00000000..4cb17f53
--- /dev/null
+++ b/vendor/luasocket/src/ltn12.lua
@@ -0,0 +1,318 @@
1-----------------------------------------------------------------------------
2-- LTN12 - Filters, sources, sinks and pumps.
3-- LuaSocket toolkit.
4-- Author: Diego Nehab
5-----------------------------------------------------------------------------
6
7-----------------------------------------------------------------------------
8-- Declare module
9-----------------------------------------------------------------------------
10local string = require("string")
11local table = require("table")
12local unpack = unpack or table.unpack
13local base = _G
14local select = select
15
16local _M = {}
17if module then -- heuristic for exporting a global package table
18 ltn12 = _M -- luacheck: ignore
19end
20local filter,source,sink,pump = {},{},{},{}
21
22_M.filter = filter
23_M.source = source
24_M.sink = sink
25_M.pump = pump
26
27-- 2048 seems to be better in windows...
28_M.BLOCKSIZE = 2048
29_M._VERSION = "LTN12 1.0.3"
30
31-----------------------------------------------------------------------------
32-- Filter stuff
33-----------------------------------------------------------------------------
34-- returns a high level filter that cycles a low-level filter
35function filter.cycle(low, ctx, extra)
36 base.assert(low)
37 return function(chunk)
38 local ret
39 ret, ctx = low(ctx, chunk, extra)
40 return ret
41 end
42end
43
44-- chains a bunch of filters together
45-- (thanks to Wim Couwenberg)
46function filter.chain(...)
47 local arg = {...}
48 local n = select('#',...)
49 local top, index = 1, 1
50 local retry = ""
51 return function(chunk)
52 retry = chunk and retry
53 while true do
54 if index == top then
55 chunk = arg[index](chunk)
56 if chunk == "" or top == n then return chunk
57 elseif chunk then index = index + 1
58 else
59 top = top+1
60 index = top
61 end
62 else
63 chunk = arg[index](chunk or "")
64 if chunk == "" then
65 index = index - 1
66 chunk = retry
67 elseif chunk then
68 if index == n then return chunk
69 else index = index + 1 end
70 else base.error("filter returned inappropriate nil") end
71 end
72 end
73 end
74end
75
76-----------------------------------------------------------------------------
77-- Source stuff
78-----------------------------------------------------------------------------
79-- create an empty source
80local function empty()
81 return nil
82end
83
84function source.empty()
85 return empty
86end
87
88-- returns a source that just outputs an error
89function source.error(err)
90 return function()
91 return nil, err
92 end
93end
94
95-- creates a file source
96function source.file(handle, io_err)
97 if handle then
98 return function()
99 local chunk = handle:read(_M.BLOCKSIZE)
100 if not chunk then handle:close() end
101 return chunk
102 end
103 else return source.error(io_err or "unable to open file") end
104end
105
106-- turns a fancy source into a simple source
107function source.simplify(src)
108 base.assert(src)
109 return function()
110 local chunk, err_or_new = src()
111 src = err_or_new or src
112 if not chunk then return nil, err_or_new
113 else return chunk end
114 end
115end
116
117-- creates string source
118function source.string(s)
119 if s then
120 local i = 1
121 return function()
122 local chunk = string.sub(s, i, i+_M.BLOCKSIZE-1)
123 i = i + _M.BLOCKSIZE
124 if chunk ~= "" then return chunk
125 else return nil end
126 end
127 else return source.empty() end
128end
129
130-- creates table source
131function source.table(t)
132 base.assert('table' == type(t))
133 local i = 0
134 return function()
135 i = i + 1
136 return t[i]
137 end
138end
139
140-- creates rewindable source
141function source.rewind(src)
142 base.assert(src)
143 local t = {}
144 return function(chunk)
145 if not chunk then
146 chunk = table.remove(t)
147 if not chunk then return src()
148 else return chunk end
149 else
150 table.insert(t, chunk)
151 end
152 end
153end
154
155-- chains a source with one or several filter(s)
156function source.chain(src, f, ...)
157 if ... then f=filter.chain(f, ...) end
158 base.assert(src and f)
159 local last_in, last_out = "", ""
160 local state = "feeding"
161 local err
162 return function()
163 if not last_out then
164 base.error('source is empty!', 2)
165 end
166 while true do
167 if state == "feeding" then
168 last_in, err = src()
169 if err then return nil, err end
170 last_out = f(last_in)
171 if not last_out then
172 if last_in then
173 base.error('filter returned inappropriate nil')
174 else
175 return nil
176 end
177 elseif last_out ~= "" then
178 state = "eating"
179 if last_in then last_in = "" end
180 return last_out
181 end
182 else
183 last_out = f(last_in)
184 if last_out == "" then
185 if last_in == "" then
186 state = "feeding"
187 else
188 base.error('filter returned ""')
189 end
190 elseif not last_out then
191 if last_in then
192 base.error('filter returned inappropriate nil')
193 else
194 return nil
195 end
196 else
197 return last_out
198 end
199 end
200 end
201 end
202end
203
204-- creates a source that produces contents of several sources, one after the
205-- other, as if they were concatenated
206-- (thanks to Wim Couwenberg)
207function source.cat(...)
208 local arg = {...}
209 local src = table.remove(arg, 1)
210 return function()
211 while src do
212 local chunk, err = src()
213 if chunk then return chunk end
214 if err then return nil, err end
215 src = table.remove(arg, 1)
216 end
217 end
218end
219
220-----------------------------------------------------------------------------
221-- Sink stuff
222-----------------------------------------------------------------------------
223-- creates a sink that stores into a table
224function sink.table(t)
225 t = t or {}
226 local f = function(chunk, err)
227 if chunk then table.insert(t, chunk) end
228 return 1
229 end
230 return f, t
231end
232
233-- turns a fancy sink into a simple sink
234function sink.simplify(snk)
235 base.assert(snk)
236 return function(chunk, err)
237 local ret, err_or_new = snk(chunk, err)
238 if not ret then return nil, err_or_new end
239 snk = err_or_new or snk
240 return 1
241 end
242end
243
244-- creates a file sink
245function sink.file(handle, io_err)
246 if handle then
247 return function(chunk, err)
248 if not chunk then
249 handle:close()
250 return 1
251 else return handle:write(chunk) end
252 end
253 else return sink.error(io_err or "unable to open file") end
254end
255
256-- creates a sink that discards data
257local function null()
258 return 1
259end
260
261function sink.null()
262 return null
263end
264
265-- creates a sink that just returns an error
266function sink.error(err)
267 return function()
268 return nil, err
269 end
270end
271
272-- chains a sink with one or several filter(s)
273function sink.chain(f, snk, ...)
274 if ... then
275 local args = { f, snk, ... }
276 snk = table.remove(args, #args)
277 f = filter.chain(unpack(args))
278 end
279 base.assert(f and snk)
280 return function(chunk, err)
281 if chunk ~= "" then
282 local filtered = f(chunk)
283 local done = chunk and ""
284 while true do
285 local ret, snkerr = snk(filtered, err)
286 if not ret then return nil, snkerr end
287 if filtered == done then return 1 end
288 filtered = f(done)
289 end
290 else return 1 end
291 end
292end
293
294-----------------------------------------------------------------------------
295-- Pump stuff
296-----------------------------------------------------------------------------
297-- pumps one chunk from the source to the sink
298function pump.step(src, snk)
299 local chunk, src_err = src()
300 local ret, snk_err = snk(chunk, src_err)
301 if chunk and ret then return 1
302 else return nil, src_err or snk_err end
303end
304
305-- pumps all data from a source to a sink, using a step function
306function pump.all(src, snk, step)
307 base.assert(src and snk)
308 step = step or pump.step
309 while true do
310 local ret, err = step(src, snk)
311 if not ret then
312 if err then return nil, err
313 else return 1 end
314 end
315 end
316end
317
318return _M
diff --git a/vendor/luasocket/src/luasocket.c b/vendor/luasocket/src/luasocket.c
new file mode 100755
index 00000000..0fd99f70
--- /dev/null
+++ b/vendor/luasocket/src/luasocket.c
@@ -0,0 +1,104 @@
1/*=========================================================================*\
2* LuaSocket toolkit
3* Networking support for the Lua language
4* Diego Nehab
5* 26/11/1999
6*
7* This library is part of an effort to progressively increase the network
8* connectivity of the Lua language. The Lua interface to networking
9* functions follows the Sockets API closely, trying to simplify all tasks
10* involved in setting up both client and server connections. The provided
11* IO routines, however, follow the Lua style, being very similar to the
12* standard Lua read and write functions.
13\*=========================================================================*/
14
15#include "luasocket.h"
16#include "auxiliar.h"
17#include "except.h"
18#include "timeout.h"
19#include "buffer.h"
20#include "inet.h"
21#include "tcp.h"
22#include "udp.h"
23#include "select.h"
24
25/*-------------------------------------------------------------------------*\
26* Internal function prototypes
27\*-------------------------------------------------------------------------*/
28static int global_skip(lua_State *L);
29static int global_unload(lua_State *L);
30static int base_open(lua_State *L);
31
32/*-------------------------------------------------------------------------*\
33* Modules and functions
34\*-------------------------------------------------------------------------*/
35static const luaL_Reg mod[] = {
36 {"auxiliar", auxiliar_open},
37 {"except", except_open},
38 {"timeout", timeout_open},
39 {"buffer", buffer_open},
40 {"inet", inet_open},
41 {"tcp", tcp_open},
42 {"udp", udp_open},
43 {"select", select_open},
44 {NULL, NULL}
45};
46
47static luaL_Reg func[] = {
48 {"skip", global_skip},
49 {"__unload", global_unload},
50 {NULL, NULL}
51};
52
53/*-------------------------------------------------------------------------*\
54* Skip a few arguments
55\*-------------------------------------------------------------------------*/
56static int global_skip(lua_State *L) {
57 int amount = (int) luaL_checkinteger(L, 1);
58 int ret = lua_gettop(L) - amount - 1;
59 return ret >= 0 ? ret : 0;
60}
61
62/*-------------------------------------------------------------------------*\
63* Unloads the library
64\*-------------------------------------------------------------------------*/
65static int global_unload(lua_State *L) {
66 (void) L;
67 socket_close();
68 return 0;
69}
70
71/*-------------------------------------------------------------------------*\
72* Setup basic stuff.
73\*-------------------------------------------------------------------------*/
74static int base_open(lua_State *L) {
75 if (socket_open()) {
76 /* export functions (and leave namespace table on top of stack) */
77 lua_newtable(L);
78 luaL_setfuncs(L, func, 0);
79#ifdef LUASOCKET_DEBUG
80 lua_pushstring(L, "_DEBUG");
81 lua_pushboolean(L, 1);
82 lua_rawset(L, -3);
83#endif
84 /* make version string available to scripts */
85 lua_pushstring(L, "_VERSION");
86 lua_pushstring(L, LUASOCKET_VERSION);
87 lua_rawset(L, -3);
88 return 1;
89 } else {
90 lua_pushstring(L, "unable to initialize library");
91 lua_error(L);
92 return 0;
93 }
94}
95
96/*-------------------------------------------------------------------------*\
97* Initializes all library modules.
98\*-------------------------------------------------------------------------*/
99LUASOCKET_API int luaopen_socket_core(lua_State *L) {
100 int i;
101 base_open(L);
102 for (i = 0; mod[i].name; i++) mod[i].func(L);
103 return 1;
104}
diff --git a/vendor/luasocket/src/luasocket.h b/vendor/luasocket/src/luasocket.h
new file mode 100644
index 00000000..1017fbaa
--- /dev/null
+++ b/vendor/luasocket/src/luasocket.h
@@ -0,0 +1,36 @@
1#ifndef LUASOCKET_H
2#define LUASOCKET_H
3/*=========================================================================*\
4* LuaSocket toolkit
5* Networking support for the Lua language
6* Diego Nehab
7* 9/11/1999
8\*=========================================================================*/
9
10/*-------------------------------------------------------------------------* \
11* Current socket library version
12\*-------------------------------------------------------------------------*/
13#define LUASOCKET_VERSION "LuaSocket 3.0.0"
14#define LUASOCKET_COPYRIGHT "Copyright (C) 1999-2013 Diego Nehab"
15
16/*-------------------------------------------------------------------------*\
17* This macro prefixes all exported API functions
18\*-------------------------------------------------------------------------*/
19#ifndef LUASOCKET_API
20#ifdef _WIN32
21#define LUASOCKET_API __declspec(dllexport)
22#else
23#define LUASOCKET_API __attribute__ ((visibility ("default")))
24#endif
25#endif
26
27#include "lua.h"
28#include "lauxlib.h"
29#include "compat.h"
30
31/*-------------------------------------------------------------------------*\
32* Initializes the library.
33\*-------------------------------------------------------------------------*/
34LUASOCKET_API int luaopen_socket_core(lua_State *L);
35
36#endif /* LUASOCKET_H */
diff --git a/vendor/luasocket/src/makefile b/vendor/luasocket/src/makefile
new file mode 100755
index 00000000..06f4d192
--- /dev/null
+++ b/vendor/luasocket/src/makefile
@@ -0,0 +1,461 @@
1# luasocket src/makefile
2#
3# Definitions in this section can be overriden on the command line or in the
4# environment.
5#
6# These are equivalent:
7#
8# export PLAT=linux DEBUG=DEBUG LUAV=5.2 prefix=/sw
9# make
10#
11# and
12#
13# make PLAT=linux DEBUG=DEBUG LUAV=5.2 prefix=/sw
14
15# PLAT: linux macosx win32 win64 mingw
16# platform to build for
17PLAT?=linux
18
19# LUAV: 5.1 5.2 5.3 5.4
20# lua version to build against
21LUAV?=5.1
22
23# MYCFLAGS: to be set by user if needed
24MYCFLAGS?=
25
26# MYLDFLAGS: to be set by user if needed
27MYLDFLAGS?=
28
29# DEBUG: NODEBUG DEBUG
30# debug mode causes luasocket to collect and returns timing information useful
31# for testing and debugging luasocket itself
32DEBUG?=NODEBUG
33
34# where lua headers are found for macosx builds
35# LUAINC_macosx:
36# /opt/local/include
37LUAINC_macosx_base?=/opt/local/include
38LUAINC_macosx?=$(LUAINC_macosx_base)/lua/$(LUAV) $(LUAINC_macosx_base)/lua$(LUAV) $(LUAINC_macosx_base)/lua-$(LUAV)
39
40# FIXME default should this default to fink or to macports?
41# What happens when more than one Lua version is installed?
42LUAPREFIX_macosx?=/opt/local
43CDIR_macosx?=lib/lua/$(LUAV)
44LDIR_macosx?=share/lua/$(LUAV)
45
46# LUAINC_linux:
47# /usr/include/lua$(LUAV)
48# /usr/local/include
49# /usr/local/include/lua$(LUAV)
50# where lua headers are found for linux builds
51LUAINC_linux_base?=/usr/include
52LUAINC_linux?=$(LUAINC_linux_base)/lua/$(LUAV) $(LUAINC_linux_base)/lua$(LUAV)
53LUAPREFIX_linux?=/usr/local
54CDIR_linux?=lib/lua/$(LUAV)
55LDIR_linux?=share/lua/$(LUAV)
56
57# LUAINC_freebsd:
58# /usr/local/include/lua$(LUAV)
59# where lua headers are found for freebsd builds
60LUAINC_freebsd_base?=/usr/local/include/
61LUAINC_freebsd?=$(LUAINC_freebsd_base)/lua/$(LUAV) $(LUAINC_freebsd_base)/lua$(LUAV)
62LUAPREFIX_freebsd?=/usr/local/
63CDIR_freebsd?=lib/lua/$(LUAV)
64LDIR_freebsd?=share/lua/$(LUAV)
65
66# where lua headers are found for mingw builds
67# LUAINC_mingw:
68# /opt/local/include
69LUAINC_mingw_base?=/usr/include
70LUAINC_mingw?=$(LUAINC_mingw_base)/lua/$(LUAV) $(LUAINC_mingw_base)/lua$(LUAV)
71LUALIB_mingw_base?=/usr/bin
72LUALIB_mingw?=$(LUALIB_mingw_base)/lua/$(LUAV)/lua$(subst .,,$(LUAV)).dll
73LUAPREFIX_mingw?=/usr
74CDIR_mingw?=lua/$(LUAV)
75LDIR_mingw?=lua/$(LUAV)/lua
76
77
78# LUAINC_win32:
79# LUALIB_win32:
80# where lua headers and libraries are found for win32 builds
81LUAPREFIX_win32?=
82LUAINC_win32?=$(LUAPREFIX_win32)/include/lua/$(LUAV) $(LUAPREFIX_win32)/include/lua$(LUAV)
83PLATFORM_win32?=Release
84CDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)
85LDIR_win32?=bin/lua/$(LUAV)/$(PLATFORM_win32)/lua
86LUALIB_win32?=$(LUAPREFIX_win32)/lib/lua/$(LUAV)/$(PLATFORM_win32)
87LUALIBNAME_win32?=lua$(subst .,,$(LUAV)).lib
88
89# LUAINC_win64:
90# LUALIB_win64:
91# where lua headers and libraries are found for win64 builds
92LUAPREFIX_win64?=
93LUAINC_win64?=$(LUAPREFIX_win64)/include/lua/$(LUAV) $(LUAPREFIX_win64)/include/lua$(LUAV)
94PLATFORM_win64?=x64/Release
95CDIR_win64?=bin/lua/$(LUAV)/$(PLATFORM_win64)
96LDIR_win64?=bin/lua/$(LUAV)/$(PLATFORM_win64)/lua
97LUALIB_win64?=$(LUAPREFIX_win64)/lib/lua/$(LUAV)/$(PLATFORM_win64)
98LUALIBNAME_win64?=lua$(subst .,,$(LUAV)).lib
99
100
101# LUAINC_solaris:
102LUAINC_solaris_base?=/usr/include
103LUAINC_solaris?=$(LUAINC_solaris_base)/lua/$(LUAV) $(LUAINC_solaris_base)/lua$(LUAV)
104LUAPREFIX_solaris?=/usr/local
105CDIR_solaris?=lib/lua/$(LUAV)
106LDIR_solaris?=share/lua/$(LUAV)
107
108# prefix: /usr/local /usr /opt/local /sw
109# the top of the default install tree
110prefix?=$(LUAPREFIX_$(PLAT))
111
112CDIR?=$(CDIR_$(PLAT))
113LDIR?=$(LDIR_$(PLAT))
114
115# DESTDIR: (no default)
116# used by package managers to install into a temporary destination
117DESTDIR?=
118
119#------
120# Definitions below can be overridden on the make command line, but
121# shouldn't have to be.
122
123
124#------
125# Install directories
126#
127
128INSTALL_DIR=install -d
129INSTALL_DATA=install -m644
130INSTALL_EXEC=install
131INSTALL_TOP=$(DESTDIR)$(prefix)
132
133INSTALL_TOP_LDIR=$(INSTALL_TOP)/$(LDIR)
134INSTALL_TOP_CDIR=$(INSTALL_TOP)/$(CDIR)
135
136INSTALL_SOCKET_LDIR=$(INSTALL_TOP_LDIR)/socket
137INSTALL_SOCKET_CDIR=$(INSTALL_TOP_CDIR)/socket
138INSTALL_MIME_LDIR=$(INSTALL_TOP_LDIR)/mime
139INSTALL_MIME_CDIR=$(INSTALL_TOP_CDIR)/mime
140
141print:
142 @echo PLAT=$(PLAT)
143 @echo LUAV=$(LUAV)
144 @echo DEBUG=$(DEBUG)
145 @echo prefix=$(prefix)
146 @echo LUAINC_$(PLAT)=$(LUAINC_$(PLAT))
147 @echo LUALIB_$(PLAT)=$(LUALIB_$(PLAT))
148 @echo INSTALL_TOP_CDIR=$(INSTALL_TOP_CDIR)
149 @echo INSTALL_TOP_LDIR=$(INSTALL_TOP_LDIR)
150 @echo CFLAGS=$(CFLAGS)
151 @echo LDFLAGS=$(LDFLAGS)
152
153#------
154# Supported platforms
155#
156PLATS= macosx linux win32 win64 mingw solaris
157
158#------
159# Compiler and linker settings
160# for Mac OS X
161SO_macosx=so
162O_macosx=o
163CC_macosx=gcc
164DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN
165CFLAGS_macosx=$(LUAINC:%=-I%) $(DEF) -Wall -O2 -fno-common
166LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o
167LD_macosx=gcc
168SOCKET_macosx=usocket.o
169
170#------
171# Compiler and linker settings
172# for Linux
173SO_linux=so
174O_linux=o
175CC_linux=gcc
176DEF_linux=-DLUASOCKET_$(DEBUG)
177CFLAGS_linux=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \
178 -Wimplicit -O2 -ggdb3 -fpic
179LDFLAGS_linux=-O -shared -fpic -o
180LD_linux=gcc
181SOCKET_linux=usocket.o
182
183#------
184# Compiler and linker settings
185# for FreeBSD
186SO_freebsd=so
187O_freebsd=o
188CC_freebsd=gcc
189DEF_freebsd=-DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN
190CFLAGS_freebsd=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \
191 -Wimplicit -O2 -ggdb3 -fpic
192LDFLAGS_freebsd=-O -shared -fpic -o
193LD_freebsd=gcc
194SOCKET_freebsd=usocket.o
195
196#------
197# Compiler and linker settings
198# for Solaris
199SO_solaris=so
200O_solaris=o
201CC_solaris=gcc
202DEF_solaris=-DLUASOCKET_$(DEBUG)
203CFLAGS_solaris=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \
204 -Wimplicit -O2 -ggdb3 -fpic
205LDFLAGS_solaris=-lnsl -lsocket -lresolv -O -shared -fpic -o
206LD_solaris=gcc
207SOCKET_solaris=usocket.o
208
209#------
210# Compiler and linker settings
211# for MingW
212SO_mingw=dll
213O_mingw=o
214CC_mingw=gcc
215DEF_mingw= -DLUASOCKET_$(DEBUG) \
216 -DWINVER=0x0501
217CFLAGS_mingw=$(LUAINC:%=-I%) $(DEF) -Wall -O2 -fno-common
218LDFLAGS_mingw= $(LUALIB) -shared -Wl,-s -lws2_32 -o
219LD_mingw=gcc
220SOCKET_mingw=wsocket.o
221
222
223#------
224# Compiler and linker settings
225# for Win32
226SO_win32=dll
227O_win32=obj
228CC_win32=cl
229DEF_win32= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \
230 //D "_CRT_SECURE_NO_WARNINGS" \
231 //D "_WINDLL" \
232 //D "LUASOCKET_$(DEBUG)"
233CFLAGS_win32=$(LUAINC:%=//I "%") $(DEF) //O2 //Ot //MD //W3 //nologo
234LDFLAGS_win32= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \
235 //MANIFEST //MANIFESTFILE:"intermediate.manifest" \
236 /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \
237 //SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \
238 //MACHINE:X86 /LIBPATH:"$(LUALIB)" \
239 $(LUALIBNAME_win32) ws2_32.lib //OUT:
240
241LD_win32=cl
242SOCKET_win32=wsocket.obj
243
244#------
245# Compiler and linker settings
246# for Win64
247SO_win64=dll
248O_win64=obj
249CC_win64=cl
250DEF_win64= //D "WIN32" //D "NDEBUG" //D "_WINDOWS" //D "_USRDLL" \
251 //D "_CRT_SECURE_NO_WARNINGS" \
252 //D "_WINDLL" \
253 //D "LUASOCKET_$(DEBUG)"
254CFLAGS_win64=$(LUAINC:%=//I "%") $(DEF) //O2 //Ot //MD //W3 //nologo
255LDFLAGS_win64= //nologo //link //NOLOGO //DLL //INCREMENTAL:NO \
256 //MANIFEST //MANIFESTFILE:"intermediate.manifest" \
257 /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \
258 //SUBSYSTEM:WINDOWS //OPT:REF //OPT:ICF //DYNAMICBASE:NO \
259 /LIBPATH:"$(LUALIB)" \
260 $(LUALIBNAME_win64) ws2_32.lib //OUT:
261
262LD_win64=cl
263SOCKET_win64=wsocket.obj
264
265.SUFFIXES: .obj
266
267.c.obj:
268 $(CC) $(CFLAGS) //Fo"$@" //c $<
269
270#------
271# Output file names
272#
273SO=$(SO_$(PLAT))
274O=$(O_$(PLAT))
275SOCKET_V=3.0.0
276MIME_V=1.0.3
277SOCKET_SO=socket-$(SOCKET_V).$(SO)
278MIME_SO=mime-$(MIME_V).$(SO)
279UNIX_SO=unix.$(SO)
280SERIAL_SO=serial.$(SO)
281SOCKET=$(SOCKET_$(PLAT))
282
283#------
284# Settings selected for platform
285#
286CC=$(CC_$(PLAT))
287DEF=$(DEF_$(PLAT))
288CFLAGS=$(MYCFLAGS) $(CFLAGS_$(PLAT))
289LDFLAGS=$(MYLDFLAGS) $(LDFLAGS_$(PLAT))
290LD=$(LD_$(PLAT))
291LUAINC= $(LUAINC_$(PLAT))
292LUALIB= $(LUALIB_$(PLAT))
293
294#------
295# Modules belonging to socket-core
296#
297SOCKET_OBJS= \
298 luasocket.$(O) \
299 timeout.$(O) \
300 buffer.$(O) \
301 io.$(O) \
302 auxiliar.$(O) \
303 compat.$(O) \
304 options.$(O) \
305 inet.$(O) \
306 $(SOCKET) \
307 except.$(O) \
308 select.$(O) \
309 tcp.$(O) \
310 udp.$(O)
311
312#------
313# Modules belonging mime-core
314#
315MIME_OBJS= \
316 mime.$(O) \
317 compat.$(O)
318
319#------
320# Modules belonging unix (local domain sockets)
321#
322UNIX_OBJS=\
323 buffer.$(O) \
324 auxiliar.$(O) \
325 options.$(O) \
326 timeout.$(O) \
327 io.$(O) \
328 usocket.$(O) \
329 unixstream.$(O) \
330 unixdgram.$(O) \
331 compat.$(O) \
332 unix.$(O)
333
334#------
335# Modules belonging to serial (device streams)
336#
337SERIAL_OBJS=\
338 buffer.$(O) \
339 compat.$(O) \
340 auxiliar.$(O) \
341 options.$(O) \
342 timeout.$(O) \
343 io.$(O) \
344 usocket.$(O) \
345 serial.$(O)
346
347#------
348# Files to install
349#
350TO_SOCKET_LDIR= \
351 http.lua \
352 url.lua \
353 tp.lua \
354 ftp.lua \
355 headers.lua \
356 smtp.lua
357
358TO_TOP_LDIR= \
359 ltn12.lua \
360 socket.lua \
361 mime.lua
362
363#------
364# Targets
365#
366default: $(PLAT)
367
368
369freebsd:
370 $(MAKE) all-unix PLAT=freebsd
371
372macosx:
373 $(MAKE) all-unix PLAT=macosx
374
375win32:
376 $(MAKE) all PLAT=win32
377
378win64:
379 $(MAKE) all PLAT=win64
380
381linux:
382 $(MAKE) all-unix PLAT=linux
383
384mingw:
385 $(MAKE) all PLAT=mingw
386
387solaris:
388 $(MAKE) all-unix PLAT=solaris
389
390none:
391 @echo "Please run"
392 @echo " make PLATFORM"
393 @echo "where PLATFORM is one of these:"
394 @echo " $(PLATS)"
395
396all: $(SOCKET_SO) $(MIME_SO)
397
398$(SOCKET_SO): $(SOCKET_OBJS)
399 $(LD) $(SOCKET_OBJS) $(LDFLAGS)$@
400
401$(MIME_SO): $(MIME_OBJS)
402 $(LD) $(MIME_OBJS) $(LDFLAGS)$@
403
404all-unix: all $(UNIX_SO) $(SERIAL_SO)
405
406$(UNIX_SO): $(UNIX_OBJS)
407 $(LD) $(UNIX_OBJS) $(LDFLAGS)$@
408
409$(SERIAL_SO): $(SERIAL_OBJS)
410 $(LD) $(SERIAL_OBJS) $(LDFLAGS)$@
411
412install:
413 $(INSTALL_DIR) $(INSTALL_TOP_LDIR)
414 $(INSTALL_DATA) $(TO_TOP_LDIR) $(INSTALL_TOP_LDIR)
415 $(INSTALL_DIR) $(INSTALL_SOCKET_LDIR)
416 $(INSTALL_DATA) $(TO_SOCKET_LDIR) $(INSTALL_SOCKET_LDIR)
417 $(INSTALL_DIR) $(INSTALL_SOCKET_CDIR)
418 $(INSTALL_EXEC) $(SOCKET_SO) $(INSTALL_SOCKET_CDIR)/core.$(SO)
419 $(INSTALL_DIR) $(INSTALL_MIME_CDIR)
420 $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_CDIR)/core.$(SO)
421
422install-unix: install
423 $(INSTALL_EXEC) $(UNIX_SO) $(INSTALL_SOCKET_CDIR)/$(UNIX_SO)
424 $(INSTALL_EXEC) $(SERIAL_SO) $(INSTALL_SOCKET_CDIR)/$(SERIAL_SO)
425
426local:
427 $(MAKE) install INSTALL_TOP_CDIR=.. INSTALL_TOP_LDIR=..
428
429clean:
430 rm -f $(SOCKET_SO) $(SOCKET_OBJS) $(SERIAL_OBJS)
431 rm -f $(MIME_SO) $(UNIX_SO) $(SERIAL_SO) $(MIME_OBJS) $(UNIX_OBJS)
432
433.PHONY: all $(PLATS) default clean echo none
434
435#------
436# List of dependencies
437#
438compat.$(O): compat.c compat.h
439auxiliar.$(O): auxiliar.c auxiliar.h
440buffer.$(O): buffer.c buffer.h io.h timeout.h
441except.$(O): except.c except.h
442inet.$(O): inet.c inet.h socket.h io.h timeout.h usocket.h
443io.$(O): io.c io.h timeout.h
444luasocket.$(O): luasocket.c luasocket.h auxiliar.h except.h \
445 timeout.h buffer.h io.h inet.h socket.h usocket.h tcp.h \
446 udp.h select.h
447mime.$(O): mime.c mime.h
448options.$(O): options.c auxiliar.h options.h socket.h io.h \
449 timeout.h usocket.h inet.h
450select.$(O): select.c socket.h io.h timeout.h usocket.h select.h
451serial.$(O): serial.c auxiliar.h socket.h io.h timeout.h usocket.h \
452 options.h unix.h buffer.h
453tcp.$(O): tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \
454 inet.h options.h tcp.h buffer.h
455timeout.$(O): timeout.c auxiliar.h timeout.h
456udp.$(O): udp.c auxiliar.h socket.h io.h timeout.h usocket.h \
457 inet.h options.h udp.h
458unix.$(O): unix.c auxiliar.h socket.h io.h timeout.h usocket.h \
459 options.h unix.h buffer.h
460usocket.$(O): usocket.c socket.h io.h timeout.h usocket.h
461wsocket.$(O): wsocket.c socket.h io.h timeout.h usocket.h
diff --git a/vendor/luasocket/src/mbox.lua b/vendor/luasocket/src/mbox.lua
new file mode 100644
index 00000000..12823b0a
--- /dev/null
+++ b/vendor/luasocket/src/mbox.lua
@@ -0,0 +1,93 @@
1local _M = {}
2
3if module then
4 mbox = _M -- luacheck: ignore
5end
6
7function _M.split_message(message_s)
8 local message = {}
9 message_s = string.gsub(message_s, "\r\n", "\n")
10 string.gsub(message_s, "^(.-\n)\n", function (h) message.headers = h end)
11 string.gsub(message_s, "^.-\n\n(.*)", function (b) message.body = b end)
12 if not message.body then
13 string.gsub(message_s, "^\n(.*)", function (b) message.body = b end)
14 end
15 if not message.headers and not message.body then
16 message.headers = message_s
17 end
18 return message.headers or "", message.body or ""
19end
20
21function _M.split_headers(headers_s)
22 local headers = {}
23 headers_s = string.gsub(headers_s, "\r\n", "\n")
24 headers_s = string.gsub(headers_s, "\n[ ]+", " ")
25 string.gsub("\n" .. headers_s, "\n([^\n]+)", function (h) table.insert(headers, h) end)
26 return headers
27end
28
29function _M.parse_header(header_s)
30 header_s = string.gsub(header_s, "\n[ ]+", " ")
31 header_s = string.gsub(header_s, "\n+", "")
32 local _, _, name, value = string.find(header_s, "([^%s:]-):%s*(.*)")
33 return name, value
34end
35
36function _M.parse_headers(headers_s)
37 local headers_t = _M.split_headers(headers_s)
38 local headers = {}
39 for i = 1, #headers_t do
40 local name, value = _M.parse_header(headers_t[i])
41 if name then
42 name = string.lower(name)
43 if headers[name] then
44 headers[name] = headers[name] .. ", " .. value
45 else headers[name] = value end
46 end
47 end
48 return headers
49end
50
51function _M.parse_from(from)
52 local _, _, name, address = string.find(from, "^%s*(.-)%s*%<(.-)%>")
53 if not address then
54 _, _, address = string.find(from, "%s*(.+)%s*")
55 end
56 name = name or ""
57 address = address or ""
58 if name == "" then name = address end
59 name = string.gsub(name, '"', "")
60 return name, address
61end
62
63function _M.split_mbox(mbox_s)
64 local mbox = {}
65 mbox_s = string.gsub(mbox_s, "\r\n", "\n") .."\n\nFrom \n"
66 local nj, i
67 local j = 1
68 while 1 do
69 i, nj = string.find(mbox_s, "\n\nFrom .-\n", j)
70 if not i then break end
71 local message = string.sub(mbox_s, j, i-1)
72 table.insert(mbox, message)
73 j = nj+1
74 end
75 return mbox
76end
77
78function _M.parse(mbox_s)
79 local mbox = _M.split_mbox(mbox_s)
80 for i = 1, #mbox do
81 mbox[i] = _M.parse_message(mbox[i])
82 end
83 return mbox
84end
85
86function _M.parse_message(message_s)
87 local message = {}
88 message.headers, message.body = _M.split_message(message_s)
89 message.headers = _M.parse_headers(message.headers)
90 return message
91end
92
93return _M
diff --git a/vendor/luasocket/src/mime.c b/vendor/luasocket/src/mime.c
new file mode 100755
index 00000000..05602f56
--- /dev/null
+++ b/vendor/luasocket/src/mime.c
@@ -0,0 +1,852 @@
1/*=========================================================================*\
2* MIME support functions
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6#include "mime.h"
7#include <string.h>
8#include <ctype.h>
9
10/*=========================================================================*\
11* Don't want to trust escape character constants
12\*=========================================================================*/
13typedef unsigned char UC;
14static const char CRLF[] = "\r\n";
15static const char EQCRLF[] = "=\r\n";
16
17/*=========================================================================*\
18* Internal function prototypes.
19\*=========================================================================*/
20static int mime_global_wrp(lua_State *L);
21static int mime_global_b64(lua_State *L);
22static int mime_global_unb64(lua_State *L);
23static int mime_global_qp(lua_State *L);
24static int mime_global_unqp(lua_State *L);
25static int mime_global_qpwrp(lua_State *L);
26static int mime_global_eol(lua_State *L);
27static int mime_global_dot(lua_State *L);
28
29static size_t dot(int c, size_t state, luaL_Buffer *buffer);
30/*static void b64setup(UC *base);*/
31static size_t b64encode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
32static size_t b64pad(const UC *input, size_t size, luaL_Buffer *buffer);
33static size_t b64decode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
34
35/*static void qpsetup(UC *class, UC *unbase);*/
36static void qpquote(UC c, luaL_Buffer *buffer);
37static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer);
38static size_t qpencode(UC c, UC *input, size_t size,
39 const char *marker, luaL_Buffer *buffer);
40static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer);
41
42/* code support functions */
43static luaL_Reg func[] = {
44 { "dot", mime_global_dot },
45 { "b64", mime_global_b64 },
46 { "eol", mime_global_eol },
47 { "qp", mime_global_qp },
48 { "qpwrp", mime_global_qpwrp },
49 { "unb64", mime_global_unb64 },
50 { "unqp", mime_global_unqp },
51 { "wrp", mime_global_wrp },
52 { NULL, NULL }
53};
54
55/*-------------------------------------------------------------------------*\
56* Quoted-printable globals
57\*-------------------------------------------------------------------------*/
58enum {QP_PLAIN, QP_QUOTED, QP_CR, QP_IF_LAST};
59
60static const UC qpclass[] = {
61 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
62 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_IF_LAST, QP_QUOTED, QP_QUOTED,
63 QP_QUOTED, QP_CR, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
64 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
65 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
66 QP_QUOTED, QP_QUOTED, QP_IF_LAST, QP_PLAIN, QP_PLAIN, QP_PLAIN,
67 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
68 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
69 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
70 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
71 QP_PLAIN, QP_QUOTED, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
72 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
73 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
74 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
75 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
76 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
77 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
78 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
79 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
80 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
81 QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN, QP_PLAIN,
82 QP_PLAIN, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
83 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
84 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
85 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
86 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
87 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
88 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
89 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
90 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
91 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
92 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
93 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
94 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
95 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
96 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
97 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
98 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
99 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
100 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
101 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
102 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED,
103 QP_QUOTED, QP_QUOTED, QP_QUOTED, QP_QUOTED
104};
105
106static const UC qpbase[] = "0123456789ABCDEF";
107
108static const UC qpunbase[] = {
109 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
110 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
111 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
112 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
113 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255,
114 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15,
115 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
116 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
117 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 255, 255,
118 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
119 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
120 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
121 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
122 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
123 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
124 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
125 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
126 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
127 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
128 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
129 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
130 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
131 255, 255, 255, 255, 255, 255, 255, 255
132};
133
134/*-------------------------------------------------------------------------*\
135* Base64 globals
136\*-------------------------------------------------------------------------*/
137static const UC b64base[] =
138 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
139
140static const UC b64unbase[] = {
141 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
142 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
143 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
144 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
145 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 0,
146 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
147 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255,
148 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
149 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
150 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
151 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
152 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
153 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
154 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
155 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
156 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
157 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
158 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
159 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
160 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
161 255, 255
162};
163
164/*=========================================================================*\
165* Exported functions
166\*=========================================================================*/
167/*-------------------------------------------------------------------------*\
168* Initializes module
169\*-------------------------------------------------------------------------*/
170LUASOCKET_API int luaopen_mime_core(lua_State *L)
171{
172 lua_newtable(L);
173 luaL_setfuncs(L, func, 0);
174 /* make version string available to scripts */
175 lua_pushstring(L, "_VERSION");
176 lua_pushstring(L, MIME_VERSION);
177 lua_rawset(L, -3);
178 /* initialize lookup tables */
179 /*qpsetup(qpclass, qpunbase);*/
180 /*b64setup(b64unbase);*/
181 return 1;
182}
183
184/*=========================================================================*\
185* Global Lua functions
186\*=========================================================================*/
187/*-------------------------------------------------------------------------*\
188* Incrementaly breaks a string into lines. The string can have CRLF breaks.
189* A, n = wrp(l, B, length)
190* A is a copy of B, broken into lines of at most 'length' bytes.
191* 'l' is how many bytes are left for the first line of B.
192* 'n' is the number of bytes left in the last line of A.
193\*-------------------------------------------------------------------------*/
194static int mime_global_wrp(lua_State *L)
195{
196 size_t size = 0;
197 int left = (int) luaL_checknumber(L, 1);
198 const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size);
199 const UC *last = input + size;
200 int length = (int) luaL_optnumber(L, 3, 76);
201 luaL_Buffer buffer;
202 /* end of input black-hole */
203 if (!input) {
204 /* if last line has not been terminated, add a line break */
205 if (left < length) lua_pushstring(L, CRLF);
206 /* otherwise, we are done */
207 else lua_pushnil(L);
208 lua_pushnumber(L, length);
209 return 2;
210 }
211 luaL_buffinit(L, &buffer);
212 while (input < last) {
213 switch (*input) {
214 case '\r':
215 break;
216 case '\n':
217 luaL_addstring(&buffer, CRLF);
218 left = length;
219 break;
220 default:
221 if (left <= 0) {
222 left = length;
223 luaL_addstring(&buffer, CRLF);
224 }
225 luaL_addchar(&buffer, *input);
226 left--;
227 break;
228 }
229 input++;
230 }
231 luaL_pushresult(&buffer);
232 lua_pushnumber(L, left);
233 return 2;
234}
235
236#if 0
237/*-------------------------------------------------------------------------*\
238* Fill base64 decode map.
239\*-------------------------------------------------------------------------*/
240static void b64setup(UC *unbase)
241{
242 int i;
243 for (i = 0; i <= 255; i++) unbase[i] = (UC) 255;
244 for (i = 0; i < 64; i++) unbase[b64base[i]] = (UC) i;
245 unbase['='] = 0;
246
247 printf("static const UC b64unbase[] = {\n");
248 for (int i = 0; i < 256; i++) {
249 printf("%d, ", unbase[i]);
250 }
251 printf("\n}\n;");
252}
253#endif
254
255/*-------------------------------------------------------------------------*\
256* Acumulates bytes in input buffer until 3 bytes are available.
257* Translate the 3 bytes into Base64 form and append to buffer.
258* Returns new number of bytes in buffer.
259\*-------------------------------------------------------------------------*/
260static size_t b64encode(UC c, UC *input, size_t size,
261 luaL_Buffer *buffer)
262{
263 input[size++] = c;
264 if (size == 3) {
265 UC code[4];
266 unsigned long value = 0;
267 value += input[0]; value <<= 8;
268 value += input[1]; value <<= 8;
269 value += input[2];
270 code[3] = b64base[value & 0x3f]; value >>= 6;
271 code[2] = b64base[value & 0x3f]; value >>= 6;
272 code[1] = b64base[value & 0x3f]; value >>= 6;
273 code[0] = b64base[value];
274 luaL_addlstring(buffer, (char *) code, 4);
275 size = 0;
276 }
277 return size;
278}
279
280/*-------------------------------------------------------------------------*\
281* Encodes the Base64 last 1 or 2 bytes and adds padding '='
282* Result, if any, is appended to buffer.
283* Returns 0.
284\*-------------------------------------------------------------------------*/
285static size_t b64pad(const UC *input, size_t size,
286 luaL_Buffer *buffer)
287{
288 unsigned long value = 0;
289 UC code[4] = {'=', '=', '=', '='};
290 switch (size) {
291 case 1:
292 value = input[0] << 4;
293 code[1] = b64base[value & 0x3f]; value >>= 6;
294 code[0] = b64base[value];
295 luaL_addlstring(buffer, (char *) code, 4);
296 break;
297 case 2:
298 value = input[0]; value <<= 8;
299 value |= input[1]; value <<= 2;
300 code[2] = b64base[value & 0x3f]; value >>= 6;
301 code[1] = b64base[value & 0x3f]; value >>= 6;
302 code[0] = b64base[value];
303 luaL_addlstring(buffer, (char *) code, 4);
304 break;
305 default:
306 break;
307 }
308 return 0;
309}
310
311/*-------------------------------------------------------------------------*\
312* Acumulates bytes in input buffer until 4 bytes are available.
313* Translate the 4 bytes from Base64 form and append to buffer.
314* Returns new number of bytes in buffer.
315\*-------------------------------------------------------------------------*/
316static size_t b64decode(UC c, UC *input, size_t size,
317 luaL_Buffer *buffer)
318{
319 /* ignore invalid characters */
320 if (b64unbase[c] > 64) return size;
321 input[size++] = c;
322 /* decode atom */
323 if (size == 4) {
324 UC decoded[3];
325 int valid, value = 0;
326 value = b64unbase[input[0]]; value <<= 6;
327 value |= b64unbase[input[1]]; value <<= 6;
328 value |= b64unbase[input[2]]; value <<= 6;
329 value |= b64unbase[input[3]];
330 decoded[2] = (UC) (value & 0xff); value >>= 8;
331 decoded[1] = (UC) (value & 0xff); value >>= 8;
332 decoded[0] = (UC) value;
333 /* take care of paddding */
334 valid = (input[2] == '=') ? 1 : (input[3] == '=') ? 2 : 3;
335 luaL_addlstring(buffer, (char *) decoded, valid);
336 return 0;
337 /* need more data */
338 } else return size;
339}
340
341/*-------------------------------------------------------------------------*\
342* Incrementally applies the Base64 transfer content encoding to a string
343* A, B = b64(C, D)
344* A is the encoded version of the largest prefix of C .. D that is
345* divisible by 3. B has the remaining bytes of C .. D, *without* encoding.
346* The easiest thing would be to concatenate the two strings and
347* encode the result, but we can't afford that or Lua would dupplicate
348* every chunk we received.
349\*-------------------------------------------------------------------------*/
350static int mime_global_b64(lua_State *L)
351{
352 UC atom[3];
353 size_t isize = 0, asize = 0;
354 const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
355 const UC *last = input + isize;
356 luaL_Buffer buffer;
357 /* end-of-input blackhole */
358 if (!input) {
359 lua_pushnil(L);
360 lua_pushnil(L);
361 return 2;
362 }
363 /* make sure we don't confuse buffer stuff with arguments */
364 lua_settop(L, 2);
365 /* process first part of the input */
366 luaL_buffinit(L, &buffer);
367 while (input < last)
368 asize = b64encode(*input++, atom, asize, &buffer);
369 input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
370 /* if second part is nil, we are done */
371 if (!input) {
372 size_t osize = 0;
373 asize = b64pad(atom, asize, &buffer);
374 luaL_pushresult(&buffer);
375 /* if the output is empty and the input is nil, return nil */
376 lua_tolstring(L, -1, &osize);
377 if (osize == 0) lua_pushnil(L);
378 lua_pushnil(L);
379 return 2;
380 }
381 /* otherwise process the second part */
382 last = input + isize;
383 while (input < last)
384 asize = b64encode(*input++, atom, asize, &buffer);
385 luaL_pushresult(&buffer);
386 lua_pushlstring(L, (char *) atom, asize);
387 return 2;
388}
389
390/*-------------------------------------------------------------------------*\
391* Incrementally removes the Base64 transfer content encoding from a string
392* A, B = b64(C, D)
393* A is the encoded version of the largest prefix of C .. D that is
394* divisible by 4. B has the remaining bytes of C .. D, *without* encoding.
395\*-------------------------------------------------------------------------*/
396static int mime_global_unb64(lua_State *L)
397{
398 UC atom[4];
399 size_t isize = 0, asize = 0;
400 const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
401 const UC *last = input + isize;
402 luaL_Buffer buffer;
403 /* end-of-input blackhole */
404 if (!input) {
405 lua_pushnil(L);
406 lua_pushnil(L);
407 return 2;
408 }
409 /* make sure we don't confuse buffer stuff with arguments */
410 lua_settop(L, 2);
411 /* process first part of the input */
412 luaL_buffinit(L, &buffer);
413 while (input < last)
414 asize = b64decode(*input++, atom, asize, &buffer);
415 input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
416 /* if second is nil, we are done */
417 if (!input) {
418 size_t osize = 0;
419 luaL_pushresult(&buffer);
420 /* if the output is empty and the input is nil, return nil */
421 lua_tolstring(L, -1, &osize);
422 if (osize == 0) lua_pushnil(L);
423 lua_pushnil(L);
424 return 2;
425 }
426 /* otherwise, process the rest of the input */
427 last = input + isize;
428 while (input < last)
429 asize = b64decode(*input++, atom, asize, &buffer);
430 luaL_pushresult(&buffer);
431 lua_pushlstring(L, (char *) atom, asize);
432 return 2;
433}
434
435/*-------------------------------------------------------------------------*\
436* Quoted-printable encoding scheme
437* all (except CRLF in text) can be =XX
438* CLRL in not text must be =XX=XX
439* 33 through 60 inclusive can be plain
440* 62 through 126 inclusive can be plain
441* 9 and 32 can be plain, unless in the end of a line, where must be =XX
442* encoded lines must be no longer than 76 not counting CRLF
443* soft line-break are =CRLF
444* To encode one byte, we need to see the next two.
445* Worst case is when we see a space, and wonder if a CRLF is comming
446\*-------------------------------------------------------------------------*/
447#if 0
448/*-------------------------------------------------------------------------*\
449* Split quoted-printable characters into classes
450* Precompute reverse map for encoding
451\*-------------------------------------------------------------------------*/
452static void qpsetup(UC *cl, UC *unbase)
453{
454
455 int i;
456 for (i = 0; i < 256; i++) cl[i] = QP_QUOTED;
457 for (i = 33; i <= 60; i++) cl[i] = QP_PLAIN;
458 for (i = 62; i <= 126; i++) cl[i] = QP_PLAIN;
459 cl['\t'] = QP_IF_LAST;
460 cl[' '] = QP_IF_LAST;
461 cl['\r'] = QP_CR;
462 for (i = 0; i < 256; i++) unbase[i] = 255;
463 unbase['0'] = 0; unbase['1'] = 1; unbase['2'] = 2;
464 unbase['3'] = 3; unbase['4'] = 4; unbase['5'] = 5;
465 unbase['6'] = 6; unbase['7'] = 7; unbase['8'] = 8;
466 unbase['9'] = 9; unbase['A'] = 10; unbase['a'] = 10;
467 unbase['B'] = 11; unbase['b'] = 11; unbase['C'] = 12;
468 unbase['c'] = 12; unbase['D'] = 13; unbase['d'] = 13;
469 unbase['E'] = 14; unbase['e'] = 14; unbase['F'] = 15;
470 unbase['f'] = 15;
471
472printf("static UC qpclass[] = {");
473 for (int i = 0; i < 256; i++) {
474 if (i % 6 == 0) {
475 printf("\n ");
476 }
477 switch(cl[i]) {
478 case QP_QUOTED:
479 printf("QP_QUOTED, ");
480 break;
481 case QP_PLAIN:
482 printf("QP_PLAIN, ");
483 break;
484 case QP_CR:
485 printf("QP_CR, ");
486 break;
487 case QP_IF_LAST:
488 printf("QP_IF_LAST, ");
489 break;
490 }
491 }
492printf("\n};\n");
493
494printf("static const UC qpunbase[] = {");
495 for (int i = 0; i < 256; i++) {
496 int c = qpunbase[i];
497 printf("%d, ", c);
498 }
499printf("\";\n");
500}
501#endif
502
503/*-------------------------------------------------------------------------*\
504* Output one character in form =XX
505\*-------------------------------------------------------------------------*/
506static void qpquote(UC c, luaL_Buffer *buffer)
507{
508 luaL_addchar(buffer, '=');
509 luaL_addchar(buffer, qpbase[c >> 4]);
510 luaL_addchar(buffer, qpbase[c & 0x0F]);
511}
512
513/*-------------------------------------------------------------------------*\
514* Accumulate characters until we are sure about how to deal with them.
515* Once we are sure, output to the buffer, in the correct form.
516\*-------------------------------------------------------------------------*/
517static size_t qpencode(UC c, UC *input, size_t size,
518 const char *marker, luaL_Buffer *buffer)
519{
520 input[size++] = c;
521 /* deal with all characters we can have */
522 while (size > 0) {
523 switch (qpclass[input[0]]) {
524 /* might be the CR of a CRLF sequence */
525 case QP_CR:
526 if (size < 2) return size;
527 if (input[1] == '\n') {
528 luaL_addstring(buffer, marker);
529 return 0;
530 } else qpquote(input[0], buffer);
531 break;
532 /* might be a space and that has to be quoted if last in line */
533 case QP_IF_LAST:
534 if (size < 3) return size;
535 /* if it is the last, quote it and we are done */
536 if (input[1] == '\r' && input[2] == '\n') {
537 qpquote(input[0], buffer);
538 luaL_addstring(buffer, marker);
539 return 0;
540 } else luaL_addchar(buffer, input[0]);
541 break;
542 /* might have to be quoted always */
543 case QP_QUOTED:
544 qpquote(input[0], buffer);
545 break;
546 /* might never have to be quoted */
547 default:
548 luaL_addchar(buffer, input[0]);
549 break;
550 }
551 input[0] = input[1]; input[1] = input[2];
552 size--;
553 }
554 return 0;
555}
556
557/*-------------------------------------------------------------------------*\
558* Deal with the final characters
559\*-------------------------------------------------------------------------*/
560static size_t qppad(UC *input, size_t size, luaL_Buffer *buffer)
561{
562 size_t i;
563 for (i = 0; i < size; i++) {
564 if (qpclass[input[i]] == QP_PLAIN) luaL_addchar(buffer, input[i]);
565 else qpquote(input[i], buffer);
566 }
567 if (size > 0) luaL_addstring(buffer, EQCRLF);
568 return 0;
569}
570
571/*-------------------------------------------------------------------------*\
572* Incrementally converts a string to quoted-printable
573* A, B = qp(C, D, marker)
574* Marker is the text to be used to replace CRLF sequences found in A.
575* A is the encoded version of the largest prefix of C .. D that
576* can be encoded without doubts.
577* B has the remaining bytes of C .. D, *without* encoding.
578\*-------------------------------------------------------------------------*/
579static int mime_global_qp(lua_State *L)
580{
581 size_t asize = 0, isize = 0;
582 UC atom[3];
583 const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
584 const UC *last = input + isize;
585 const char *marker = luaL_optstring(L, 3, CRLF);
586 luaL_Buffer buffer;
587 /* end-of-input blackhole */
588 if (!input) {
589 lua_pushnil(L);
590 lua_pushnil(L);
591 return 2;
592 }
593 /* make sure we don't confuse buffer stuff with arguments */
594 lua_settop(L, 3);
595 /* process first part of input */
596 luaL_buffinit(L, &buffer);
597 while (input < last)
598 asize = qpencode(*input++, atom, asize, marker, &buffer);
599 input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
600 /* if second part is nil, we are done */
601 if (!input) {
602 asize = qppad(atom, asize, &buffer);
603 luaL_pushresult(&buffer);
604 if (!(*lua_tostring(L, -1))) lua_pushnil(L);
605 lua_pushnil(L);
606 return 2;
607 }
608 /* otherwise process rest of input */
609 last = input + isize;
610 while (input < last)
611 asize = qpencode(*input++, atom, asize, marker, &buffer);
612 luaL_pushresult(&buffer);
613 lua_pushlstring(L, (char *) atom, asize);
614 return 2;
615}
616
617/*-------------------------------------------------------------------------*\
618* Accumulate characters until we are sure about how to deal with them.
619* Once we are sure, output the to the buffer, in the correct form.
620\*-------------------------------------------------------------------------*/
621static size_t qpdecode(UC c, UC *input, size_t size, luaL_Buffer *buffer) {
622 int d;
623 input[size++] = c;
624 /* deal with all characters we can deal */
625 switch (input[0]) {
626 /* if we have an escape character */
627 case '=':
628 if (size < 3) return size;
629 /* eliminate soft line break */
630 if (input[1] == '\r' && input[2] == '\n') return 0;
631 /* decode quoted representation */
632 c = qpunbase[input[1]]; d = qpunbase[input[2]];
633 /* if it is an invalid, do not decode */
634 if (c > 15 || d > 15) luaL_addlstring(buffer, (char *)input, 3);
635 else luaL_addchar(buffer, (char) ((c << 4) + d));
636 return 0;
637 case '\r':
638 if (size < 2) return size;
639 if (input[1] == '\n') luaL_addlstring(buffer, (char *)input, 2);
640 return 0;
641 default:
642 if (input[0] == '\t' || (input[0] > 31 && input[0] < 127))
643 luaL_addchar(buffer, input[0]);
644 return 0;
645 }
646}
647
648/*-------------------------------------------------------------------------*\
649* Incrementally decodes a string in quoted-printable
650* A, B = qp(C, D)
651* A is the decoded version of the largest prefix of C .. D that
652* can be decoded without doubts.
653* B has the remaining bytes of C .. D, *without* decoding.
654\*-------------------------------------------------------------------------*/
655static int mime_global_unqp(lua_State *L)
656{
657 size_t asize = 0, isize = 0;
658 UC atom[3];
659 const UC *input = (const UC *) luaL_optlstring(L, 1, NULL, &isize);
660 const UC *last = input + isize;
661 luaL_Buffer buffer;
662 /* end-of-input blackhole */
663 if (!input) {
664 lua_pushnil(L);
665 lua_pushnil(L);
666 return 2;
667 }
668 /* make sure we don't confuse buffer stuff with arguments */
669 lua_settop(L, 2);
670 /* process first part of input */
671 luaL_buffinit(L, &buffer);
672 while (input < last)
673 asize = qpdecode(*input++, atom, asize, &buffer);
674 input = (const UC *) luaL_optlstring(L, 2, NULL, &isize);
675 /* if second part is nil, we are done */
676 if (!input) {
677 luaL_pushresult(&buffer);
678 if (!(*lua_tostring(L, -1))) lua_pushnil(L);
679 lua_pushnil(L);
680 return 2;
681 }
682 /* otherwise process rest of input */
683 last = input + isize;
684 while (input < last)
685 asize = qpdecode(*input++, atom, asize, &buffer);
686 luaL_pushresult(&buffer);
687 lua_pushlstring(L, (char *) atom, asize);
688 return 2;
689}
690
691/*-------------------------------------------------------------------------*\
692* Incrementally breaks a quoted-printed string into lines
693* A, n = qpwrp(l, B, length)
694* A is a copy of B, broken into lines of at most 'length' bytes.
695* 'l' is how many bytes are left for the first line of B.
696* 'n' is the number of bytes left in the last line of A.
697* There are two complications: lines can't be broken in the middle
698* of an encoded =XX, and there might be line breaks already
699\*-------------------------------------------------------------------------*/
700static int mime_global_qpwrp(lua_State *L)
701{
702 size_t size = 0;
703 int left = (int) luaL_checknumber(L, 1);
704 const UC *input = (const UC *) luaL_optlstring(L, 2, NULL, &size);
705 const UC *last = input + size;
706 int length = (int) luaL_optnumber(L, 3, 76);
707 luaL_Buffer buffer;
708 /* end-of-input blackhole */
709 if (!input) {
710 if (left < length) lua_pushstring(L, EQCRLF);
711 else lua_pushnil(L);
712 lua_pushnumber(L, length);
713 return 2;
714 }
715 /* process all input */
716 luaL_buffinit(L, &buffer);
717 while (input < last) {
718 switch (*input) {
719 case '\r':
720 break;
721 case '\n':
722 left = length;
723 luaL_addstring(&buffer, CRLF);
724 break;
725 case '=':
726 if (left <= 3) {
727 left = length;
728 luaL_addstring(&buffer, EQCRLF);
729 }
730 luaL_addchar(&buffer, *input);
731 left--;
732 break;
733 default:
734 if (left <= 1) {
735 left = length;
736 luaL_addstring(&buffer, EQCRLF);
737 }
738 luaL_addchar(&buffer, *input);
739 left--;
740 break;
741 }
742 input++;
743 }
744 luaL_pushresult(&buffer);
745 lua_pushnumber(L, left);
746 return 2;
747}
748
749/*-------------------------------------------------------------------------*\
750* Here is what we do: \n, and \r are considered candidates for line
751* break. We issue *one* new line marker if any of them is seen alone, or
752* followed by a different one. That is, \n\n and \r\r will issue two
753* end of line markers each, but \r\n, \n\r etc will only issue *one*
754* marker. This covers Mac OS, Mac OS X, VMS, Unix and DOS, as well as
755* probably other more obscure conventions.
756*
757* c is the current character being processed
758* last is the previous character
759\*-------------------------------------------------------------------------*/
760#define eolcandidate(c) (c == '\r' || c == '\n')
761static int eolprocess(int c, int last, const char *marker,
762 luaL_Buffer *buffer)
763{
764 if (eolcandidate(c)) {
765 if (eolcandidate(last)) {
766 if (c == last) luaL_addstring(buffer, marker);
767 return 0;
768 } else {
769 luaL_addstring(buffer, marker);
770 return c;
771 }
772 } else {
773 luaL_addchar(buffer, (char) c);
774 return 0;
775 }
776}
777
778/*-------------------------------------------------------------------------*\
779* Converts a string to uniform EOL convention.
780* A, n = eol(o, B, marker)
781* A is the converted version of the largest prefix of B that can be
782* converted unambiguously. 'o' is the context returned by the previous
783* call. 'n' is the new context.
784\*-------------------------------------------------------------------------*/
785static int mime_global_eol(lua_State *L)
786{
787 int ctx = (int) luaL_checkinteger(L, 1);
788 size_t isize = 0;
789 const char *input = luaL_optlstring(L, 2, NULL, &isize);
790 const char *last = input + isize;
791 const char *marker = luaL_optstring(L, 3, CRLF);
792 luaL_Buffer buffer;
793 luaL_buffinit(L, &buffer);
794 /* end of input blackhole */
795 if (!input) {
796 lua_pushnil(L);
797 lua_pushnumber(L, 0);
798 return 2;
799 }
800 /* process all input */
801 while (input < last)
802 ctx = eolprocess(*input++, ctx, marker, &buffer);
803 luaL_pushresult(&buffer);
804 lua_pushnumber(L, ctx);
805 return 2;
806}
807
808/*-------------------------------------------------------------------------*\
809* Takes one byte and stuff it if needed.
810\*-------------------------------------------------------------------------*/
811static size_t dot(int c, size_t state, luaL_Buffer *buffer)
812{
813 luaL_addchar(buffer, (char) c);
814 switch (c) {
815 case '\r':
816 return 1;
817 case '\n':
818 return (state == 1)? 2: 0;
819 case '.':
820 if (state == 2)
821 luaL_addchar(buffer, '.');
822 /* Falls through. */
823 default:
824 return 0;
825 }
826}
827
828/*-------------------------------------------------------------------------*\
829* Incrementally applies smtp stuffing to a string
830* A, n = dot(l, D)
831\*-------------------------------------------------------------------------*/
832static int mime_global_dot(lua_State *L)
833{
834 size_t isize = 0, state = (size_t) luaL_checknumber(L, 1);
835 const char *input = luaL_optlstring(L, 2, NULL, &isize);
836 const char *last = input + isize;
837 luaL_Buffer buffer;
838 /* end-of-input blackhole */
839 if (!input) {
840 lua_pushnil(L);
841 lua_pushnumber(L, 2);
842 return 2;
843 }
844 /* process all input */
845 luaL_buffinit(L, &buffer);
846 while (input < last)
847 state = dot(*input++, state, &buffer);
848 luaL_pushresult(&buffer);
849 lua_pushnumber(L, (lua_Number) state);
850 return 2;
851}
852
diff --git a/vendor/luasocket/src/mime.h b/vendor/luasocket/src/mime.h
new file mode 100644
index 00000000..4d938f46
--- /dev/null
+++ b/vendor/luasocket/src/mime.h
@@ -0,0 +1,22 @@
1#ifndef MIME_H
2#define MIME_H
3/*=========================================================================*\
4* Core MIME support
5* LuaSocket toolkit
6*
7* This module provides functions to implement transfer content encodings
8* and formatting conforming to RFC 2045. It is used by mime.lua, which
9* provide a higher level interface to this functionality.
10\*=========================================================================*/
11#include "luasocket.h"
12
13/*-------------------------------------------------------------------------*\
14* Current MIME library version
15\*-------------------------------------------------------------------------*/
16#define MIME_VERSION "MIME 1.0.3"
17#define MIME_COPYRIGHT "Copyright (C) 2004-2013 Diego Nehab"
18#define MIME_AUTHORS "Diego Nehab"
19
20LUASOCKET_API int luaopen_mime_core(lua_State *L);
21
22#endif /* MIME_H */
diff --git a/vendor/luasocket/src/mime.lua b/vendor/luasocket/src/mime.lua
new file mode 100644
index 00000000..93539de6
--- /dev/null
+++ b/vendor/luasocket/src/mime.lua
@@ -0,0 +1,81 @@
1-----------------------------------------------------------------------------
2-- MIME support for the Lua language.
3-- Author: Diego Nehab
4-- Conforming to RFCs 2045-2049
5-----------------------------------------------------------------------------
6
7-----------------------------------------------------------------------------
8-- Declare module and import dependencies
9-----------------------------------------------------------------------------
10local base = _G
11local ltn12 = require("ltn12")
12local mime = require("mime.core")
13local _M = mime
14
15-- encode, decode and wrap algorithm tables
16local encodet, decodet, wrapt = {},{},{}
17
18_M.encodet = encodet
19_M.decodet = decodet
20_M.wrapt = wrapt
21
22-- creates a function that chooses a filter by name from a given table
23local function choose(table)
24 return function(name, opt1, opt2)
25 if base.type(name) ~= "string" then
26 name, opt1, opt2 = "default", name, opt1
27 end
28 local f = table[name or "nil"]
29 if not f then
30 base.error("unknown key (" .. base.tostring(name) .. ")", 3)
31 else return f(opt1, opt2) end
32 end
33end
34
35-- define the encoding filters
36encodet['base64'] = function()
37 return ltn12.filter.cycle(_M.b64, "")
38end
39
40encodet['quoted-printable'] = function(mode)
41 return ltn12.filter.cycle(_M.qp, "",
42 (mode == "binary") and "=0D=0A" or "\r\n")
43end
44
45-- define the decoding filters
46decodet['base64'] = function()
47 return ltn12.filter.cycle(_M.unb64, "")
48end
49
50decodet['quoted-printable'] = function()
51 return ltn12.filter.cycle(_M.unqp, "")
52end
53
54-- define the line-wrap filters
55wrapt['text'] = function(length)
56 length = length or 76
57 return ltn12.filter.cycle(_M.wrp, length, length)
58end
59wrapt['base64'] = wrapt['text']
60wrapt['default'] = wrapt['text']
61
62wrapt['quoted-printable'] = function()
63 return ltn12.filter.cycle(_M.qpwrp, 76, 76)
64end
65
66-- function that choose the encoding, decoding or wrap algorithm
67_M.encode = choose(encodet)
68_M.decode = choose(decodet)
69_M.wrap = choose(wrapt)
70
71-- define the end-of-line normalization filter
72function _M.normalize(marker)
73 return ltn12.filter.cycle(_M.eol, 0, marker)
74end
75
76-- high level stuffing filter
77function _M.stuff()
78 return ltn12.filter.cycle(_M.dot, 2)
79end
80
81return _M
diff --git a/vendor/luasocket/src/options.c b/vendor/luasocket/src/options.c
new file mode 100644
index 00000000..3280c51d
--- /dev/null
+++ b/vendor/luasocket/src/options.c
@@ -0,0 +1,480 @@
1/*=========================================================================*\
2* Common option interface
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6#include "auxiliar.h"
7#include "options.h"
8#include "inet.h"
9#include <string.h>
10
11/*=========================================================================*\
12* Internal functions prototypes
13\*=========================================================================*/
14static int opt_setmembership(lua_State *L, p_socket ps, int level, int name);
15static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name);
16static int opt_setboolean(lua_State *L, p_socket ps, int level, int name);
17static int opt_getboolean(lua_State *L, p_socket ps, int level, int name);
18static int opt_setint(lua_State *L, p_socket ps, int level, int name);
19static int opt_getint(lua_State *L, p_socket ps, int level, int name);
20static int opt_set(lua_State *L, p_socket ps, int level, int name,
21 void *val, int len);
22static int opt_get(lua_State *L, p_socket ps, int level, int name,
23 void *val, int* len);
24
25/*=========================================================================*\
26* Exported functions
27\*=========================================================================*/
28/*-------------------------------------------------------------------------*\
29* Calls appropriate option handler
30\*-------------------------------------------------------------------------*/
31int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps)
32{
33 const char *name = luaL_checkstring(L, 2); /* obj, name, ... */
34 while (opt->name && strcmp(name, opt->name))
35 opt++;
36 if (!opt->func) {
37 char msg[57];
38 sprintf(msg, "unsupported option `%.35s'", name);
39 luaL_argerror(L, 2, msg);
40 }
41 return opt->func(L, ps);
42}
43
44int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps)
45{
46 const char *name = luaL_checkstring(L, 2); /* obj, name, ... */
47 while (opt->name && strcmp(name, opt->name))
48 opt++;
49 if (!opt->func) {
50 char msg[57];
51 sprintf(msg, "unsupported option `%.35s'", name);
52 luaL_argerror(L, 2, msg);
53 }
54 return opt->func(L, ps);
55}
56
57/*------------------------------------------------------*/
58/* enables reuse of local address */
59int opt_set_reuseaddr(lua_State *L, p_socket ps)
60{
61 return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
62}
63
64int opt_get_reuseaddr(lua_State *L, p_socket ps)
65{
66 return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
67}
68
69/*------------------------------------------------------*/
70/* enables reuse of local port */
71int opt_set_reuseport(lua_State *L, p_socket ps)
72{
73 return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
74}
75
76int opt_get_reuseport(lua_State *L, p_socket ps)
77{
78 return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
79}
80
81/*------------------------------------------------------*/
82/* disables the Nagle algorithm */
83int opt_set_tcp_nodelay(lua_State *L, p_socket ps)
84{
85 return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
86}
87
88int opt_get_tcp_nodelay(lua_State *L, p_socket ps)
89{
90 return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
91}
92
93/*------------------------------------------------------*/
94#ifdef TCP_KEEPIDLE
95
96int opt_get_tcp_keepidle(lua_State *L, p_socket ps)
97{
98 return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPIDLE);
99}
100
101int opt_set_tcp_keepidle(lua_State *L, p_socket ps)
102{
103 return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPIDLE);
104}
105
106#endif
107
108/*------------------------------------------------------*/
109#ifdef TCP_KEEPCNT
110
111int opt_get_tcp_keepcnt(lua_State *L, p_socket ps)
112{
113 return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPCNT);
114}
115
116int opt_set_tcp_keepcnt(lua_State *L, p_socket ps)
117{
118 return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPCNT);
119}
120
121#endif
122
123/*------------------------------------------------------*/
124#ifdef TCP_KEEPINTVL
125
126int opt_get_tcp_keepintvl(lua_State *L, p_socket ps)
127{
128 return opt_getint(L, ps, IPPROTO_TCP, TCP_KEEPINTVL);
129}
130
131int opt_set_tcp_keepintvl(lua_State *L, p_socket ps)
132{
133 return opt_setint(L, ps, IPPROTO_TCP, TCP_KEEPINTVL);
134}
135
136#endif
137
138/*------------------------------------------------------*/
139int opt_set_keepalive(lua_State *L, p_socket ps)
140{
141 return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
142}
143
144int opt_get_keepalive(lua_State *L, p_socket ps)
145{
146 return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
147}
148
149/*------------------------------------------------------*/
150int opt_set_dontroute(lua_State *L, p_socket ps)
151{
152 return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
153}
154
155int opt_get_dontroute(lua_State *L, p_socket ps)
156{
157 return opt_getboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
158}
159
160/*------------------------------------------------------*/
161int opt_set_broadcast(lua_State *L, p_socket ps)
162{
163 return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST);
164}
165
166int opt_get_broadcast(lua_State *L, p_socket ps)
167{
168 return opt_getboolean(L, ps, SOL_SOCKET, SO_BROADCAST);
169}
170
171/*------------------------------------------------------*/
172int opt_set_recv_buf_size(lua_State *L, p_socket ps)
173{
174 return opt_setint(L, ps, SOL_SOCKET, SO_RCVBUF);
175}
176
177int opt_get_recv_buf_size(lua_State *L, p_socket ps)
178{
179 return opt_getint(L, ps, SOL_SOCKET, SO_RCVBUF);
180}
181
182/*------------------------------------------------------*/
183int opt_get_send_buf_size(lua_State *L, p_socket ps)
184{
185 return opt_getint(L, ps, SOL_SOCKET, SO_SNDBUF);
186}
187
188int opt_set_send_buf_size(lua_State *L, p_socket ps)
189{
190 return opt_setint(L, ps, SOL_SOCKET, SO_SNDBUF);
191}
192
193// /*------------------------------------------------------*/
194
195#ifdef TCP_FASTOPEN
196int opt_set_tcp_fastopen(lua_State *L, p_socket ps)
197{
198 return opt_setint(L, ps, IPPROTO_TCP, TCP_FASTOPEN);
199}
200#endif
201
202#ifdef TCP_FASTOPEN_CONNECT
203int opt_set_tcp_fastopen_connect(lua_State *L, p_socket ps)
204{
205 return opt_setint(L, ps, IPPROTO_TCP, TCP_FASTOPEN_CONNECT);
206}
207#endif
208
209/*------------------------------------------------------*/
210
211#ifdef TCP_DEFER_ACCEPT
212int opt_set_tcp_defer_accept(lua_State *L, p_socket ps)
213{
214 return opt_setint(L, ps, IPPROTO_TCP, TCP_DEFER_ACCEPT);
215}
216#endif
217
218/*------------------------------------------------------*/
219int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps)
220{
221 return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS);
222}
223
224int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps)
225{
226 return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS);
227}
228
229/*------------------------------------------------------*/
230int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps)
231{
232 return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
233}
234
235int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps)
236{
237 return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
238}
239
240/*------------------------------------------------------*/
241int opt_set_ip_multicast_loop(lua_State *L, p_socket ps)
242{
243 return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP);
244}
245
246int opt_get_ip_multicast_loop(lua_State *L, p_socket ps)
247{
248 return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP);
249}
250
251/*------------------------------------------------------*/
252int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps)
253{
254 return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP);
255}
256
257int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps)
258{
259 return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP);
260}
261
262/*------------------------------------------------------*/
263int opt_set_linger(lua_State *L, p_socket ps)
264{
265 struct linger li; /* obj, name, table */
266 if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
267 lua_pushstring(L, "on");
268 lua_gettable(L, 3);
269 if (!lua_isboolean(L, -1))
270 luaL_argerror(L, 3, "boolean 'on' field expected");
271 li.l_onoff = (u_short) lua_toboolean(L, -1);
272 lua_pushstring(L, "timeout");
273 lua_gettable(L, 3);
274 if (!lua_isnumber(L, -1))
275 luaL_argerror(L, 3, "number 'timeout' field expected");
276 li.l_linger = (u_short) lua_tonumber(L, -1);
277 return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li));
278}
279
280int opt_get_linger(lua_State *L, p_socket ps)
281{
282 struct linger li; /* obj, name */
283 int len = sizeof(li);
284 int err = opt_get(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, &len);
285 if (err)
286 return err;
287 lua_newtable(L);
288 lua_pushboolean(L, li.l_onoff);
289 lua_setfield(L, -2, "on");
290 lua_pushinteger(L, li.l_linger);
291 lua_setfield(L, -2, "timeout");
292 return 1;
293}
294
295/*------------------------------------------------------*/
296int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps)
297{
298 return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL);
299}
300
301/*------------------------------------------------------*/
302int opt_set_ip_multicast_if(lua_State *L, p_socket ps)
303{
304 const char *address = luaL_checkstring(L, 3); /* obj, name, ip */
305 struct in_addr val;
306 val.s_addr = htonl(INADDR_ANY);
307 if (strcmp(address, "*") && !inet_aton(address, &val))
308 luaL_argerror(L, 3, "ip expected");
309 return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF,
310 (char *) &val, sizeof(val));
311}
312
313int opt_get_ip_multicast_if(lua_State *L, p_socket ps)
314{
315 struct in_addr val;
316 socklen_t len = sizeof(val);
317 if (getsockopt(*ps, IPPROTO_IP, IP_MULTICAST_IF, (char *) &val, &len) < 0) {
318 lua_pushnil(L);
319 lua_pushstring(L, "getsockopt failed");
320 return 2;
321 }
322 lua_pushstring(L, inet_ntoa(val));
323 return 1;
324}
325
326/*------------------------------------------------------*/
327int opt_set_ip_add_membership(lua_State *L, p_socket ps)
328{
329 return opt_setmembership(L, ps, IPPROTO_IP, IP_ADD_MEMBERSHIP);
330}
331
332int opt_set_ip_drop_membersip(lua_State *L, p_socket ps)
333{
334 return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP);
335}
336
337/*------------------------------------------------------*/
338int opt_set_ip6_add_membership(lua_State *L, p_socket ps)
339{
340 return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP);
341}
342
343int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps)
344{
345 return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP);
346}
347
348/*------------------------------------------------------*/
349int opt_get_ip6_v6only(lua_State *L, p_socket ps)
350{
351 return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY);
352}
353
354int opt_set_ip6_v6only(lua_State *L, p_socket ps)
355{
356 return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY);
357}
358
359/*------------------------------------------------------*/
360int opt_get_error(lua_State *L, p_socket ps)
361{
362 int val = 0;
363 socklen_t len = sizeof(val);
364 if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) {
365 lua_pushnil(L);
366 lua_pushstring(L, "getsockopt failed");
367 return 2;
368 }
369 lua_pushstring(L, socket_strerror(val));
370 return 1;
371}
372
373/*=========================================================================*\
374* Auxiliar functions
375\*=========================================================================*/
376static int opt_setmembership(lua_State *L, p_socket ps, int level, int name)
377{
378 struct ip_mreq val; /* obj, name, table */
379 if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
380 lua_pushstring(L, "multiaddr");
381 lua_gettable(L, 3);
382 if (!lua_isstring(L, -1))
383 luaL_argerror(L, 3, "string 'multiaddr' field expected");
384 if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr))
385 luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
386 lua_pushstring(L, "interface");
387 lua_gettable(L, 3);
388 if (!lua_isstring(L, -1))
389 luaL_argerror(L, 3, "string 'interface' field expected");
390 val.imr_interface.s_addr = htonl(INADDR_ANY);
391 if (strcmp(lua_tostring(L, -1), "*") &&
392 !inet_aton(lua_tostring(L, -1), &val.imr_interface))
393 luaL_argerror(L, 3, "invalid 'interface' ip address");
394 return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
395}
396
397static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name)
398{
399 struct ipv6_mreq val; /* obj, opt-name, table */
400 memset(&val, 0, sizeof(val));
401 if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
402 lua_pushstring(L, "multiaddr");
403 lua_gettable(L, 3);
404 if (!lua_isstring(L, -1))
405 luaL_argerror(L, 3, "string 'multiaddr' field expected");
406 if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr))
407 luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
408 lua_pushstring(L, "interface");
409 lua_gettable(L, 3);
410 /* By default we listen to interface on default route
411 * (sigh). However, interface= can override it. We should
412 * support either number, or name for it. Waiting for
413 * windows port of if_nametoindex */
414 if (!lua_isnil(L, -1)) {
415 if (lua_isnumber(L, -1)) {
416 val.ipv6mr_interface = (unsigned int) lua_tonumber(L, -1);
417 } else
418 luaL_argerror(L, -1, "number 'interface' field expected");
419 }
420 return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
421}
422
423static
424int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
425{
426 socklen_t socklen = *len;
427 if (getsockopt(*ps, level, name, (char *) val, &socklen) < 0) {
428 lua_pushnil(L);
429 lua_pushstring(L, "getsockopt failed");
430 return 2;
431 }
432 *len = socklen;
433 return 0;
434}
435
436static
437int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
438{
439 if (setsockopt(*ps, level, name, (char *) val, len) < 0) {
440 lua_pushnil(L);
441 lua_pushstring(L, "setsockopt failed");
442 return 2;
443 }
444 lua_pushnumber(L, 1);
445 return 1;
446}
447
448static int opt_getboolean(lua_State *L, p_socket ps, int level, int name)
449{
450 int val = 0;
451 int len = sizeof(val);
452 int err = opt_get(L, ps, level, name, (char *) &val, &len);
453 if (err)
454 return err;
455 lua_pushboolean(L, val);
456 return 1;
457}
458
459static int opt_setboolean(lua_State *L, p_socket ps, int level, int name)
460{
461 int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */
462 return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
463}
464
465static int opt_getint(lua_State *L, p_socket ps, int level, int name)
466{
467 int val = 0;
468 int len = sizeof(val);
469 int err = opt_get(L, ps, level, name, (char *) &val, &len);
470 if (err)
471 return err;
472 lua_pushnumber(L, val);
473 return 1;
474}
475
476static int opt_setint(lua_State *L, p_socket ps, int level, int name)
477{
478 int val = (int) lua_tonumber(L, 3); /* obj, name, int */
479 return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
480}
diff --git a/vendor/luasocket/src/options.h b/vendor/luasocket/src/options.h
new file mode 100644
index 00000000..456eeb5f
--- /dev/null
+++ b/vendor/luasocket/src/options.h
@@ -0,0 +1,113 @@
1#ifndef OPTIONS_H
2#define OPTIONS_H
3/*=========================================================================*\
4* Common option interface
5* LuaSocket toolkit
6*
7* This module provides a common interface to socket options, used mainly by
8* modules UDP and TCP.
9\*=========================================================================*/
10
11#include "luasocket.h"
12#include "socket.h"
13
14/* option registry */
15typedef struct t_opt {
16 const char *name;
17 int (*func)(lua_State *L, p_socket ps);
18} t_opt;
19typedef t_opt *p_opt;
20
21#ifndef _WIN32
22#pragma GCC visibility push(hidden)
23#endif
24
25int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps);
26int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps);
27
28int opt_set_reuseaddr(lua_State *L, p_socket ps);
29int opt_get_reuseaddr(lua_State *L, p_socket ps);
30
31int opt_set_reuseport(lua_State *L, p_socket ps);
32int opt_get_reuseport(lua_State *L, p_socket ps);
33
34int opt_set_tcp_nodelay(lua_State *L, p_socket ps);
35int opt_get_tcp_nodelay(lua_State *L, p_socket ps);
36
37#ifdef TCP_KEEPIDLE
38int opt_set_tcp_keepidle(lua_State *L, p_socket ps);
39int opt_get_tcp_keepidle(lua_State *L, p_socket ps);
40#endif
41
42#ifdef TCP_KEEPCNT
43int opt_set_tcp_keepcnt(lua_State *L, p_socket ps);
44int opt_get_tcp_keepcnt(lua_State *L, p_socket ps);
45#endif
46
47#ifdef TCP_KEEPINTVL
48int opt_set_tcp_keepintvl(lua_State *L, p_socket ps);
49int opt_get_tcp_keepintvl(lua_State *L, p_socket ps);
50#endif
51
52#ifdef TCP_DEFER_ACCEPT
53int opt_set_tcp_defer_accept(lua_State *L, p_socket ps);
54#endif
55
56int opt_set_keepalive(lua_State *L, p_socket ps);
57int opt_get_keepalive(lua_State *L, p_socket ps);
58
59int opt_set_dontroute(lua_State *L, p_socket ps);
60int opt_get_dontroute(lua_State *L, p_socket ps);
61
62int opt_set_broadcast(lua_State *L, p_socket ps);
63int opt_get_broadcast(lua_State *L, p_socket ps);
64
65int opt_set_recv_buf_size(lua_State *L, p_socket ps);
66int opt_get_recv_buf_size(lua_State *L, p_socket ps);
67
68int opt_set_send_buf_size(lua_State *L, p_socket ps);
69int opt_get_send_buf_size(lua_State *L, p_socket ps);
70
71#ifdef TCP_FASTOPEN
72int opt_set_tcp_fastopen(lua_State *L, p_socket ps);
73#endif
74#ifdef TCP_FASTOPEN_CONNECT
75int opt_set_tcp_fastopen_connect(lua_State *L, p_socket ps);
76#endif
77
78int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps);
79int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps);
80
81int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps);
82int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps);
83
84int opt_set_ip_multicast_loop(lua_State *L, p_socket ps);
85int opt_get_ip_multicast_loop(lua_State *L, p_socket ps);
86
87int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps);
88int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps);
89
90int opt_set_linger(lua_State *L, p_socket ps);
91int opt_get_linger(lua_State *L, p_socket ps);
92
93int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps);
94
95int opt_set_ip_multicast_if(lua_State *L, p_socket ps);
96int opt_get_ip_multicast_if(lua_State *L, p_socket ps);
97
98int opt_set_ip_add_membership(lua_State *L, p_socket ps);
99int opt_set_ip_drop_membersip(lua_State *L, p_socket ps);
100
101int opt_set_ip6_add_membership(lua_State *L, p_socket ps);
102int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps);
103
104int opt_set_ip6_v6only(lua_State *L, p_socket ps);
105int opt_get_ip6_v6only(lua_State *L, p_socket ps);
106
107int opt_get_error(lua_State *L, p_socket ps);
108
109#ifndef _WIN32
110#pragma GCC visibility pop
111#endif
112
113#endif
diff --git a/vendor/luasocket/src/pierror.h b/vendor/luasocket/src/pierror.h
new file mode 100644
index 00000000..cb773ab7
--- /dev/null
+++ b/vendor/luasocket/src/pierror.h
@@ -0,0 +1,28 @@
1#ifndef PIERROR_H
2#define PIERROR_H
3/*=========================================================================*\
4* Error messages
5* Defines platform independent error messages
6\*=========================================================================*/
7
8#define PIE_HOST_NOT_FOUND "host not found"
9#define PIE_ADDRINUSE "address already in use"
10#define PIE_ISCONN "already connected"
11#define PIE_ACCESS "permission denied"
12#define PIE_CONNREFUSED "connection refused"
13#define PIE_CONNABORTED "closed"
14#define PIE_CONNRESET "closed"
15#define PIE_TIMEDOUT "timeout"
16#define PIE_AGAIN "temporary failure in name resolution"
17#define PIE_BADFLAGS "invalid value for ai_flags"
18#define PIE_BADHINTS "invalid value for hints"
19#define PIE_FAIL "non-recoverable failure in name resolution"
20#define PIE_FAMILY "ai_family not supported"
21#define PIE_MEMORY "memory allocation failure"
22#define PIE_NONAME "host or service not provided, or not known"
23#define PIE_OVERFLOW "argument buffer overflow"
24#define PIE_PROTOCOL "resolved protocol is unknown"
25#define PIE_SERVICE "service not supported for socket type"
26#define PIE_SOCKTYPE "ai_socktype not supported"
27
28#endif
diff --git a/vendor/luasocket/src/select.c b/vendor/luasocket/src/select.c
new file mode 100644
index 00000000..bb47c459
--- /dev/null
+++ b/vendor/luasocket/src/select.c
@@ -0,0 +1,214 @@
1/*=========================================================================*\
2* Select implementation
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6
7#include "socket.h"
8#include "timeout.h"
9#include "select.h"
10
11#include <string.h>
12
13/*=========================================================================*\
14* Internal function prototypes.
15\*=========================================================================*/
16static t_socket getfd(lua_State *L);
17static int dirty(lua_State *L);
18static void collect_fd(lua_State *L, int tab, int itab,
19 fd_set *set, t_socket *max_fd);
20static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set);
21static void return_fd(lua_State *L, fd_set *set, t_socket max_fd,
22 int itab, int tab, int start);
23static void make_assoc(lua_State *L, int tab);
24static int global_select(lua_State *L);
25
26/* functions in library namespace */
27static luaL_Reg func[] = {
28 {"select", global_select},
29 {NULL, NULL}
30};
31
32/*-------------------------------------------------------------------------*\
33* Initializes module
34\*-------------------------------------------------------------------------*/
35int select_open(lua_State *L) {
36 lua_pushstring(L, "_SETSIZE");
37 lua_pushinteger(L, FD_SETSIZE);
38 lua_rawset(L, -3);
39 lua_pushstring(L, "_SOCKETINVALID");
40 lua_pushinteger(L, SOCKET_INVALID);
41 lua_rawset(L, -3);
42 luaL_setfuncs(L, func, 0);
43 return 0;
44}
45
46/*=========================================================================*\
47* Global Lua functions
48\*=========================================================================*/
49/*-------------------------------------------------------------------------*\
50* Waits for a set of sockets until a condition is met or timeout.
51\*-------------------------------------------------------------------------*/
52static int global_select(lua_State *L) {
53 int rtab, wtab, itab, ret, ndirty;
54 t_socket max_fd = SOCKET_INVALID;
55 fd_set rset, wset;
56 t_timeout tm;
57 double t = luaL_optnumber(L, 3, -1);
58 FD_ZERO(&rset); FD_ZERO(&wset);
59 lua_settop(L, 3);
60 lua_newtable(L); itab = lua_gettop(L);
61 lua_newtable(L); rtab = lua_gettop(L);
62 lua_newtable(L); wtab = lua_gettop(L);
63 collect_fd(L, 1, itab, &rset, &max_fd);
64 collect_fd(L, 2, itab, &wset, &max_fd);
65 ndirty = check_dirty(L, 1, rtab, &rset);
66 t = ndirty > 0? 0.0: t;
67 timeout_init(&tm, t, -1);
68 timeout_markstart(&tm);
69 ret = socket_select(max_fd+1, &rset, &wset, NULL, &tm);
70 if (ret > 0 || ndirty > 0) {
71 return_fd(L, &rset, max_fd+1, itab, rtab, ndirty);
72 return_fd(L, &wset, max_fd+1, itab, wtab, 0);
73 make_assoc(L, rtab);
74 make_assoc(L, wtab);
75 return 2;
76 } else if (ret == 0) {
77 lua_pushstring(L, "timeout");
78 return 3;
79 } else {
80 luaL_error(L, "select failed");
81 return 3;
82 }
83}
84
85/*=========================================================================*\
86* Internal functions
87\*=========================================================================*/
88static t_socket getfd(lua_State *L) {
89 t_socket fd = SOCKET_INVALID;
90 lua_pushstring(L, "getfd");
91 lua_gettable(L, -2);
92 if (!lua_isnil(L, -1)) {
93 lua_pushvalue(L, -2);
94 lua_call(L, 1, 1);
95 if (lua_isnumber(L, -1)) {
96 double numfd = lua_tonumber(L, -1);
97 fd = (numfd >= 0.0)? (t_socket) numfd: SOCKET_INVALID;
98 }
99 }
100 lua_pop(L, 1);
101 return fd;
102}
103
104static int dirty(lua_State *L) {
105 int is = 0;
106 lua_pushstring(L, "dirty");
107 lua_gettable(L, -2);
108 if (!lua_isnil(L, -1)) {
109 lua_pushvalue(L, -2);
110 lua_call(L, 1, 1);
111 is = lua_toboolean(L, -1);
112 }
113 lua_pop(L, 1);
114 return is;
115}
116
117static void collect_fd(lua_State *L, int tab, int itab,
118 fd_set *set, t_socket *max_fd) {
119 int i = 1, n = 0;
120 /* nil is the same as an empty table */
121 if (lua_isnil(L, tab)) return;
122 /* otherwise we need it to be a table */
123 luaL_checktype(L, tab, LUA_TTABLE);
124 for ( ;; ) {
125 t_socket fd;
126 lua_pushnumber(L, i);
127 lua_gettable(L, tab);
128 if (lua_isnil(L, -1)) {
129 lua_pop(L, 1);
130 break;
131 }
132 /* getfd figures out if this is a socket */
133 fd = getfd(L);
134 if (fd != SOCKET_INVALID) {
135 /* make sure we don't overflow the fd_set */
136#ifdef _WIN32
137 if (n >= FD_SETSIZE)
138 luaL_argerror(L, tab, "too many sockets");
139#else
140 if (fd >= FD_SETSIZE)
141 luaL_argerror(L, tab, "descriptor too large for set size");
142#endif
143 FD_SET(fd, set);
144 n++;
145 /* keep track of the largest descriptor so far */
146 if (*max_fd == SOCKET_INVALID || *max_fd < fd)
147 *max_fd = fd;
148 /* make sure we can map back from descriptor to the object */
149 lua_pushnumber(L, (lua_Number) fd);
150 lua_pushvalue(L, -2);
151 lua_settable(L, itab);
152 }
153 lua_pop(L, 1);
154 i = i + 1;
155 }
156}
157
158static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) {
159 int ndirty = 0, i = 1;
160 if (lua_isnil(L, tab))
161 return 0;
162 for ( ;; ) {
163 t_socket fd;
164 lua_pushnumber(L, i);
165 lua_gettable(L, tab);
166 if (lua_isnil(L, -1)) {
167 lua_pop(L, 1);
168 break;
169 }
170 fd = getfd(L);
171 if (fd != SOCKET_INVALID && dirty(L)) {
172 lua_pushnumber(L, ++ndirty);
173 lua_pushvalue(L, -2);
174 lua_settable(L, dtab);
175 FD_CLR(fd, set);
176 }
177 lua_pop(L, 1);
178 i = i + 1;
179 }
180 return ndirty;
181}
182
183static void return_fd(lua_State *L, fd_set *set, t_socket max_fd,
184 int itab, int tab, int start) {
185 t_socket fd;
186 for (fd = 0; fd < max_fd; fd++) {
187 if (FD_ISSET(fd, set)) {
188 lua_pushnumber(L, ++start);
189 lua_pushnumber(L, (lua_Number) fd);
190 lua_gettable(L, itab);
191 lua_settable(L, tab);
192 }
193 }
194}
195
196static void make_assoc(lua_State *L, int tab) {
197 int i = 1, atab;
198 lua_newtable(L); atab = lua_gettop(L);
199 for ( ;; ) {
200 lua_pushnumber(L, i);
201 lua_gettable(L, tab);
202 if (!lua_isnil(L, -1)) {
203 lua_pushnumber(L, i);
204 lua_pushvalue(L, -2);
205 lua_settable(L, atab);
206 lua_pushnumber(L, i);
207 lua_settable(L, atab);
208 } else {
209 lua_pop(L, 1);
210 break;
211 }
212 i = i+1;
213 }
214}
diff --git a/vendor/luasocket/src/select.h b/vendor/luasocket/src/select.h
new file mode 100644
index 00000000..5d45fe75
--- /dev/null
+++ b/vendor/luasocket/src/select.h
@@ -0,0 +1,23 @@
1#ifndef SELECT_H
2#define SELECT_H
3/*=========================================================================*\
4* Select implementation
5* LuaSocket toolkit
6*
7* Each object that can be passed to the select function has to export
8* method getfd() which returns the descriptor to be passed to the
9* underlying select function. Another method, dirty(), should return
10* true if there is data ready for reading (required for buffered input).
11\*=========================================================================*/
12
13#ifndef _WIN32
14#pragma GCC visibility push(hidden)
15#endif
16
17int select_open(lua_State *L);
18
19#ifndef _WIN32
20#pragma GCC visibility pop
21#endif
22
23#endif /* SELECT_H */
diff --git a/vendor/luasocket/src/serial.c b/vendor/luasocket/src/serial.c
new file mode 100644
index 00000000..21485d3e
--- /dev/null
+++ b/vendor/luasocket/src/serial.c
@@ -0,0 +1,171 @@
1/*=========================================================================*\
2* Serial stream
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6
7#include "auxiliar.h"
8#include "socket.h"
9#include "options.h"
10#include "unix.h"
11
12#include <string.h>
13#include <sys/un.h>
14
15/*
16Reuses userdata definition from unix.h, since it is useful for all
17stream-like objects.
18
19If we stored the serial path for use in error messages or userdata
20printing, we might need our own userdata definition.
21
22Group usage is semi-inherited from unix.c, but unnecessary since we
23have only one object type.
24*/
25
26/*=========================================================================*\
27* Internal function prototypes
28\*=========================================================================*/
29static int global_create(lua_State *L);
30static int meth_send(lua_State *L);
31static int meth_receive(lua_State *L);
32static int meth_close(lua_State *L);
33static int meth_settimeout(lua_State *L);
34static int meth_getfd(lua_State *L);
35static int meth_setfd(lua_State *L);
36static int meth_dirty(lua_State *L);
37static int meth_getstats(lua_State *L);
38static int meth_setstats(lua_State *L);
39
40/* serial object methods */
41static luaL_Reg serial_methods[] = {
42 {"__gc", meth_close},
43 {"__tostring", auxiliar_tostring},
44 {"close", meth_close},
45 {"dirty", meth_dirty},
46 {"getfd", meth_getfd},
47 {"getstats", meth_getstats},
48 {"setstats", meth_setstats},
49 {"receive", meth_receive},
50 {"send", meth_send},
51 {"setfd", meth_setfd},
52 {"settimeout", meth_settimeout},
53 {NULL, NULL}
54};
55
56/*-------------------------------------------------------------------------*\
57* Initializes module
58\*-------------------------------------------------------------------------*/
59LUASOCKET_API int luaopen_socket_serial(lua_State *L) {
60 /* create classes */
61 auxiliar_newclass(L, "serial{client}", serial_methods);
62 /* create class groups */
63 auxiliar_add2group(L, "serial{client}", "serial{any}");
64 lua_pushcfunction(L, global_create);
65 return 1;
66}
67
68/*=========================================================================*\
69* Lua methods
70\*=========================================================================*/
71/*-------------------------------------------------------------------------*\
72* Just call buffered IO methods
73\*-------------------------------------------------------------------------*/
74static int meth_send(lua_State *L) {
75 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
76 return buffer_meth_send(L, &un->buf);
77}
78
79static int meth_receive(lua_State *L) {
80 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
81 return buffer_meth_receive(L, &un->buf);
82}
83
84static int meth_getstats(lua_State *L) {
85 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
86 return buffer_meth_getstats(L, &un->buf);
87}
88
89static int meth_setstats(lua_State *L) {
90 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
91 return buffer_meth_setstats(L, &un->buf);
92}
93
94/*-------------------------------------------------------------------------*\
95* Select support methods
96\*-------------------------------------------------------------------------*/
97static int meth_getfd(lua_State *L) {
98 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
99 lua_pushnumber(L, (int) un->sock);
100 return 1;
101}
102
103/* this is very dangerous, but can be handy for those that are brave enough */
104static int meth_setfd(lua_State *L) {
105 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
106 un->sock = (t_socket) luaL_checknumber(L, 2);
107 return 0;
108}
109
110static int meth_dirty(lua_State *L) {
111 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
112 lua_pushboolean(L, !buffer_isempty(&un->buf));
113 return 1;
114}
115
116/*-------------------------------------------------------------------------*\
117* Closes socket used by object
118\*-------------------------------------------------------------------------*/
119static int meth_close(lua_State *L)
120{
121 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
122 socket_destroy(&un->sock);
123 lua_pushnumber(L, 1);
124 return 1;
125}
126
127
128/*-------------------------------------------------------------------------*\
129* Just call tm methods
130\*-------------------------------------------------------------------------*/
131static int meth_settimeout(lua_State *L) {
132 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
133 return timeout_meth_settimeout(L, &un->tm);
134}
135
136/*=========================================================================*\
137* Library functions
138\*=========================================================================*/
139
140
141/*-------------------------------------------------------------------------*\
142* Creates a serial object
143\*-------------------------------------------------------------------------*/
144static int global_create(lua_State *L) {
145 const char* path = luaL_checkstring(L, 1);
146
147 /* allocate unix object */
148 p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
149
150 /* open serial device */
151 t_socket sock = open(path, O_NOCTTY|O_RDWR);
152
153 /*printf("open %s on %d\n", path, sock);*/
154
155 if (sock < 0) {
156 lua_pushnil(L);
157 lua_pushstring(L, socket_strerror(errno));
158 lua_pushnumber(L, errno);
159 return 3;
160 }
161 /* set its type as client object */
162 auxiliar_setclass(L, "serial{client}", -1);
163 /* initialize remaining structure fields */
164 socket_setnonblocking(&sock);
165 un->sock = sock;
166 io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,
167 (p_error) socket_ioerror, &un->sock);
168 timeout_init(&un->tm, -1, -1);
169 buffer_init(&un->buf, &un->io, &un->tm);
170 return 1;
171}
diff --git a/vendor/luasocket/src/smtp.lua b/vendor/luasocket/src/smtp.lua
new file mode 100644
index 00000000..b113d006
--- /dev/null
+++ b/vendor/luasocket/src/smtp.lua
@@ -0,0 +1,256 @@
1-----------------------------------------------------------------------------
2-- SMTP client support for the Lua language.
3-- LuaSocket toolkit.
4-- Author: Diego Nehab
5-----------------------------------------------------------------------------
6
7-----------------------------------------------------------------------------
8-- Declare module and import dependencies
9-----------------------------------------------------------------------------
10local base = _G
11local coroutine = require("coroutine")
12local string = require("string")
13local math = require("math")
14local os = require("os")
15local socket = require("socket")
16local tp = require("socket.tp")
17local ltn12 = require("ltn12")
18local headers = require("socket.headers")
19local mime = require("mime")
20
21socket.smtp = {}
22local _M = socket.smtp
23
24-----------------------------------------------------------------------------
25-- Program constants
26-----------------------------------------------------------------------------
27-- timeout for connection
28_M.TIMEOUT = 60
29-- default server used to send e-mails
30_M.SERVER = "localhost"
31-- default port
32_M.PORT = 25
33-- domain used in HELO command and default sendmail
34-- If we are under a CGI, try to get from environment
35_M.DOMAIN = os.getenv("SERVER_NAME") or "localhost"
36-- default time zone (means we don't know)
37_M.ZONE = "-0000"
38
39---------------------------------------------------------------------------
40-- Low level SMTP API
41-----------------------------------------------------------------------------
42local metat = { __index = {} }
43
44function metat.__index:greet(domain)
45 self.try(self.tp:check("2.."))
46 self.try(self.tp:command("EHLO", domain or _M.DOMAIN))
47 return socket.skip(1, self.try(self.tp:check("2..")))
48end
49
50function metat.__index:mail(from)
51 self.try(self.tp:command("MAIL", "FROM:" .. from))
52 return self.try(self.tp:check("2.."))
53end
54
55function metat.__index:rcpt(to)
56 self.try(self.tp:command("RCPT", "TO:" .. to))
57 return self.try(self.tp:check("2.."))
58end
59
60function metat.__index:data(src, step)
61 self.try(self.tp:command("DATA"))
62 self.try(self.tp:check("3.."))
63 self.try(self.tp:source(src, step))
64 self.try(self.tp:send("\r\n.\r\n"))
65 return self.try(self.tp:check("2.."))
66end
67
68function metat.__index:quit()
69 self.try(self.tp:command("QUIT"))
70 return self.try(self.tp:check("2.."))
71end
72
73function metat.__index:close()
74 return self.tp:close()
75end
76
77function metat.__index:login(user, password)
78 self.try(self.tp:command("AUTH", "LOGIN"))
79 self.try(self.tp:check("3.."))
80 self.try(self.tp:send(mime.b64(user) .. "\r\n"))
81 self.try(self.tp:check("3.."))
82 self.try(self.tp:send(mime.b64(password) .. "\r\n"))
83 return self.try(self.tp:check("2.."))
84end
85
86function metat.__index:plain(user, password)
87 local auth = "PLAIN " .. mime.b64("\0" .. user .. "\0" .. password)
88 self.try(self.tp:command("AUTH", auth))
89 return self.try(self.tp:check("2.."))
90end
91
92function metat.__index:auth(user, password, ext)
93 if not user or not password then return 1 end
94 if string.find(ext, "AUTH[^\n]+LOGIN") then
95 return self:login(user, password)
96 elseif string.find(ext, "AUTH[^\n]+PLAIN") then
97 return self:plain(user, password)
98 else
99 self.try(nil, "authentication not supported")
100 end
101end
102
103-- send message or throw an exception
104function metat.__index:send(mailt)
105 self:mail(mailt.from)
106 if base.type(mailt.rcpt) == "table" then
107 for i,v in base.ipairs(mailt.rcpt) do
108 self:rcpt(v)
109 end
110 else
111 self:rcpt(mailt.rcpt)
112 end
113 self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step)
114end
115
116function _M.open(server, port, create)
117 local tp = socket.try(tp.connect(server or _M.SERVER, port or _M.PORT,
118 _M.TIMEOUT, create))
119 local s = base.setmetatable({tp = tp}, metat)
120 -- make sure tp is closed if we get an exception
121 s.try = socket.newtry(function()
122 s:close()
123 end)
124 return s
125end
126
127-- convert headers to lowercase
128local function lower_headers(headers)
129 local lower = {}
130 for i,v in base.pairs(headers or lower) do
131 lower[string.lower(i)] = v
132 end
133 return lower
134end
135
136---------------------------------------------------------------------------
137-- Multipart message source
138-----------------------------------------------------------------------------
139-- returns a hopefully unique mime boundary
140local seqno = 0
141local function newboundary()
142 seqno = seqno + 1
143 return string.format('%s%05d==%05u', os.date('%d%m%Y%H%M%S'),
144 math.random(0, 99999), seqno)
145end
146
147-- send_message forward declaration
148local send_message
149
150-- yield the headers all at once, it's faster
151local function send_headers(tosend)
152 local canonic = headers.canonic
153 local h = "\r\n"
154 for f,v in base.pairs(tosend) do
155 h = (canonic[f] or f) .. ': ' .. v .. "\r\n" .. h
156 end
157 coroutine.yield(h)
158end
159
160-- yield multipart message body from a multipart message table
161local function send_multipart(mesgt)
162 -- make sure we have our boundary and send headers
163 local bd = newboundary()
164 local headers = lower_headers(mesgt.headers or {})
165 headers['content-type'] = headers['content-type'] or 'multipart/mixed'
166 headers['content-type'] = headers['content-type'] ..
167 '; boundary="' .. bd .. '"'
168 send_headers(headers)
169 -- send preamble
170 if mesgt.body.preamble then
171 coroutine.yield(mesgt.body.preamble)
172 coroutine.yield("\r\n")
173 end
174 -- send each part separated by a boundary
175 for i, m in base.ipairs(mesgt.body) do
176 coroutine.yield("\r\n--" .. bd .. "\r\n")
177 send_message(m)
178 end
179 -- send last boundary
180 coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n")
181 -- send epilogue
182 if mesgt.body.epilogue then
183 coroutine.yield(mesgt.body.epilogue)
184 coroutine.yield("\r\n")
185 end
186end
187
188-- yield message body from a source
189local function send_source(mesgt)
190 -- make sure we have a content-type
191 local headers = lower_headers(mesgt.headers or {})
192 headers['content-type'] = headers['content-type'] or
193 'text/plain; charset="iso-8859-1"'
194 send_headers(headers)
195 -- send body from source
196 while true do
197 local chunk, err = mesgt.body()
198 if err then coroutine.yield(nil, err)
199 elseif chunk then coroutine.yield(chunk)
200 else break end
201 end
202end
203
204-- yield message body from a string
205local function send_string(mesgt)
206 -- make sure we have a content-type
207 local headers = lower_headers(mesgt.headers or {})
208 headers['content-type'] = headers['content-type'] or
209 'text/plain; charset="iso-8859-1"'
210 send_headers(headers)
211 -- send body from string
212 coroutine.yield(mesgt.body)
213end
214
215-- message source
216function send_message(mesgt)
217 if base.type(mesgt.body) == "table" then send_multipart(mesgt)
218 elseif base.type(mesgt.body) == "function" then send_source(mesgt)
219 else send_string(mesgt) end
220end
221
222-- set defaul headers
223local function adjust_headers(mesgt)
224 local lower = lower_headers(mesgt.headers)
225 lower["date"] = lower["date"] or
226 os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or _M.ZONE)
227 lower["x-mailer"] = lower["x-mailer"] or socket._VERSION
228 -- this can't be overriden
229 lower["mime-version"] = "1.0"
230 return lower
231end
232
233function _M.message(mesgt)
234 mesgt.headers = adjust_headers(mesgt)
235 -- create and return message source
236 local co = coroutine.create(function() send_message(mesgt) end)
237 return function()
238 local ret, a, b = coroutine.resume(co)
239 if ret then return a, b
240 else return nil, a end
241 end
242end
243
244---------------------------------------------------------------------------
245-- High level SMTP API
246-----------------------------------------------------------------------------
247_M.send = socket.protect(function(mailt)
248 local s = _M.open(mailt.server, mailt.port, mailt.create)
249 local ext = s:greet(mailt.domain)
250 s:auth(mailt.user, mailt.password, ext)
251 s:send(mailt)
252 s:quit()
253 return s:close()
254end)
255
256return _M \ No newline at end of file
diff --git a/vendor/luasocket/src/socket.h b/vendor/luasocket/src/socket.h
new file mode 100755
index 00000000..2555bab6
--- /dev/null
+++ b/vendor/luasocket/src/socket.h
@@ -0,0 +1,75 @@
1#ifndef SOCKET_H
2#define SOCKET_H
3/*=========================================================================*\
4* Socket compatibilization module
5* LuaSocket toolkit
6*
7* BSD Sockets and WinSock are similar, but there are a few irritating
8* differences. Also, not all *nix platforms behave the same. This module
9* (and the associated usocket.h and wsocket.h) factor these differences and
10* creates a interface compatible with the io.h module.
11\*=========================================================================*/
12#include "io.h"
13
14/*=========================================================================*\
15* Platform specific compatibilization
16\*=========================================================================*/
17#ifdef _WIN32
18#include "wsocket.h"
19#define LUA_GAI_STRERROR gai_strerrorA
20#else
21#include "usocket.h"
22#define LUA_GAI_STRERROR gai_strerror
23#endif
24
25/*=========================================================================*\
26* The connect and accept functions accept a timeout and their
27* implementations are somewhat complicated. We chose to move
28* the timeout control into this module for these functions in
29* order to simplify the modules that use them.
30\*=========================================================================*/
31#include "timeout.h"
32
33/* convenient shorthand */
34typedef struct sockaddr SA;
35
36/*=========================================================================*\
37* Functions bellow implement a comfortable platform independent
38* interface to sockets
39\*=========================================================================*/
40
41#ifndef _WIN32
42#pragma GCC visibility push(hidden)
43#endif
44
45int socket_waitfd(p_socket ps, int sw, p_timeout tm);
46int socket_open(void);
47int socket_close(void);
48void socket_destroy(p_socket ps);
49int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds, p_timeout tm);
50int socket_create(p_socket ps, int domain, int type, int protocol);
51int socket_bind(p_socket ps, SA *addr, socklen_t addr_len);
52int socket_listen(p_socket ps, int backlog);
53void socket_shutdown(p_socket ps, int how);
54int socket_connect(p_socket ps, SA *addr, socklen_t addr_len, p_timeout tm);
55int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *addr_len, p_timeout tm);
56int socket_send(p_socket ps, const char *data, size_t count, size_t *sent, p_timeout tm);
57int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, SA *addr, socklen_t addr_len, p_timeout tm);
58int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm);
59int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, SA *addr, socklen_t *addr_len, p_timeout tm);
60int socket_write(p_socket ps, const char *data, size_t count, size_t *sent, p_timeout tm);
61int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm);
62void socket_setblocking(p_socket ps);
63void socket_setnonblocking(p_socket ps);
64int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp);
65int socket_gethostbyname(const char *addr, struct hostent **hp);
66const char *socket_hoststrerror(int err);
67const char *socket_strerror(int err);
68const char *socket_ioerror(p_socket ps, int err);
69const char *socket_gaistrerror(int err);
70
71#ifndef _WIN32
72#pragma GCC visibility pop
73#endif
74
75#endif /* SOCKET_H */
diff --git a/vendor/luasocket/src/socket.lua b/vendor/luasocket/src/socket.lua
new file mode 100644
index 00000000..d1c0b164
--- /dev/null
+++ b/vendor/luasocket/src/socket.lua
@@ -0,0 +1,149 @@
1-----------------------------------------------------------------------------
2-- LuaSocket helper module
3-- Author: Diego Nehab
4-----------------------------------------------------------------------------
5
6-----------------------------------------------------------------------------
7-- Declare module and import dependencies
8-----------------------------------------------------------------------------
9local base = _G
10local string = require("string")
11local math = require("math")
12local socket = require("socket.core")
13
14local _M = socket
15
16-----------------------------------------------------------------------------
17-- Exported auxiliar functions
18-----------------------------------------------------------------------------
19function _M.connect4(address, port, laddress, lport)
20 return socket.connect(address, port, laddress, lport, "inet")
21end
22
23function _M.connect6(address, port, laddress, lport)
24 return socket.connect(address, port, laddress, lport, "inet6")
25end
26
27function _M.bind(host, port, backlog)
28 if host == "*" then host = "0.0.0.0" end
29 local addrinfo, err = socket.dns.getaddrinfo(host);
30 if not addrinfo then return nil, err end
31 local sock, res
32 err = "no info on address"
33 for i, alt in base.ipairs(addrinfo) do
34 if alt.family == "inet" then
35 sock, err = socket.tcp4()
36 else
37 sock, err = socket.tcp6()
38 end
39 if not sock then return nil, err end
40 sock:setoption("reuseaddr", true)
41 res, err = sock:bind(alt.addr, port)
42 if not res then
43 sock:close()
44 else
45 res, err = sock:listen(backlog)
46 if not res then
47 sock:close()
48 else
49 return sock
50 end
51 end
52 end
53 return nil, err
54end
55
56_M.try = _M.newtry()
57
58function _M.choose(table)
59 return function(name, opt1, opt2)
60 if base.type(name) ~= "string" then
61 name, opt1, opt2 = "default", name, opt1
62 end
63 local f = table[name or "nil"]
64 if not f then base.error("unknown key (".. base.tostring(name) ..")", 3)
65 else return f(opt1, opt2) end
66 end
67end
68
69-----------------------------------------------------------------------------
70-- Socket sources and sinks, conforming to LTN12
71-----------------------------------------------------------------------------
72-- create namespaces inside LuaSocket namespace
73local sourcet, sinkt = {}, {}
74_M.sourcet = sourcet
75_M.sinkt = sinkt
76
77_M.BLOCKSIZE = 2048
78
79sinkt["close-when-done"] = function(sock)
80 return base.setmetatable({
81 getfd = function() return sock:getfd() end,
82 dirty = function() return sock:dirty() end
83 }, {
84 __call = function(self, chunk, err)
85 if not chunk then
86 sock:close()
87 return 1
88 else return sock:send(chunk) end
89 end
90 })
91end
92
93sinkt["keep-open"] = function(sock)
94 return base.setmetatable({
95 getfd = function() return sock:getfd() end,
96 dirty = function() return sock:dirty() end
97 }, {
98 __call = function(self, chunk, err)
99 if chunk then return sock:send(chunk)
100 else return 1 end
101 end
102 })
103end
104
105sinkt["default"] = sinkt["keep-open"]
106
107_M.sink = _M.choose(sinkt)
108
109sourcet["by-length"] = function(sock, length)
110 return base.setmetatable({
111 getfd = function() return sock:getfd() end,
112 dirty = function() return sock:dirty() end
113 }, {
114 __call = function()
115 if length <= 0 then return nil end
116 local size = math.min(socket.BLOCKSIZE, length)
117 local chunk, err = sock:receive(size)
118 if err then return nil, err end
119 length = length - string.len(chunk)
120 return chunk
121 end
122 })
123end
124
125sourcet["until-closed"] = function(sock)
126 local done
127 return base.setmetatable({
128 getfd = function() return sock:getfd() end,
129 dirty = function() return sock:dirty() end
130 }, {
131 __call = function()
132 if done then return nil end
133 local chunk, err, partial = sock:receive(socket.BLOCKSIZE)
134 if not err then return chunk
135 elseif err == "closed" then
136 sock:close()
137 done = 1
138 return partial
139 else return nil, err end
140 end
141 })
142end
143
144
145sourcet["default"] = sourcet["until-closed"]
146
147_M.source = _M.choose(sourcet)
148
149return _M
diff --git a/vendor/luasocket/src/tcp.c b/vendor/luasocket/src/tcp.c
new file mode 100644
index 00000000..e84db845
--- /dev/null
+++ b/vendor/luasocket/src/tcp.c
@@ -0,0 +1,480 @@
1/*=========================================================================*\
2* TCP object
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6
7#include "auxiliar.h"
8#include "socket.h"
9#include "inet.h"
10#include "options.h"
11#include "tcp.h"
12
13#include <string.h>
14
15/*=========================================================================*\
16* Internal function prototypes
17\*=========================================================================*/
18static int global_create(lua_State *L);
19static int global_create4(lua_State *L);
20static int global_create6(lua_State *L);
21static int global_connect(lua_State *L);
22static int meth_connect(lua_State *L);
23static int meth_listen(lua_State *L);
24static int meth_getfamily(lua_State *L);
25static int meth_bind(lua_State *L);
26static int meth_send(lua_State *L);
27static int meth_getstats(lua_State *L);
28static int meth_setstats(lua_State *L);
29static int meth_getsockname(lua_State *L);
30static int meth_getpeername(lua_State *L);
31static int meth_shutdown(lua_State *L);
32static int meth_receive(lua_State *L);
33static int meth_accept(lua_State *L);
34static int meth_close(lua_State *L);
35static int meth_getoption(lua_State *L);
36static int meth_setoption(lua_State *L);
37static int meth_gettimeout(lua_State *L);
38static int meth_settimeout(lua_State *L);
39static int meth_getfd(lua_State *L);
40static int meth_setfd(lua_State *L);
41static int meth_dirty(lua_State *L);
42
43/* tcp object methods */
44static luaL_Reg tcp_methods[] = {
45 {"__gc", meth_close},
46 {"__tostring", auxiliar_tostring},
47 {"accept", meth_accept},
48 {"bind", meth_bind},
49 {"close", meth_close},
50 {"connect", meth_connect},
51 {"dirty", meth_dirty},
52 {"getfamily", meth_getfamily},
53 {"getfd", meth_getfd},
54 {"getoption", meth_getoption},
55 {"getpeername", meth_getpeername},
56 {"getsockname", meth_getsockname},
57 {"getstats", meth_getstats},
58 {"setstats", meth_setstats},
59 {"listen", meth_listen},
60 {"receive", meth_receive},
61 {"send", meth_send},
62 {"setfd", meth_setfd},
63 {"setoption", meth_setoption},
64 {"setpeername", meth_connect},
65 {"setsockname", meth_bind},
66 {"settimeout", meth_settimeout},
67 {"gettimeout", meth_gettimeout},
68 {"shutdown", meth_shutdown},
69 {NULL, NULL}
70};
71
72/* socket option handlers */
73static t_opt optget[] = {
74 {"keepalive", opt_get_keepalive},
75 {"reuseaddr", opt_get_reuseaddr},
76 {"reuseport", opt_get_reuseport},
77 {"tcp-nodelay", opt_get_tcp_nodelay},
78#ifdef TCP_KEEPIDLE
79 {"tcp-keepidle", opt_get_tcp_keepidle},
80#endif
81#ifdef TCP_KEEPCNT
82 {"tcp-keepcnt", opt_get_tcp_keepcnt},
83#endif
84#ifdef TCP_KEEPINTVL
85 {"tcp-keepintvl", opt_get_tcp_keepintvl},
86#endif
87 {"linger", opt_get_linger},
88 {"error", opt_get_error},
89 {"recv-buffer-size", opt_get_recv_buf_size},
90 {"send-buffer-size", opt_get_send_buf_size},
91 {NULL, NULL}
92};
93
94static t_opt optset[] = {
95 {"keepalive", opt_set_keepalive},
96 {"reuseaddr", opt_set_reuseaddr},
97 {"reuseport", opt_set_reuseport},
98 {"tcp-nodelay", opt_set_tcp_nodelay},
99#ifdef TCP_KEEPIDLE
100 {"tcp-keepidle", opt_set_tcp_keepidle},
101#endif
102#ifdef TCP_KEEPCNT
103 {"tcp-keepcnt", opt_set_tcp_keepcnt},
104#endif
105#ifdef TCP_KEEPINTVL
106 {"tcp-keepintvl", opt_set_tcp_keepintvl},
107#endif
108 {"ipv6-v6only", opt_set_ip6_v6only},
109 {"linger", opt_set_linger},
110 {"recv-buffer-size", opt_set_recv_buf_size},
111 {"send-buffer-size", opt_set_send_buf_size},
112#ifdef TCP_DEFER_ACCEPT
113 {"tcp-defer-accept", opt_set_tcp_defer_accept},
114#endif
115#ifdef TCP_FASTOPEN
116 {"tcp-fastopen", opt_set_tcp_fastopen},
117#endif
118#ifdef TCP_FASTOPEN_CONNECT
119 {"tcp-fastopen-connect", opt_set_tcp_fastopen_connect},
120#endif
121 {NULL, NULL}
122};
123
124/* functions in library namespace */
125static luaL_Reg func[] = {
126 {"tcp", global_create},
127 {"tcp4", global_create4},
128 {"tcp6", global_create6},
129 {"connect", global_connect},
130 {NULL, NULL}
131};
132
133/*-------------------------------------------------------------------------*\
134* Initializes module
135\*-------------------------------------------------------------------------*/
136int tcp_open(lua_State *L)
137{
138 /* create classes */
139 auxiliar_newclass(L, "tcp{master}", tcp_methods);
140 auxiliar_newclass(L, "tcp{client}", tcp_methods);
141 auxiliar_newclass(L, "tcp{server}", tcp_methods);
142 /* create class groups */
143 auxiliar_add2group(L, "tcp{master}", "tcp{any}");
144 auxiliar_add2group(L, "tcp{client}", "tcp{any}");
145 auxiliar_add2group(L, "tcp{server}", "tcp{any}");
146 /* define library functions */
147 luaL_setfuncs(L, func, 0);
148 return 0;
149}
150
151/*=========================================================================*\
152* Lua methods
153\*=========================================================================*/
154/*-------------------------------------------------------------------------*\
155* Just call buffered IO methods
156\*-------------------------------------------------------------------------*/
157static int meth_send(lua_State *L) {
158 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1);
159 return buffer_meth_send(L, &tcp->buf);
160}
161
162static int meth_receive(lua_State *L) {
163 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1);
164 return buffer_meth_receive(L, &tcp->buf);
165}
166
167static int meth_getstats(lua_State *L) {
168 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1);
169 return buffer_meth_getstats(L, &tcp->buf);
170}
171
172static int meth_setstats(lua_State *L) {
173 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1);
174 return buffer_meth_setstats(L, &tcp->buf);
175}
176
177/*-------------------------------------------------------------------------*\
178* Just call option handler
179\*-------------------------------------------------------------------------*/
180static int meth_getoption(lua_State *L)
181{
182 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
183 return opt_meth_getoption(L, optget, &tcp->sock);
184}
185
186static int meth_setoption(lua_State *L)
187{
188 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
189 return opt_meth_setoption(L, optset, &tcp->sock);
190}
191
192/*-------------------------------------------------------------------------*\
193* Select support methods
194\*-------------------------------------------------------------------------*/
195static int meth_getfd(lua_State *L)
196{
197 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
198 lua_pushnumber(L, (int) tcp->sock);
199 return 1;
200}
201
202/* this is very dangerous, but can be handy for those that are brave enough */
203static int meth_setfd(lua_State *L)
204{
205 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
206 tcp->sock = (t_socket) luaL_checknumber(L, 2);
207 return 0;
208}
209
210static int meth_dirty(lua_State *L)
211{
212 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
213 lua_pushboolean(L, !buffer_isempty(&tcp->buf));
214 return 1;
215}
216
217/*-------------------------------------------------------------------------*\
218* Waits for and returns a client object attempting connection to the
219* server object
220\*-------------------------------------------------------------------------*/
221static int meth_accept(lua_State *L)
222{
223 p_tcp server = (p_tcp) auxiliar_checkclass(L, "tcp{server}", 1);
224 p_timeout tm = timeout_markstart(&server->tm);
225 t_socket sock;
226 const char *err = inet_tryaccept(&server->sock, server->family, &sock, tm);
227 /* if successful, push client socket */
228 if (err == NULL) {
229 p_tcp clnt = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
230 auxiliar_setclass(L, "tcp{client}", -1);
231 /* initialize structure fields */
232 memset(clnt, 0, sizeof(t_tcp));
233 socket_setnonblocking(&sock);
234 clnt->sock = sock;
235 io_init(&clnt->io, (p_send) socket_send, (p_recv) socket_recv,
236 (p_error) socket_ioerror, &clnt->sock);
237 timeout_init(&clnt->tm, -1, -1);
238 buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
239 clnt->family = server->family;
240 return 1;
241 } else {
242 lua_pushnil(L);
243 lua_pushstring(L, err);
244 return 2;
245 }
246}
247
248/*-------------------------------------------------------------------------*\
249* Binds an object to an address
250\*-------------------------------------------------------------------------*/
251static int meth_bind(lua_State *L) {
252 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1);
253 const char *address = luaL_checkstring(L, 2);
254 const char *port = luaL_checkstring(L, 3);
255 const char *err;
256 struct addrinfo bindhints;
257 memset(&bindhints, 0, sizeof(bindhints));
258 bindhints.ai_socktype = SOCK_STREAM;
259 bindhints.ai_family = tcp->family;
260 bindhints.ai_flags = AI_PASSIVE;
261 err = inet_trybind(&tcp->sock, &tcp->family, address, port, &bindhints);
262 if (err) {
263 lua_pushnil(L);
264 lua_pushstring(L, err);
265 return 2;
266 }
267 lua_pushnumber(L, 1);
268 return 1;
269}
270
271/*-------------------------------------------------------------------------*\
272* Turns a master tcp object into a client object.
273\*-------------------------------------------------------------------------*/
274static int meth_connect(lua_State *L) {
275 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
276 const char *address = luaL_checkstring(L, 2);
277 const char *port = luaL_checkstring(L, 3);
278 struct addrinfo connecthints;
279 const char *err;
280 memset(&connecthints, 0, sizeof(connecthints));
281 connecthints.ai_socktype = SOCK_STREAM;
282 /* make sure we try to connect only to the same family */
283 connecthints.ai_family = tcp->family;
284 timeout_markstart(&tcp->tm);
285 err = inet_tryconnect(&tcp->sock, &tcp->family, address, port,
286 &tcp->tm, &connecthints);
287 /* have to set the class even if it failed due to non-blocking connects */
288 auxiliar_setclass(L, "tcp{client}", 1);
289 if (err) {
290 lua_pushnil(L);
291 lua_pushstring(L, err);
292 return 2;
293 }
294 lua_pushnumber(L, 1);
295 return 1;
296}
297
298/*-------------------------------------------------------------------------*\
299* Closes socket used by object
300\*-------------------------------------------------------------------------*/
301static int meth_close(lua_State *L)
302{
303 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
304 socket_destroy(&tcp->sock);
305 lua_pushnumber(L, 1);
306 return 1;
307}
308
309/*-------------------------------------------------------------------------*\
310* Returns family as string
311\*-------------------------------------------------------------------------*/
312static int meth_getfamily(lua_State *L)
313{
314 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
315 if (tcp->family == AF_INET6) {
316 lua_pushliteral(L, "inet6");
317 return 1;
318 } else if (tcp->family == AF_INET) {
319 lua_pushliteral(L, "inet4");
320 return 1;
321 } else {
322 lua_pushliteral(L, "inet4");
323 return 1;
324 }
325}
326
327/*-------------------------------------------------------------------------*\
328* Puts the sockt in listen mode
329\*-------------------------------------------------------------------------*/
330static int meth_listen(lua_State *L)
331{
332 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{master}", 1);
333 int backlog = (int) luaL_optnumber(L, 2, 32);
334 int err = socket_listen(&tcp->sock, backlog);
335 if (err != IO_DONE) {
336 lua_pushnil(L);
337 lua_pushstring(L, socket_strerror(err));
338 return 2;
339 }
340 /* turn master object into a server object */
341 auxiliar_setclass(L, "tcp{server}", 1);
342 lua_pushnumber(L, 1);
343 return 1;
344}
345
346/*-------------------------------------------------------------------------*\
347* Shuts the connection down partially
348\*-------------------------------------------------------------------------*/
349static int meth_shutdown(lua_State *L)
350{
351 /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */
352 static const char* methods[] = { "receive", "send", "both", NULL };
353 p_tcp tcp = (p_tcp) auxiliar_checkclass(L, "tcp{client}", 1);
354 int how = luaL_checkoption(L, 2, "both", methods);
355 socket_shutdown(&tcp->sock, how);
356 lua_pushnumber(L, 1);
357 return 1;
358}
359
360/*-------------------------------------------------------------------------*\
361* Just call inet methods
362\*-------------------------------------------------------------------------*/
363static int meth_getpeername(lua_State *L)
364{
365 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
366 return inet_meth_getpeername(L, &tcp->sock, tcp->family);
367}
368
369static int meth_getsockname(lua_State *L)
370{
371 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
372 return inet_meth_getsockname(L, &tcp->sock, tcp->family);
373}
374
375/*-------------------------------------------------------------------------*\
376* Just call tm methods
377\*-------------------------------------------------------------------------*/
378static int meth_settimeout(lua_State *L)
379{
380 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
381 return timeout_meth_settimeout(L, &tcp->tm);
382}
383
384static int meth_gettimeout(lua_State *L)
385{
386 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
387 return timeout_meth_gettimeout(L, &tcp->tm);
388}
389
390/*=========================================================================*\
391* Library functions
392\*=========================================================================*/
393/*-------------------------------------------------------------------------*\
394* Creates a master tcp object
395\*-------------------------------------------------------------------------*/
396static int tcp_create(lua_State *L, int family) {
397 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
398 memset(tcp, 0, sizeof(t_tcp));
399 /* set its type as master object */
400 auxiliar_setclass(L, "tcp{master}", -1);
401 /* if family is AF_UNSPEC, we leave the socket invalid and
402 * store AF_UNSPEC into family. This will allow it to later be
403 * replaced with an AF_INET6 or AF_INET socket upon first use. */
404 tcp->sock = SOCKET_INVALID;
405 tcp->family = family;
406 io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
407 (p_error) socket_ioerror, &tcp->sock);
408 timeout_init(&tcp->tm, -1, -1);
409 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
410 if (family != AF_UNSPEC) {
411 const char *err = inet_trycreate(&tcp->sock, family, SOCK_STREAM, 0);
412 if (err != NULL) {
413 lua_pushnil(L);
414 lua_pushstring(L, err);
415 return 2;
416 }
417 socket_setnonblocking(&tcp->sock);
418 }
419 return 1;
420}
421
422static int global_create(lua_State *L) {
423 return tcp_create(L, AF_UNSPEC);
424}
425
426static int global_create4(lua_State *L) {
427 return tcp_create(L, AF_INET);
428}
429
430static int global_create6(lua_State *L) {
431 return tcp_create(L, AF_INET6);
432}
433
434static int global_connect(lua_State *L) {
435 const char *remoteaddr = luaL_checkstring(L, 1);
436 const char *remoteserv = luaL_checkstring(L, 2);
437 const char *localaddr = luaL_optstring(L, 3, NULL);
438 const char *localserv = luaL_optstring(L, 4, "0");
439 int family = inet_optfamily(L, 5, "unspec");
440 p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
441 struct addrinfo bindhints, connecthints;
442 const char *err = NULL;
443 /* initialize tcp structure */
444 memset(tcp, 0, sizeof(t_tcp));
445 io_init(&tcp->io, (p_send) socket_send, (p_recv) socket_recv,
446 (p_error) socket_ioerror, &tcp->sock);
447 timeout_init(&tcp->tm, -1, -1);
448 buffer_init(&tcp->buf, &tcp->io, &tcp->tm);
449 tcp->sock = SOCKET_INVALID;
450 tcp->family = AF_UNSPEC;
451 /* allow user to pick local address and port */
452 memset(&bindhints, 0, sizeof(bindhints));
453 bindhints.ai_socktype = SOCK_STREAM;
454 bindhints.ai_family = family;
455 bindhints.ai_flags = AI_PASSIVE;
456 if (localaddr) {
457 err = inet_trybind(&tcp->sock, &tcp->family, localaddr,
458 localserv, &bindhints);
459 if (err) {
460 lua_pushnil(L);
461 lua_pushstring(L, err);
462 return 2;
463 }
464 }
465 /* try to connect to remote address and port */
466 memset(&connecthints, 0, sizeof(connecthints));
467 connecthints.ai_socktype = SOCK_STREAM;
468 /* make sure we try to connect only to the same family */
469 connecthints.ai_family = tcp->family;
470 err = inet_tryconnect(&tcp->sock, &tcp->family, remoteaddr, remoteserv,
471 &tcp->tm, &connecthints);
472 if (err) {
473 socket_destroy(&tcp->sock);
474 lua_pushnil(L);
475 lua_pushstring(L, err);
476 return 2;
477 }
478 auxiliar_setclass(L, "tcp{client}", -1);
479 return 1;
480}
diff --git a/vendor/luasocket/src/tcp.h b/vendor/luasocket/src/tcp.h
new file mode 100644
index 00000000..9b282efe
--- /dev/null
+++ b/vendor/luasocket/src/tcp.h
@@ -0,0 +1,43 @@
1#ifndef TCP_H
2#define TCP_H
3/*=========================================================================*\
4* TCP object
5* LuaSocket toolkit
6*
7* The tcp.h module is basicly a glue that puts together modules buffer.h,
8* timeout.h socket.h and inet.h to provide the LuaSocket TCP (AF_INET,
9* SOCK_STREAM) support.
10*
11* Three classes are defined: master, client and server. The master class is
12* a newly created tcp object, that has not been bound or connected. Server
13* objects are tcp objects bound to some local address. Client objects are
14* tcp objects either connected to some address or returned by the accept
15* method of a server object.
16\*=========================================================================*/
17#include "luasocket.h"
18
19#include "buffer.h"
20#include "timeout.h"
21#include "socket.h"
22
23typedef struct t_tcp_ {
24 t_socket sock;
25 t_io io;
26 t_buffer buf;
27 t_timeout tm;
28 int family;
29} t_tcp;
30
31typedef t_tcp *p_tcp;
32
33#ifndef _WIN32
34#pragma GCC visibility push(hidden)
35#endif
36
37int tcp_open(lua_State *L);
38
39#ifndef _WIN32
40#pragma GCC visibility pop
41#endif
42
43#endif /* TCP_H */
diff --git a/vendor/luasocket/src/timeout.c b/vendor/luasocket/src/timeout.c
new file mode 100644
index 00000000..2bdc0698
--- /dev/null
+++ b/vendor/luasocket/src/timeout.c
@@ -0,0 +1,226 @@
1/*=========================================================================*\
2* Timeout management functions
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6
7#include "auxiliar.h"
8#include "timeout.h"
9
10#include <stdio.h>
11#include <limits.h>
12#include <float.h>
13
14#ifdef _WIN32
15#include <windows.h>
16#else
17#include <time.h>
18#include <sys/time.h>
19#endif
20
21/* min and max macros */
22#ifndef MIN
23#define MIN(x, y) ((x) < (y) ? x : y)
24#endif
25#ifndef MAX
26#define MAX(x, y) ((x) > (y) ? x : y)
27#endif
28
29/*=========================================================================*\
30* Internal function prototypes
31\*=========================================================================*/
32static int timeout_lua_gettime(lua_State *L);
33static int timeout_lua_sleep(lua_State *L);
34
35static luaL_Reg func[] = {
36 { "gettime", timeout_lua_gettime },
37 { "sleep", timeout_lua_sleep },
38 { NULL, NULL }
39};
40
41/*=========================================================================*\
42* Exported functions.
43\*=========================================================================*/
44/*-------------------------------------------------------------------------*\
45* Initialize structure
46\*-------------------------------------------------------------------------*/
47void timeout_init(p_timeout tm, double block, double total) {
48 tm->block = block;
49 tm->total = total;
50}
51
52/*-------------------------------------------------------------------------*\
53* Determines how much time we have left for the next system call,
54* if the previous call was successful
55* Input
56* tm: timeout control structure
57* Returns
58* the number of ms left or -1 if there is no time limit
59\*-------------------------------------------------------------------------*/
60double timeout_get(p_timeout tm) {
61 if (tm->block < 0.0 && tm->total < 0.0) {
62 return -1;
63 } else if (tm->block < 0.0) {
64 double t = tm->total - timeout_gettime() + tm->start;
65 return MAX(t, 0.0);
66 } else if (tm->total < 0.0) {
67 return tm->block;
68 } else {
69 double t = tm->total - timeout_gettime() + tm->start;
70 return MIN(tm->block, MAX(t, 0.0));
71 }
72}
73
74/*-------------------------------------------------------------------------*\
75* Returns time since start of operation
76* Input
77* tm: timeout control structure
78* Returns
79* start field of structure
80\*-------------------------------------------------------------------------*/
81double timeout_getstart(p_timeout tm) {
82 return tm->start;
83}
84
85/*-------------------------------------------------------------------------*\
86* Determines how much time we have left for the next system call,
87* if the previous call was a failure
88* Input
89* tm: timeout control structure
90* Returns
91* the number of ms left or -1 if there is no time limit
92\*-------------------------------------------------------------------------*/
93double timeout_getretry(p_timeout tm) {
94 if (tm->block < 0.0 && tm->total < 0.0) {
95 return -1;
96 } else if (tm->block < 0.0) {
97 double t = tm->total - timeout_gettime() + tm->start;
98 return MAX(t, 0.0);
99 } else if (tm->total < 0.0) {
100 double t = tm->block - timeout_gettime() + tm->start;
101 return MAX(t, 0.0);
102 } else {
103 double t = tm->total - timeout_gettime() + tm->start;
104 return MIN(tm->block, MAX(t, 0.0));
105 }
106}
107
108/*-------------------------------------------------------------------------*\
109* Marks the operation start time in structure
110* Input
111* tm: timeout control structure
112\*-------------------------------------------------------------------------*/
113p_timeout timeout_markstart(p_timeout tm) {
114 tm->start = timeout_gettime();
115 return tm;
116}
117
118/*-------------------------------------------------------------------------*\
119* Gets time in s, relative to January 1, 1970 (UTC)
120* Returns
121* time in s.
122\*-------------------------------------------------------------------------*/
123#ifdef _WIN32
124double timeout_gettime(void) {
125 FILETIME ft;
126 double t;
127 GetSystemTimeAsFileTime(&ft);
128 /* Windows file time (time since January 1, 1601 (UTC)) */
129 t = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7);
130 /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */
131 return (t - 11644473600.0);
132}
133#else
134double timeout_gettime(void) {
135 struct timeval v;
136 gettimeofday(&v, (struct timezone *) NULL);
137 /* Unix Epoch time (time since January 1, 1970 (UTC)) */
138 return v.tv_sec + v.tv_usec/1.0e6;
139}
140#endif
141
142/*-------------------------------------------------------------------------*\
143* Initializes module
144\*-------------------------------------------------------------------------*/
145int timeout_open(lua_State *L) {
146 luaL_setfuncs(L, func, 0);
147 return 0;
148}
149
150/*-------------------------------------------------------------------------*\
151* Sets timeout values for IO operations
152* Lua Input: base, time [, mode]
153* time: time out value in seconds
154* mode: "b" for block timeout, "t" for total timeout. (default: b)
155\*-------------------------------------------------------------------------*/
156int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
157 double t = luaL_optnumber(L, 2, -1);
158 const char *mode = luaL_optstring(L, 3, "b");
159 switch (*mode) {
160 case 'b':
161 tm->block = t;
162 break;
163 case 'r': case 't':
164 tm->total = t;
165 break;
166 default:
167 luaL_argcheck(L, 0, 3, "invalid timeout mode");
168 break;
169 }
170 lua_pushnumber(L, 1);
171 return 1;
172}
173
174/*-------------------------------------------------------------------------*\
175* Gets timeout values for IO operations
176* Lua Output: block, total
177\*-------------------------------------------------------------------------*/
178int timeout_meth_gettimeout(lua_State *L, p_timeout tm) {
179 lua_pushnumber(L, tm->block);
180 lua_pushnumber(L, tm->total);
181 return 2;
182}
183
184/*=========================================================================*\
185* Test support functions
186\*=========================================================================*/
187/*-------------------------------------------------------------------------*\
188* Returns the time the system has been up, in secconds.
189\*-------------------------------------------------------------------------*/
190static int timeout_lua_gettime(lua_State *L)
191{
192 lua_pushnumber(L, timeout_gettime());
193 return 1;
194}
195
196/*-------------------------------------------------------------------------*\
197* Sleep for n seconds.
198\*-------------------------------------------------------------------------*/
199#ifdef _WIN32
200int timeout_lua_sleep(lua_State *L)
201{
202 double n = luaL_checknumber(L, 1);
203 if (n < 0.0) n = 0.0;
204 if (n < DBL_MAX/1000.0) n *= 1000.0;
205 if (n > INT_MAX) n = INT_MAX;
206 Sleep((int)n);
207 return 0;
208}
209#else
210int timeout_lua_sleep(lua_State *L)
211{
212 double n = luaL_checknumber(L, 1);
213 struct timespec t, r;
214 if (n < 0.0) n = 0.0;
215 if (n > INT_MAX) n = INT_MAX;
216 t.tv_sec = (int) n;
217 n -= t.tv_sec;
218 t.tv_nsec = (int) (n * 1000000000);
219 if (t.tv_nsec >= 1000000000) t.tv_nsec = 999999999;
220 while (nanosleep(&t, &r) != 0) {
221 t.tv_sec = r.tv_sec;
222 t.tv_nsec = r.tv_nsec;
223 }
224 return 0;
225}
226#endif
diff --git a/vendor/luasocket/src/timeout.h b/vendor/luasocket/src/timeout.h
new file mode 100644
index 00000000..9e5250d3
--- /dev/null
+++ b/vendor/luasocket/src/timeout.h
@@ -0,0 +1,40 @@
1#ifndef TIMEOUT_H
2#define TIMEOUT_H
3/*=========================================================================*\
4* Timeout management functions
5* LuaSocket toolkit
6\*=========================================================================*/
7#include "luasocket.h"
8
9/* timeout control structure */
10typedef struct t_timeout_ {
11 double block; /* maximum time for blocking calls */
12 double total; /* total number of miliseconds for operation */
13 double start; /* time of start of operation */
14} t_timeout;
15typedef t_timeout *p_timeout;
16
17#ifndef _WIN32
18#pragma GCC visibility push(hidden)
19#endif
20
21void timeout_init(p_timeout tm, double block, double total);
22double timeout_get(p_timeout tm);
23double timeout_getstart(p_timeout tm);
24double timeout_getretry(p_timeout tm);
25p_timeout timeout_markstart(p_timeout tm);
26
27double timeout_gettime(void);
28
29int timeout_open(lua_State *L);
30
31int timeout_meth_settimeout(lua_State *L, p_timeout tm);
32int timeout_meth_gettimeout(lua_State *L, p_timeout tm);
33
34#ifndef _WIN32
35#pragma GCC visibility pop
36#endif
37
38#define timeout_iszero(tm) ((tm)->block == 0.0)
39
40#endif /* TIMEOUT_H */
diff --git a/vendor/luasocket/src/tp.lua b/vendor/luasocket/src/tp.lua
new file mode 100644
index 00000000..b8ebc56d
--- /dev/null
+++ b/vendor/luasocket/src/tp.lua
@@ -0,0 +1,134 @@
1-----------------------------------------------------------------------------
2-- Unified SMTP/FTP subsystem
3-- LuaSocket toolkit.
4-- Author: Diego Nehab
5-----------------------------------------------------------------------------
6
7-----------------------------------------------------------------------------
8-- Declare module and import dependencies
9-----------------------------------------------------------------------------
10local base = _G
11local string = require("string")
12local socket = require("socket")
13local ltn12 = require("ltn12")
14
15socket.tp = {}
16local _M = socket.tp
17
18-----------------------------------------------------------------------------
19-- Program constants
20-----------------------------------------------------------------------------
21_M.TIMEOUT = 60
22
23-----------------------------------------------------------------------------
24-- Implementation
25-----------------------------------------------------------------------------
26-- gets server reply (works for SMTP and FTP)
27local function get_reply(c)
28 local code, current, sep
29 local line, err = c:receive()
30 local reply = line
31 if err then return nil, err end
32 code, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
33 if not code then return nil, "invalid server reply" end
34 if sep == "-" then -- reply is multiline
35 repeat
36 line, err = c:receive()
37 if err then return nil, err end
38 current, sep = socket.skip(2, string.find(line, "^(%d%d%d)(.?)"))
39 reply = reply .. "\n" .. line
40 -- reply ends with same code
41 until code == current and sep == " "
42 end
43 return code, reply
44end
45
46-- metatable for sock object
47local metat = { __index = {} }
48
49function metat.__index:getpeername()
50 return self.c:getpeername()
51end
52
53function metat.__index:getsockname()
54 return self.c:getpeername()
55end
56
57function metat.__index:check(ok)
58 local code, reply = get_reply(self.c)
59 if not code then return nil, reply end
60 if base.type(ok) ~= "function" then
61 if base.type(ok) == "table" then
62 for i, v in base.ipairs(ok) do
63 if string.find(code, v) then
64 return base.tonumber(code), reply
65 end
66 end
67 return nil, reply
68 else
69 if string.find(code, ok) then return base.tonumber(code), reply
70 else return nil, reply end
71 end
72 else return ok(base.tonumber(code), reply) end
73end
74
75function metat.__index:command(cmd, arg)
76 cmd = string.upper(cmd)
77 if arg then
78 return self.c:send(cmd .. " " .. arg.. "\r\n")
79 else
80 return self.c:send(cmd .. "\r\n")
81 end
82end
83
84function metat.__index:sink(snk, pat)
85 local chunk, err = self.c:receive(pat)
86 return snk(chunk, err)
87end
88
89function metat.__index:send(data)
90 return self.c:send(data)
91end
92
93function metat.__index:receive(pat)
94 return self.c:receive(pat)
95end
96
97function metat.__index:getfd()
98 return self.c:getfd()
99end
100
101function metat.__index:dirty()
102 return self.c:dirty()
103end
104
105function metat.__index:getcontrol()
106 return self.c
107end
108
109function metat.__index:source(source, step)
110 local sink = socket.sink("keep-open", self.c)
111 local ret, err = ltn12.pump.all(source, sink, step or ltn12.pump.step)
112 return ret, err
113end
114
115-- closes the underlying c
116function metat.__index:close()
117 self.c:close()
118 return 1
119end
120
121-- connect with server and return c object
122function _M.connect(host, port, timeout, create)
123 local c, e = (create or socket.tcp)()
124 if not c then return nil, e end
125 c:settimeout(timeout or _M.TIMEOUT)
126 local r, e = c:connect(host, port)
127 if not r then
128 c:close()
129 return nil, e
130 end
131 return base.setmetatable({c = c}, metat)
132end
133
134return _M
diff --git a/vendor/luasocket/src/udp.c b/vendor/luasocket/src/udp.c
new file mode 100755
index 00000000..712ad50f
--- /dev/null
+++ b/vendor/luasocket/src/udp.c
@@ -0,0 +1,488 @@
1/*=========================================================================*\
2* UDP object
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6
7#include "auxiliar.h"
8#include "socket.h"
9#include "inet.h"
10#include "options.h"
11#include "udp.h"
12
13#include <string.h>
14#include <stdlib.h>
15
16/* min and max macros */
17#ifndef MIN
18#define MIN(x, y) ((x) < (y) ? x : y)
19#endif
20#ifndef MAX
21#define MAX(x, y) ((x) > (y) ? x : y)
22#endif
23
24/*=========================================================================*\
25* Internal function prototypes
26\*=========================================================================*/
27static int global_create(lua_State *L);
28static int global_create4(lua_State *L);
29static int global_create6(lua_State *L);
30static int meth_send(lua_State *L);
31static int meth_sendto(lua_State *L);
32static int meth_receive(lua_State *L);
33static int meth_receivefrom(lua_State *L);
34static int meth_getfamily(lua_State *L);
35static int meth_getsockname(lua_State *L);
36static int meth_getpeername(lua_State *L);
37static int meth_gettimeout(lua_State *L);
38static int meth_setsockname(lua_State *L);
39static int meth_setpeername(lua_State *L);
40static int meth_close(lua_State *L);
41static int meth_setoption(lua_State *L);
42static int meth_getoption(lua_State *L);
43static int meth_settimeout(lua_State *L);
44static int meth_getfd(lua_State *L);
45static int meth_setfd(lua_State *L);
46static int meth_dirty(lua_State *L);
47
48/* udp object methods */
49static luaL_Reg udp_methods[] = {
50 {"__gc", meth_close},
51 {"__tostring", auxiliar_tostring},
52 {"close", meth_close},
53 {"dirty", meth_dirty},
54 {"getfamily", meth_getfamily},
55 {"getfd", meth_getfd},
56 {"getpeername", meth_getpeername},
57 {"getsockname", meth_getsockname},
58 {"receive", meth_receive},
59 {"receivefrom", meth_receivefrom},
60 {"send", meth_send},
61 {"sendto", meth_sendto},
62 {"setfd", meth_setfd},
63 {"setoption", meth_setoption},
64 {"getoption", meth_getoption},
65 {"setpeername", meth_setpeername},
66 {"setsockname", meth_setsockname},
67 {"settimeout", meth_settimeout},
68 {"gettimeout", meth_gettimeout},
69 {NULL, NULL}
70};
71
72/* socket options for setoption */
73static t_opt optset[] = {
74 {"dontroute", opt_set_dontroute},
75 {"broadcast", opt_set_broadcast},
76 {"reuseaddr", opt_set_reuseaddr},
77 {"reuseport", opt_set_reuseport},
78 {"ip-multicast-if", opt_set_ip_multicast_if},
79 {"ip-multicast-ttl", opt_set_ip_multicast_ttl},
80 {"ip-multicast-loop", opt_set_ip_multicast_loop},
81 {"ip-add-membership", opt_set_ip_add_membership},
82 {"ip-drop-membership", opt_set_ip_drop_membersip},
83 {"ipv6-unicast-hops", opt_set_ip6_unicast_hops},
84 {"ipv6-multicast-hops", opt_set_ip6_unicast_hops},
85 {"ipv6-multicast-loop", opt_set_ip6_multicast_loop},
86 {"ipv6-add-membership", opt_set_ip6_add_membership},
87 {"ipv6-drop-membership", opt_set_ip6_drop_membersip},
88 {"ipv6-v6only", opt_set_ip6_v6only},
89 {"recv-buffer-size", opt_set_recv_buf_size},
90 {"send-buffer-size", opt_set_send_buf_size},
91 {NULL, NULL}
92};
93
94/* socket options for getoption */
95static t_opt optget[] = {
96 {"dontroute", opt_get_dontroute},
97 {"broadcast", opt_get_broadcast},
98 {"reuseaddr", opt_get_reuseaddr},
99 {"reuseport", opt_get_reuseport},
100 {"ip-multicast-if", opt_get_ip_multicast_if},
101 {"ip-multicast-loop", opt_get_ip_multicast_loop},
102 {"error", opt_get_error},
103 {"ipv6-unicast-hops", opt_get_ip6_unicast_hops},
104 {"ipv6-multicast-hops", opt_get_ip6_unicast_hops},
105 {"ipv6-multicast-loop", opt_get_ip6_multicast_loop},
106 {"ipv6-v6only", opt_get_ip6_v6only},
107 {"recv-buffer-size", opt_get_recv_buf_size},
108 {"send-buffer-size", opt_get_send_buf_size},
109 {NULL, NULL}
110};
111
112/* functions in library namespace */
113static luaL_Reg func[] = {
114 {"udp", global_create},
115 {"udp4", global_create4},
116 {"udp6", global_create6},
117 {NULL, NULL}
118};
119
120/*-------------------------------------------------------------------------*\
121* Initializes module
122\*-------------------------------------------------------------------------*/
123int udp_open(lua_State *L) {
124 /* create classes */
125 auxiliar_newclass(L, "udp{connected}", udp_methods);
126 auxiliar_newclass(L, "udp{unconnected}", udp_methods);
127 /* create class groups */
128 auxiliar_add2group(L, "udp{connected}", "udp{any}");
129 auxiliar_add2group(L, "udp{unconnected}", "udp{any}");
130 auxiliar_add2group(L, "udp{connected}", "select{able}");
131 auxiliar_add2group(L, "udp{unconnected}", "select{able}");
132 /* define library functions */
133 luaL_setfuncs(L, func, 0);
134 /* export default UDP size */
135 lua_pushliteral(L, "_DATAGRAMSIZE");
136 lua_pushinteger(L, UDP_DATAGRAMSIZE);
137 lua_rawset(L, -3);
138 return 0;
139}
140
141/*=========================================================================*\
142* Lua methods
143\*=========================================================================*/
144static const char *udp_strerror(int err) {
145 /* a 'closed' error on an unconnected means the target address was not
146 * accepted by the transport layer */
147 if (err == IO_CLOSED) return "refused";
148 else return socket_strerror(err);
149}
150
151/*-------------------------------------------------------------------------*\
152* Send data through connected udp socket
153\*-------------------------------------------------------------------------*/
154static int meth_send(lua_State *L) {
155 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1);
156 p_timeout tm = &udp->tm;
157 size_t count, sent = 0;
158 int err;
159 const char *data = luaL_checklstring(L, 2, &count);
160 timeout_markstart(tm);
161 err = socket_send(&udp->sock, data, count, &sent, tm);
162 if (err != IO_DONE) {
163 lua_pushnil(L);
164 lua_pushstring(L, udp_strerror(err));
165 return 2;
166 }
167 lua_pushnumber(L, (lua_Number) sent);
168 return 1;
169}
170
171/*-------------------------------------------------------------------------*\
172* Send data through unconnected udp socket
173\*-------------------------------------------------------------------------*/
174static int meth_sendto(lua_State *L) {
175 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
176 size_t count, sent = 0;
177 const char *data = luaL_checklstring(L, 2, &count);
178 const char *ip = luaL_checkstring(L, 3);
179 const char *port = luaL_checkstring(L, 4);
180 p_timeout tm = &udp->tm;
181 int err;
182 struct addrinfo aihint;
183 struct addrinfo *ai;
184 memset(&aihint, 0, sizeof(aihint));
185 aihint.ai_family = udp->family;
186 aihint.ai_socktype = SOCK_DGRAM;
187 aihint.ai_flags = AI_NUMERICHOST;
188#ifdef AI_NUMERICSERV
189 aihint.ai_flags |= AI_NUMERICSERV;
190#endif
191 err = getaddrinfo(ip, port, &aihint, &ai);
192 if (err) {
193 lua_pushnil(L);
194 lua_pushstring(L, LUA_GAI_STRERROR(err));
195 return 2;
196 }
197
198 /* create socket if on first sendto if AF_UNSPEC was set */
199 if (udp->family == AF_UNSPEC && udp->sock == SOCKET_INVALID) {
200 struct addrinfo *ap;
201 const char *errstr = NULL;
202 for (ap = ai; ap != NULL; ap = ap->ai_next) {
203 errstr = inet_trycreate(&udp->sock, ap->ai_family, SOCK_DGRAM, 0);
204 if (errstr == NULL) {
205 socket_setnonblocking(&udp->sock);
206 udp->family = ap->ai_family;
207 break;
208 }
209 }
210 if (errstr != NULL) {
211 lua_pushnil(L);
212 lua_pushstring(L, errstr);
213 freeaddrinfo(ai);
214 return 2;
215 }
216 }
217
218 timeout_markstart(tm);
219 err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr,
220 (socklen_t) ai->ai_addrlen, tm);
221 freeaddrinfo(ai);
222 if (err != IO_DONE) {
223 lua_pushnil(L);
224 lua_pushstring(L, udp_strerror(err));
225 return 2;
226 }
227 lua_pushnumber(L, (lua_Number) sent);
228 return 1;
229}
230
231/*-------------------------------------------------------------------------*\
232* Receives data from a UDP socket
233\*-------------------------------------------------------------------------*/
234static int meth_receive(lua_State *L) {
235 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
236 char buf[UDP_DATAGRAMSIZE];
237 size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
238 char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
239 int err;
240 p_timeout tm = &udp->tm;
241 timeout_markstart(tm);
242 if (!dgram) {
243 lua_pushnil(L);
244 lua_pushliteral(L, "out of memory");
245 return 2;
246 }
247 err = socket_recv(&udp->sock, dgram, wanted, &got, tm);
248 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
249 if (err != IO_DONE && err != IO_CLOSED) {
250 lua_pushnil(L);
251 lua_pushstring(L, udp_strerror(err));
252 if (wanted > sizeof(buf)) free(dgram);
253 return 2;
254 }
255 lua_pushlstring(L, dgram, got);
256 if (wanted > sizeof(buf)) free(dgram);
257 return 1;
258}
259
260/*-------------------------------------------------------------------------*\
261* Receives data and sender from a UDP socket
262\*-------------------------------------------------------------------------*/
263static int meth_receivefrom(lua_State *L) {
264 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
265 char buf[UDP_DATAGRAMSIZE];
266 size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
267 char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
268 struct sockaddr_storage addr;
269 socklen_t addr_len = sizeof(addr);
270 char addrstr[INET6_ADDRSTRLEN];
271 char portstr[6];
272 int err;
273 p_timeout tm = &udp->tm;
274 timeout_markstart(tm);
275 if (!dgram) {
276 lua_pushnil(L);
277 lua_pushliteral(L, "out of memory");
278 return 2;
279 }
280 err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr,
281 &addr_len, tm);
282 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
283 if (err != IO_DONE && err != IO_CLOSED) {
284 lua_pushnil(L);
285 lua_pushstring(L, udp_strerror(err));
286 if (wanted > sizeof(buf)) free(dgram);
287 return 2;
288 }
289 err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
290 INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV);
291 if (err) {
292 lua_pushnil(L);
293 lua_pushstring(L, LUA_GAI_STRERROR(err));
294 if (wanted > sizeof(buf)) free(dgram);
295 return 2;
296 }
297 lua_pushlstring(L, dgram, got);
298 lua_pushstring(L, addrstr);
299 lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10));
300 if (wanted > sizeof(buf)) free(dgram);
301 return 3;
302}
303
304/*-------------------------------------------------------------------------*\
305* Returns family as string
306\*-------------------------------------------------------------------------*/
307static int meth_getfamily(lua_State *L) {
308 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
309 if (udp->family == AF_INET6) {
310 lua_pushliteral(L, "inet6");
311 return 1;
312 } else {
313 lua_pushliteral(L, "inet4");
314 return 1;
315 }
316}
317
318/*-------------------------------------------------------------------------*\
319* Select support methods
320\*-------------------------------------------------------------------------*/
321static int meth_getfd(lua_State *L) {
322 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
323 lua_pushnumber(L, (int) udp->sock);
324 return 1;
325}
326
327/* this is very dangerous, but can be handy for those that are brave enough */
328static int meth_setfd(lua_State *L) {
329 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
330 udp->sock = (t_socket) luaL_checknumber(L, 2);
331 return 0;
332}
333
334static int meth_dirty(lua_State *L) {
335 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
336 (void) udp;
337 lua_pushboolean(L, 0);
338 return 1;
339}
340
341/*-------------------------------------------------------------------------*\
342* Just call inet methods
343\*-------------------------------------------------------------------------*/
344static int meth_getpeername(lua_State *L) {
345 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1);
346 return inet_meth_getpeername(L, &udp->sock, udp->family);
347}
348
349static int meth_getsockname(lua_State *L) {
350 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
351 return inet_meth_getsockname(L, &udp->sock, udp->family);
352}
353
354/*-------------------------------------------------------------------------*\
355* Just call option handler
356\*-------------------------------------------------------------------------*/
357static int meth_setoption(lua_State *L) {
358 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
359 return opt_meth_setoption(L, optset, &udp->sock);
360}
361
362/*-------------------------------------------------------------------------*\
363* Just call option handler
364\*-------------------------------------------------------------------------*/
365static int meth_getoption(lua_State *L) {
366 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
367 return opt_meth_getoption(L, optget, &udp->sock);
368}
369
370/*-------------------------------------------------------------------------*\
371* Just call tm methods
372\*-------------------------------------------------------------------------*/
373static int meth_settimeout(lua_State *L) {
374 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
375 return timeout_meth_settimeout(L, &udp->tm);
376}
377
378static int meth_gettimeout(lua_State *L) {
379 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
380 return timeout_meth_gettimeout(L, &udp->tm);
381}
382
383/*-------------------------------------------------------------------------*\
384* Turns a master udp object into a client object.
385\*-------------------------------------------------------------------------*/
386static int meth_setpeername(lua_State *L) {
387 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
388 p_timeout tm = &udp->tm;
389 const char *address = luaL_checkstring(L, 2);
390 int connecting = strcmp(address, "*");
391 const char *port = connecting? luaL_checkstring(L, 3): "0";
392 struct addrinfo connecthints;
393 const char *err;
394 memset(&connecthints, 0, sizeof(connecthints));
395 connecthints.ai_socktype = SOCK_DGRAM;
396 /* make sure we try to connect only to the same family */
397 connecthints.ai_family = udp->family;
398 if (connecting) {
399 err = inet_tryconnect(&udp->sock, &udp->family, address,
400 port, tm, &connecthints);
401 if (err) {
402 lua_pushnil(L);
403 lua_pushstring(L, err);
404 return 2;
405 }
406 auxiliar_setclass(L, "udp{connected}", 1);
407 } else {
408 /* we ignore possible errors because Mac OS X always
409 * returns EAFNOSUPPORT */
410 inet_trydisconnect(&udp->sock, udp->family, tm);
411 auxiliar_setclass(L, "udp{unconnected}", 1);
412 }
413 lua_pushnumber(L, 1);
414 return 1;
415}
416
417/*-------------------------------------------------------------------------*\
418* Closes socket used by object
419\*-------------------------------------------------------------------------*/
420static int meth_close(lua_State *L) {
421 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
422 socket_destroy(&udp->sock);
423 lua_pushnumber(L, 1);
424 return 1;
425}
426
427/*-------------------------------------------------------------------------*\
428* Turns a master object into a server object
429\*-------------------------------------------------------------------------*/
430static int meth_setsockname(lua_State *L) {
431 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
432 const char *address = luaL_checkstring(L, 2);
433 const char *port = luaL_checkstring(L, 3);
434 const char *err;
435 struct addrinfo bindhints;
436 memset(&bindhints, 0, sizeof(bindhints));
437 bindhints.ai_socktype = SOCK_DGRAM;
438 bindhints.ai_family = udp->family;
439 bindhints.ai_flags = AI_PASSIVE;
440 err = inet_trybind(&udp->sock, &udp->family, address, port, &bindhints);
441 if (err) {
442 lua_pushnil(L);
443 lua_pushstring(L, err);
444 return 2;
445 }
446 lua_pushnumber(L, 1);
447 return 1;
448}
449
450/*=========================================================================*\
451* Library functions
452\*=========================================================================*/
453/*-------------------------------------------------------------------------*\
454* Creates a master udp object
455\*-------------------------------------------------------------------------*/
456static int udp_create(lua_State *L, int family) {
457 /* allocate udp object */
458 p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
459 auxiliar_setclass(L, "udp{unconnected}", -1);
460 /* if family is AF_UNSPEC, we leave the socket invalid and
461 * store AF_UNSPEC into family. This will allow it to later be
462 * replaced with an AF_INET6 or AF_INET socket upon first use. */
463 udp->sock = SOCKET_INVALID;
464 timeout_init(&udp->tm, -1, -1);
465 udp->family = family;
466 if (family != AF_UNSPEC) {
467 const char *err = inet_trycreate(&udp->sock, family, SOCK_DGRAM, 0);
468 if (err != NULL) {
469 lua_pushnil(L);
470 lua_pushstring(L, err);
471 return 2;
472 }
473 socket_setnonblocking(&udp->sock);
474 }
475 return 1;
476}
477
478static int global_create(lua_State *L) {
479 return udp_create(L, AF_UNSPEC);
480}
481
482static int global_create4(lua_State *L) {
483 return udp_create(L, AF_INET);
484}
485
486static int global_create6(lua_State *L) {
487 return udp_create(L, AF_INET6);
488}
diff --git a/vendor/luasocket/src/udp.h b/vendor/luasocket/src/udp.h
new file mode 100644
index 00000000..07d5247f
--- /dev/null
+++ b/vendor/luasocket/src/udp.h
@@ -0,0 +1,39 @@
1#ifndef UDP_H
2#define UDP_H
3/*=========================================================================*\
4* UDP object
5* LuaSocket toolkit
6*
7* The udp.h module provides LuaSocket with support for UDP protocol
8* (AF_INET, SOCK_DGRAM).
9*
10* Two classes are defined: connected and unconnected. UDP objects are
11* originally unconnected. They can be "connected" to a given address
12* with a call to the setpeername function. The same function can be used to
13* break the connection.
14\*=========================================================================*/
15#include "luasocket.h"
16
17#include "timeout.h"
18#include "socket.h"
19
20#define UDP_DATAGRAMSIZE 8192
21
22typedef struct t_udp_ {
23 t_socket sock;
24 t_timeout tm;
25 int family;
26} t_udp;
27typedef t_udp *p_udp;
28
29#ifndef _WIN32
30#pragma GCC visibility push(hidden)
31#endif
32
33int udp_open(lua_State *L);
34
35#ifndef _WIN32
36#pragma GCC visibility pop
37#endif
38
39#endif /* UDP_H */
diff --git a/vendor/luasocket/src/unix.c b/vendor/luasocket/src/unix.c
new file mode 100644
index 00000000..268d8b21
--- /dev/null
+++ b/vendor/luasocket/src/unix.c
@@ -0,0 +1,69 @@
1/*=========================================================================*\
2* Unix domain socket
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6
7#include "unixstream.h"
8#include "unixdgram.h"
9
10/*-------------------------------------------------------------------------*\
11* Modules and functions
12\*-------------------------------------------------------------------------*/
13static const luaL_Reg mod[] = {
14 {"stream", unixstream_open},
15 {"dgram", unixdgram_open},
16 {NULL, NULL}
17};
18
19static void add_alias(lua_State *L, int index, const char *name, const char *target)
20{
21 lua_getfield(L, index, target);
22 lua_setfield(L, index, name);
23}
24
25static int compat_socket_unix_call(lua_State *L)
26{
27 /* Look up socket.unix.stream in the socket.unix table (which is the first
28 * argument). */
29 lua_getfield(L, 1, "stream");
30
31 /* Replace the stack entry for the socket.unix table with the
32 * socket.unix.stream function. */
33 lua_replace(L, 1);
34
35 /* Call socket.unix.stream, passing along any arguments. */
36 int n = lua_gettop(L);
37 lua_call(L, n-1, LUA_MULTRET);
38
39 /* Pass along the return values from socket.unix.stream. */
40 n = lua_gettop(L);
41 return n;
42}
43
44/*-------------------------------------------------------------------------*\
45* Initializes module
46\*-------------------------------------------------------------------------*/
47LUASOCKET_API int luaopen_socket_unix(lua_State *L)
48{
49 int i;
50 lua_newtable(L);
51 int socket_unix_table = lua_gettop(L);
52
53 for (i = 0; mod[i].name; i++)
54 mod[i].func(L);
55
56 /* Add backwards compatibility aliases "tcp" and "udp" for the "stream" and
57 * "dgram" functions. */
58 add_alias(L, socket_unix_table, "tcp", "stream");
59 add_alias(L, socket_unix_table, "udp", "dgram");
60
61 /* Add a backwards compatibility function and a metatable setup to call it
62 * for the old socket.unix() interface. */
63 lua_pushcfunction(L, compat_socket_unix_call);
64 lua_setfield(L, socket_unix_table, "__call");
65 lua_pushvalue(L, socket_unix_table);
66 lua_setmetatable(L, socket_unix_table);
67
68 return 1;
69}
diff --git a/vendor/luasocket/src/unix.h b/vendor/luasocket/src/unix.h
new file mode 100644
index 00000000..c2035618
--- /dev/null
+++ b/vendor/luasocket/src/unix.h
@@ -0,0 +1,26 @@
1#ifndef UNIX_H
2#define UNIX_H
3/*=========================================================================*\
4* Unix domain object
5* LuaSocket toolkit
6*
7* This module is just an example of how to extend LuaSocket with a new
8* domain.
9\*=========================================================================*/
10#include "luasocket.h"
11
12#include "buffer.h"
13#include "timeout.h"
14#include "socket.h"
15
16typedef struct t_unix_ {
17 t_socket sock;
18 t_io io;
19 t_buffer buf;
20 t_timeout tm;
21} t_unix;
22typedef t_unix *p_unix;
23
24LUASOCKET_API int luaopen_socket_unix(lua_State *L);
25
26#endif /* UNIX_H */
diff --git a/vendor/luasocket/src/unixdgram.c b/vendor/luasocket/src/unixdgram.c
new file mode 100644
index 00000000..69093d73
--- /dev/null
+++ b/vendor/luasocket/src/unixdgram.c
@@ -0,0 +1,405 @@
1/*=========================================================================*\
2* Unix domain socket dgram submodule
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6
7#include "auxiliar.h"
8#include "socket.h"
9#include "options.h"
10#include "unix.h"
11
12#include <string.h>
13#include <stdlib.h>
14
15#include <sys/un.h>
16
17#define UNIXDGRAM_DATAGRAMSIZE 8192
18
19/* provide a SUN_LEN macro if sys/un.h doesn't (e.g. Android) */
20#ifndef SUN_LEN
21#define SUN_LEN(ptr) \
22 ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
23 + strlen ((ptr)->sun_path))
24#endif
25
26/*=========================================================================*\
27* Internal function prototypes
28\*=========================================================================*/
29static int global_create(lua_State *L);
30static int meth_connect(lua_State *L);
31static int meth_bind(lua_State *L);
32static int meth_send(lua_State *L);
33static int meth_receive(lua_State *L);
34static int meth_close(lua_State *L);
35static int meth_setoption(lua_State *L);
36static int meth_settimeout(lua_State *L);
37static int meth_gettimeout(lua_State *L);
38static int meth_getfd(lua_State *L);
39static int meth_setfd(lua_State *L);
40static int meth_dirty(lua_State *L);
41static int meth_receivefrom(lua_State *L);
42static int meth_sendto(lua_State *L);
43static int meth_getsockname(lua_State *L);
44
45static const char *unixdgram_tryconnect(p_unix un, const char *path);
46static const char *unixdgram_trybind(p_unix un, const char *path);
47
48/* unixdgram object methods */
49static luaL_Reg unixdgram_methods[] = {
50 {"__gc", meth_close},
51 {"__tostring", auxiliar_tostring},
52 {"bind", meth_bind},
53 {"close", meth_close},
54 {"connect", meth_connect},
55 {"dirty", meth_dirty},
56 {"getfd", meth_getfd},
57 {"send", meth_send},
58 {"sendto", meth_sendto},
59 {"receive", meth_receive},
60 {"receivefrom", meth_receivefrom},
61 {"setfd", meth_setfd},
62 {"setoption", meth_setoption},
63 {"setpeername", meth_connect},
64 {"setsockname", meth_bind},
65 {"getsockname", meth_getsockname},
66 {"settimeout", meth_settimeout},
67 {"gettimeout", meth_gettimeout},
68 {NULL, NULL}
69};
70
71/* socket option handlers */
72static t_opt optset[] = {
73 {"reuseaddr", opt_set_reuseaddr},
74 {NULL, NULL}
75};
76
77/* functions in library namespace */
78static luaL_Reg func[] = {
79 {"dgram", global_create},
80 {NULL, NULL}
81};
82
83/*-------------------------------------------------------------------------*\
84* Initializes module
85\*-------------------------------------------------------------------------*/
86int unixdgram_open(lua_State *L)
87{
88 /* create classes */
89 auxiliar_newclass(L, "unixdgram{connected}", unixdgram_methods);
90 auxiliar_newclass(L, "unixdgram{unconnected}", unixdgram_methods);
91 /* create class groups */
92 auxiliar_add2group(L, "unixdgram{connected}", "unixdgram{any}");
93 auxiliar_add2group(L, "unixdgram{unconnected}", "unixdgram{any}");
94 auxiliar_add2group(L, "unixdgram{connected}", "select{able}");
95 auxiliar_add2group(L, "unixdgram{unconnected}", "select{able}");
96
97 luaL_setfuncs(L, func, 0);
98 return 0;
99}
100
101/*=========================================================================*\
102* Lua methods
103\*=========================================================================*/
104static const char *unixdgram_strerror(int err)
105{
106 /* a 'closed' error on an unconnected means the target address was not
107 * accepted by the transport layer */
108 if (err == IO_CLOSED) return "refused";
109 else return socket_strerror(err);
110}
111
112static int meth_send(lua_State *L)
113{
114 p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{connected}", 1);
115 p_timeout tm = &un->tm;
116 size_t count, sent = 0;
117 int err;
118 const char *data = luaL_checklstring(L, 2, &count);
119 timeout_markstart(tm);
120 err = socket_send(&un->sock, data, count, &sent, tm);
121 if (err != IO_DONE) {
122 lua_pushnil(L);
123 lua_pushstring(L, unixdgram_strerror(err));
124 return 2;
125 }
126 lua_pushnumber(L, (lua_Number) sent);
127 return 1;
128}
129
130/*-------------------------------------------------------------------------*\
131* Send data through unconnected unixdgram socket
132\*-------------------------------------------------------------------------*/
133static int meth_sendto(lua_State *L)
134{
135 p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
136 size_t count, sent = 0;
137 const char *data = luaL_checklstring(L, 2, &count);
138 const char *path = luaL_checkstring(L, 3);
139 p_timeout tm = &un->tm;
140 int err;
141 struct sockaddr_un remote;
142 size_t len = strlen(path);
143
144 if (len >= sizeof(remote.sun_path)) {
145 lua_pushnil(L);
146 lua_pushstring(L, "path too long");
147 return 2;
148 }
149
150 memset(&remote, 0, sizeof(remote));
151 strcpy(remote.sun_path, path);
152 remote.sun_family = AF_UNIX;
153 timeout_markstart(tm);
154#ifdef UNIX_HAS_SUN_LEN
155 remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
156 + len + 1;
157 err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote, remote.sun_len, tm);
158#else
159 err = socket_sendto(&un->sock, data, count, &sent, (SA *) &remote,
160 sizeof(remote.sun_family) + len, tm);
161#endif
162 if (err != IO_DONE) {
163 lua_pushnil(L);
164 lua_pushstring(L, unixdgram_strerror(err));
165 return 2;
166 }
167 lua_pushnumber(L, (lua_Number) sent);
168 return 1;
169}
170
171static int meth_receive(lua_State *L) {
172 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
173 char buf[UNIXDGRAM_DATAGRAMSIZE];
174 size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
175 char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
176 int err;
177 p_timeout tm = &un->tm;
178 timeout_markstart(tm);
179 if (!dgram) {
180 lua_pushnil(L);
181 lua_pushliteral(L, "out of memory");
182 return 2;
183 }
184 err = socket_recv(&un->sock, dgram, wanted, &got, tm);
185 /* Unlike STREAM, recv() of zero is not closed, but a zero-length packet. */
186 if (err != IO_DONE && err != IO_CLOSED) {
187 lua_pushnil(L);
188 lua_pushstring(L, unixdgram_strerror(err));
189 if (wanted > sizeof(buf)) free(dgram);
190 return 2;
191 }
192 lua_pushlstring(L, dgram, got);
193 if (wanted > sizeof(buf)) free(dgram);
194 return 1;
195}
196
197/*-------------------------------------------------------------------------*\
198* Receives data and sender from a DGRAM socket
199\*-------------------------------------------------------------------------*/
200static int meth_receivefrom(lua_State *L) {
201 p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
202 char buf[UNIXDGRAM_DATAGRAMSIZE];
203 size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
204 char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
205 struct sockaddr_un addr;
206 socklen_t addr_len = sizeof(addr);
207 int err;
208 p_timeout tm = &un->tm;
209 timeout_markstart(tm);
210 if (!dgram) {
211 lua_pushnil(L);
212 lua_pushliteral(L, "out of memory");
213 return 2;
214 }
215 addr.sun_path[0] = '\0';
216 err = socket_recvfrom(&un->sock, dgram, wanted, &got, (SA *) &addr,
217 &addr_len, tm);
218 /* Unlike STREAM, recv() of zero is not closed, but a zero-length packet. */
219 if (err != IO_DONE && err != IO_CLOSED) {
220 lua_pushnil(L);
221 lua_pushstring(L, unixdgram_strerror(err));
222 if (wanted > sizeof(buf)) free(dgram);
223 return 2;
224 }
225
226 lua_pushlstring(L, dgram, got);
227 /* the path may be empty, when client send without bind */
228 lua_pushstring(L, addr.sun_path);
229 if (wanted > sizeof(buf)) free(dgram);
230 return 2;
231}
232
233/*-------------------------------------------------------------------------*\
234* Just call option handler
235\*-------------------------------------------------------------------------*/
236static int meth_setoption(lua_State *L) {
237 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
238 return opt_meth_setoption(L, optset, &un->sock);
239}
240
241/*-------------------------------------------------------------------------*\
242* Select support methods
243\*-------------------------------------------------------------------------*/
244static int meth_getfd(lua_State *L) {
245 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
246 lua_pushnumber(L, (int) un->sock);
247 return 1;
248}
249
250/* this is very dangerous, but can be handy for those that are brave enough */
251static int meth_setfd(lua_State *L) {
252 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
253 un->sock = (t_socket) luaL_checknumber(L, 2);
254 return 0;
255}
256
257static int meth_dirty(lua_State *L) {
258 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
259 (void) un;
260 lua_pushboolean(L, 0);
261 return 1;
262}
263
264/*-------------------------------------------------------------------------*\
265* Binds an object to an address
266\*-------------------------------------------------------------------------*/
267static const char *unixdgram_trybind(p_unix un, const char *path) {
268 struct sockaddr_un local;
269 size_t len = strlen(path);
270 if (len >= sizeof(local.sun_path)) return "path too long";
271 memset(&local, 0, sizeof(local));
272 strcpy(local.sun_path, path);
273 local.sun_family = AF_UNIX;
274 size_t addrlen = SUN_LEN(&local);
275#ifdef UNIX_HAS_SUN_LEN
276 local.sun_len = addrlen + 1;
277#endif
278 int err = socket_bind(&un->sock, (SA *) &local, addrlen);
279 if (err != IO_DONE) socket_destroy(&un->sock);
280 return socket_strerror(err);
281}
282
283static int meth_bind(lua_State *L)
284{
285 p_unix un = (p_unix) auxiliar_checkclass(L, "unixdgram{unconnected}", 1);
286 const char *path = luaL_checkstring(L, 2);
287 const char *err = unixdgram_trybind(un, path);
288 if (err) {
289 lua_pushnil(L);
290 lua_pushstring(L, err);
291 return 2;
292 }
293 lua_pushnumber(L, 1);
294 return 1;
295}
296
297static int meth_getsockname(lua_State *L)
298{
299 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
300 struct sockaddr_un peer = {0};
301 socklen_t peer_len = sizeof(peer);
302
303 if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) {
304 lua_pushnil(L);
305 lua_pushstring(L, socket_strerror(errno));
306 return 2;
307 }
308
309 lua_pushstring(L, peer.sun_path);
310 return 1;
311}
312
313/*-------------------------------------------------------------------------*\
314* Turns a master unixdgram object into a client object.
315\*-------------------------------------------------------------------------*/
316static const char *unixdgram_tryconnect(p_unix un, const char *path)
317{
318 struct sockaddr_un remote;
319 size_t len = strlen(path);
320 if (len >= sizeof(remote.sun_path)) return "path too long";
321 memset(&remote, 0, sizeof(remote));
322 strcpy(remote.sun_path, path);
323 remote.sun_family = AF_UNIX;
324 timeout_markstart(&un->tm);
325 size_t addrlen = SUN_LEN(&remote);
326#ifdef UNIX_HAS_SUN_LEN
327 remote.sun_len = addrlen + 1;
328#endif
329 int err = socket_connect(&un->sock, (SA *) &remote, addrlen, &un->tm);
330 if (err != IO_DONE) socket_destroy(&un->sock);
331 return socket_strerror(err);
332}
333
334static int meth_connect(lua_State *L)
335{
336 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
337 const char *path = luaL_checkstring(L, 2);
338 const char *err = unixdgram_tryconnect(un, path);
339 if (err) {
340 lua_pushnil(L);
341 lua_pushstring(L, err);
342 return 2;
343 }
344 /* turn unconnected object into a connected object */
345 auxiliar_setclass(L, "unixdgram{connected}", 1);
346 lua_pushnumber(L, 1);
347 return 1;
348}
349
350/*-------------------------------------------------------------------------*\
351* Closes socket used by object
352\*-------------------------------------------------------------------------*/
353static int meth_close(lua_State *L)
354{
355 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
356 socket_destroy(&un->sock);
357 lua_pushnumber(L, 1);
358 return 1;
359}
360
361/*-------------------------------------------------------------------------*\
362* Just call tm methods
363\*-------------------------------------------------------------------------*/
364static int meth_settimeout(lua_State *L)
365{
366 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
367 return timeout_meth_settimeout(L, &un->tm);
368}
369
370static int meth_gettimeout(lua_State *L)
371{
372 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixdgram{any}", 1);
373 return timeout_meth_gettimeout(L, &un->tm);
374}
375
376/*=========================================================================*\
377* Library functions
378\*=========================================================================*/
379/*-------------------------------------------------------------------------*\
380* Creates a master unixdgram object
381\*-------------------------------------------------------------------------*/
382static int global_create(lua_State *L)
383{
384 t_socket sock;
385 int err = socket_create(&sock, AF_UNIX, SOCK_DGRAM, 0);
386 /* try to allocate a system socket */
387 if (err == IO_DONE) {
388 /* allocate unixdgram object */
389 p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
390 /* set its type as master object */
391 auxiliar_setclass(L, "unixdgram{unconnected}", -1);
392 /* initialize remaining structure fields */
393 socket_setnonblocking(&sock);
394 un->sock = sock;
395 io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
396 (p_error) socket_ioerror, &un->sock);
397 timeout_init(&un->tm, -1, -1);
398 buffer_init(&un->buf, &un->io, &un->tm);
399 return 1;
400 } else {
401 lua_pushnil(L);
402 lua_pushstring(L, socket_strerror(err));
403 return 2;
404 }
405}
diff --git a/vendor/luasocket/src/unixdgram.h b/vendor/luasocket/src/unixdgram.h
new file mode 100644
index 00000000..a1a0166b
--- /dev/null
+++ b/vendor/luasocket/src/unixdgram.h
@@ -0,0 +1,28 @@
1#ifndef UNIXDGRAM_H
2#define UNIXDGRAM_H
3/*=========================================================================*\
4* DGRAM object
5* LuaSocket toolkit
6*
7* The dgram.h module provides LuaSocket with support for DGRAM protocol
8* (AF_INET, SOCK_DGRAM).
9*
10* Two classes are defined: connected and unconnected. DGRAM objects are
11* originally unconnected. They can be "connected" to a given address
12* with a call to the setpeername function. The same function can be used to
13* break the connection.
14\*=========================================================================*/
15
16#include "unix.h"
17
18#ifndef _WIN32
19#pragma GCC visibility push(hidden)
20#endif
21
22int unixdgram_open(lua_State *L);
23
24#ifndef _WIN32
25#pragma GCC visibility pop
26#endif
27
28#endif /* UNIXDGRAM_H */
diff --git a/vendor/luasocket/src/unixstream.c b/vendor/luasocket/src/unixstream.c
new file mode 100644
index 00000000..02aced9c
--- /dev/null
+++ b/vendor/luasocket/src/unixstream.c
@@ -0,0 +1,355 @@
1/*=========================================================================*\
2* Unix domain socket stream sub module
3* LuaSocket toolkit
4\*=========================================================================*/
5#include "luasocket.h"
6
7#include "auxiliar.h"
8#include "socket.h"
9#include "options.h"
10#include "unixstream.h"
11
12#include <string.h>
13#include <sys/un.h>
14
15/*=========================================================================*\
16* Internal function prototypes
17\*=========================================================================*/
18static int global_create(lua_State *L);
19static int meth_connect(lua_State *L);
20static int meth_listen(lua_State *L);
21static int meth_bind(lua_State *L);
22static int meth_send(lua_State *L);
23static int meth_shutdown(lua_State *L);
24static int meth_receive(lua_State *L);
25static int meth_accept(lua_State *L);
26static int meth_close(lua_State *L);
27static int meth_setoption(lua_State *L);
28static int meth_settimeout(lua_State *L);
29static int meth_getfd(lua_State *L);
30static int meth_setfd(lua_State *L);
31static int meth_dirty(lua_State *L);
32static int meth_getstats(lua_State *L);
33static int meth_setstats(lua_State *L);
34static int meth_getsockname(lua_State *L);
35
36static const char *unixstream_tryconnect(p_unix un, const char *path);
37static const char *unixstream_trybind(p_unix un, const char *path);
38
39/* unixstream object methods */
40static luaL_Reg unixstream_methods[] = {
41 {"__gc", meth_close},
42 {"__tostring", auxiliar_tostring},
43 {"accept", meth_accept},
44 {"bind", meth_bind},
45 {"close", meth_close},
46 {"connect", meth_connect},
47 {"dirty", meth_dirty},
48 {"getfd", meth_getfd},
49 {"getstats", meth_getstats},
50 {"setstats", meth_setstats},
51 {"listen", meth_listen},
52 {"receive", meth_receive},
53 {"send", meth_send},
54 {"setfd", meth_setfd},
55 {"setoption", meth_setoption},
56 {"setpeername", meth_connect},
57 {"setsockname", meth_bind},
58 {"getsockname", meth_getsockname},
59 {"settimeout", meth_settimeout},
60 {"shutdown", meth_shutdown},
61 {NULL, NULL}
62};
63
64/* socket option handlers */
65static t_opt optset[] = {
66 {"keepalive", opt_set_keepalive},
67 {"reuseaddr", opt_set_reuseaddr},
68 {"linger", opt_set_linger},
69 {NULL, NULL}
70};
71
72/* functions in library namespace */
73static luaL_Reg func[] = {
74 {"stream", global_create},
75 {NULL, NULL}
76};
77
78/*-------------------------------------------------------------------------*\
79* Initializes module
80\*-------------------------------------------------------------------------*/
81int unixstream_open(lua_State *L)
82{
83 /* create classes */
84 auxiliar_newclass(L, "unixstream{master}", unixstream_methods);
85 auxiliar_newclass(L, "unixstream{client}", unixstream_methods);
86 auxiliar_newclass(L, "unixstream{server}", unixstream_methods);
87
88 /* create class groups */
89 auxiliar_add2group(L, "unixstream{master}", "unixstream{any}");
90 auxiliar_add2group(L, "unixstream{client}", "unixstream{any}");
91 auxiliar_add2group(L, "unixstream{server}", "unixstream{any}");
92
93 luaL_setfuncs(L, func, 0);
94 return 0;
95}
96
97/*=========================================================================*\
98* Lua methods
99\*=========================================================================*/
100/*-------------------------------------------------------------------------*\
101* Just call buffered IO methods
102\*-------------------------------------------------------------------------*/
103static int meth_send(lua_State *L) {
104 p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1);
105 return buffer_meth_send(L, &un->buf);
106}
107
108static int meth_receive(lua_State *L) {
109 p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1);
110 return buffer_meth_receive(L, &un->buf);
111}
112
113static int meth_getstats(lua_State *L) {
114 p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1);
115 return buffer_meth_getstats(L, &un->buf);
116}
117
118static int meth_setstats(lua_State *L) {
119 p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1);
120 return buffer_meth_setstats(L, &un->buf);
121}
122
123/*-------------------------------------------------------------------------*\
124* Just call option handler
125\*-------------------------------------------------------------------------*/
126static int meth_setoption(lua_State *L) {
127 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
128 return opt_meth_setoption(L, optset, &un->sock);
129}
130
131/*-------------------------------------------------------------------------*\
132* Select support methods
133\*-------------------------------------------------------------------------*/
134static int meth_getfd(lua_State *L) {
135 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
136 lua_pushnumber(L, (int) un->sock);
137 return 1;
138}
139
140/* this is very dangerous, but can be handy for those that are brave enough */
141static int meth_setfd(lua_State *L) {
142 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
143 un->sock = (t_socket) luaL_checknumber(L, 2);
144 return 0;
145}
146
147static int meth_dirty(lua_State *L) {
148 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
149 lua_pushboolean(L, !buffer_isempty(&un->buf));
150 return 1;
151}
152
153/*-------------------------------------------------------------------------*\
154* Waits for and returns a client object attempting connection to the
155* server object
156\*-------------------------------------------------------------------------*/
157static int meth_accept(lua_State *L) {
158 p_unix server = (p_unix) auxiliar_checkclass(L, "unixstream{server}", 1);
159 p_timeout tm = timeout_markstart(&server->tm);
160 t_socket sock;
161 int err = socket_accept(&server->sock, &sock, NULL, NULL, tm);
162 /* if successful, push client socket */
163 if (err == IO_DONE) {
164 p_unix clnt = (p_unix) lua_newuserdata(L, sizeof(t_unix));
165 auxiliar_setclass(L, "unixstream{client}", -1);
166 /* initialize structure fields */
167 socket_setnonblocking(&sock);
168 clnt->sock = sock;
169 io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv,
170 (p_error) socket_ioerror, &clnt->sock);
171 timeout_init(&clnt->tm, -1, -1);
172 buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
173 return 1;
174 } else {
175 lua_pushnil(L);
176 lua_pushstring(L, socket_strerror(err));
177 return 2;
178 }
179}
180
181/*-------------------------------------------------------------------------*\
182* Binds an object to an address
183\*-------------------------------------------------------------------------*/
184static const char *unixstream_trybind(p_unix un, const char *path) {
185 struct sockaddr_un local;
186 size_t len = strlen(path);
187 int err;
188 if (len >= sizeof(local.sun_path)) return "path too long";
189 memset(&local, 0, sizeof(local));
190 strcpy(local.sun_path, path);
191 local.sun_family = AF_UNIX;
192#ifdef UNIX_HAS_SUN_LEN
193 local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
194 + len + 1;
195 err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
196
197#else
198 err = socket_bind(&un->sock, (SA *) &local,
199 sizeof(local.sun_family) + len);
200#endif
201 if (err != IO_DONE) socket_destroy(&un->sock);
202 return socket_strerror(err);
203}
204
205static int meth_bind(lua_State *L) {
206 p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1);
207 const char *path = luaL_checkstring(L, 2);
208 const char *err = unixstream_trybind(un, path);
209 if (err) {
210 lua_pushnil(L);
211 lua_pushstring(L, err);
212 return 2;
213 }
214 lua_pushnumber(L, 1);
215 return 1;
216}
217
218static int meth_getsockname(lua_State *L)
219{
220 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
221 struct sockaddr_un peer = {0};
222 socklen_t peer_len = sizeof(peer);
223
224 if (getsockname(un->sock, (SA *) &peer, &peer_len) < 0) {
225 lua_pushnil(L);
226 lua_pushstring(L, socket_strerror(errno));
227 return 2;
228 }
229
230 lua_pushstring(L, peer.sun_path);
231 return 1;
232}
233
234/*-------------------------------------------------------------------------*\
235* Turns a master unixstream object into a client object.
236\*-------------------------------------------------------------------------*/
237static const char *unixstream_tryconnect(p_unix un, const char *path)
238{
239 struct sockaddr_un remote;
240 int err;
241 size_t len = strlen(path);
242 if (len >= sizeof(remote.sun_path)) return "path too long";
243 memset(&remote, 0, sizeof(remote));
244 strcpy(remote.sun_path, path);
245 remote.sun_family = AF_UNIX;
246 timeout_markstart(&un->tm);
247#ifdef UNIX_HAS_SUN_LEN
248 remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
249 + len + 1;
250 err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
251#else
252 err = socket_connect(&un->sock, (SA *) &remote,
253 sizeof(remote.sun_family) + len, &un->tm);
254#endif
255 if (err != IO_DONE) socket_destroy(&un->sock);
256 return socket_strerror(err);
257}
258
259static int meth_connect(lua_State *L)
260{
261 p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1);
262 const char *path = luaL_checkstring(L, 2);
263 const char *err = unixstream_tryconnect(un, path);
264 if (err) {
265 lua_pushnil(L);
266 lua_pushstring(L, err);
267 return 2;
268 }
269 /* turn master object into a client object */
270 auxiliar_setclass(L, "unixstream{client}", 1);
271 lua_pushnumber(L, 1);
272 return 1;
273}
274
275/*-------------------------------------------------------------------------*\
276* Closes socket used by object
277\*-------------------------------------------------------------------------*/
278static int meth_close(lua_State *L)
279{
280 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
281 socket_destroy(&un->sock);
282 lua_pushnumber(L, 1);
283 return 1;
284}
285
286/*-------------------------------------------------------------------------*\
287* Puts the sockt in listen mode
288\*-------------------------------------------------------------------------*/
289static int meth_listen(lua_State *L)
290{
291 p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1);
292 int backlog = (int) luaL_optnumber(L, 2, 32);
293 int err = socket_listen(&un->sock, backlog);
294 if (err != IO_DONE) {
295 lua_pushnil(L);
296 lua_pushstring(L, socket_strerror(err));
297 return 2;
298 }
299 /* turn master object into a server object */
300 auxiliar_setclass(L, "unixstream{server}", 1);
301 lua_pushnumber(L, 1);
302 return 1;
303}
304
305/*-------------------------------------------------------------------------*\
306* Shuts the connection down partially
307\*-------------------------------------------------------------------------*/
308static int meth_shutdown(lua_State *L)
309{
310 /* SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, so we can use method index directly */
311 static const char* methods[] = { "receive", "send", "both", NULL };
312 p_unix stream = (p_unix) auxiliar_checkclass(L, "unixstream{client}", 1);
313 int how = luaL_checkoption(L, 2, "both", methods);
314 socket_shutdown(&stream->sock, how);
315 lua_pushnumber(L, 1);
316 return 1;
317}
318
319/*-------------------------------------------------------------------------*\
320* Just call tm methods
321\*-------------------------------------------------------------------------*/
322static int meth_settimeout(lua_State *L) {
323 p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1);
324 return timeout_meth_settimeout(L, &un->tm);
325}
326
327/*=========================================================================*\
328* Library functions
329\*=========================================================================*/
330/*-------------------------------------------------------------------------*\
331* Creates a master unixstream object
332\*-------------------------------------------------------------------------*/
333static int global_create(lua_State *L) {
334 t_socket sock;
335 int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0);
336 /* try to allocate a system socket */
337 if (err == IO_DONE) {
338 /* allocate unixstream object */
339 p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
340 /* set its type as master object */
341 auxiliar_setclass(L, "unixstream{master}", -1);
342 /* initialize remaining structure fields */
343 socket_setnonblocking(&sock);
344 un->sock = sock;
345 io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
346 (p_error) socket_ioerror, &un->sock);
347 timeout_init(&un->tm, -1, -1);
348 buffer_init(&un->buf, &un->io, &un->tm);
349 return 1;
350 } else {
351 lua_pushnil(L);
352 lua_pushstring(L, socket_strerror(err));
353 return 2;
354 }
355}
diff --git a/vendor/luasocket/src/unixstream.h b/vendor/luasocket/src/unixstream.h
new file mode 100644
index 00000000..7916affa
--- /dev/null
+++ b/vendor/luasocket/src/unixstream.h
@@ -0,0 +1,29 @@
1#ifndef UNIXSTREAM_H
2#define UNIXSTREAM_H
3/*=========================================================================*\
4* UNIX STREAM object
5* LuaSocket toolkit
6*
7* The unixstream.h module is basicly a glue that puts together modules buffer.h,
8* timeout.h socket.h and inet.h to provide the LuaSocket UNIX STREAM (AF_UNIX,
9* SOCK_STREAM) support.
10*
11* Three classes are defined: master, client and server. The master class is
12* a newly created unixstream object, that has not been bound or connected. Server
13* objects are unixstream objects bound to some local address. Client objects are
14* unixstream objects either connected to some address or returned by the accept
15* method of a server object.
16\*=========================================================================*/
17#include "unix.h"
18
19#ifndef _WIN32
20#pragma GCC visibility push(hidden)
21#endif
22
23int unixstream_open(lua_State *L);
24
25#ifndef _WIN32
26#pragma GCC visibility pop
27#endif
28
29#endif /* UNIXSTREAM_H */
diff --git a/vendor/luasocket/src/url.lua b/vendor/luasocket/src/url.lua
new file mode 100644
index 00000000..8e0dc5ce
--- /dev/null
+++ b/vendor/luasocket/src/url.lua
@@ -0,0 +1,331 @@
1-----------------------------------------------------------------------------
2-- URI parsing, composition and relative URL resolution
3-- LuaSocket toolkit.
4-- Author: Diego Nehab
5-----------------------------------------------------------------------------
6
7-----------------------------------------------------------------------------
8-- Declare module
9-----------------------------------------------------------------------------
10local string = require("string")
11local base = _G
12local table = require("table")
13local socket = require("socket")
14
15socket.url = {}
16local _M = socket.url
17
18-----------------------------------------------------------------------------
19-- Module version
20-----------------------------------------------------------------------------
21_M._VERSION = "URL 1.0.3"
22
23-----------------------------------------------------------------------------
24-- Encodes a string into its escaped hexadecimal representation
25-- Input
26-- s: binary string to be encoded
27-- Returns
28-- escaped representation of string binary
29-----------------------------------------------------------------------------
30function _M.escape(s)
31 return (string.gsub(s, "([^A-Za-z0-9_])", function(c)
32 return string.format("%%%02x", string.byte(c))
33 end))
34end
35
36-----------------------------------------------------------------------------
37-- Protects a path segment, to prevent it from interfering with the
38-- url parsing.
39-- Input
40-- s: binary string to be encoded
41-- Returns
42-- escaped representation of string binary
43-----------------------------------------------------------------------------
44local function make_set(t)
45 local s = {}
46 for i,v in base.ipairs(t) do
47 s[t[i]] = 1
48 end
49 return s
50end
51
52-- these are allowed within a path segment, along with alphanum
53-- other characters must be escaped
54local segment_set = make_set {
55 "-", "_", ".", "!", "~", "*", "'", "(",
56 ")", ":", "@", "&", "=", "+", "$", ",",
57}
58
59local function protect_segment(s)
60 return string.gsub(s, "([^A-Za-z0-9_])", function (c)
61 if segment_set[c] then return c
62 else return string.format("%%%02X", string.byte(c)) end
63 end)
64end
65
66-----------------------------------------------------------------------------
67-- Unencodes a escaped hexadecimal string into its binary representation
68-- Input
69-- s: escaped hexadecimal string to be unencoded
70-- Returns
71-- unescaped binary representation of escaped hexadecimal binary
72-----------------------------------------------------------------------------
73function _M.unescape(s)
74 return (string.gsub(s, "%%(%x%x)", function(hex)
75 return string.char(base.tonumber(hex, 16))
76 end))
77end
78
79-----------------------------------------------------------------------------
80-- Removes '..' and '.' components appropriately from a path.
81-- Input
82-- path
83-- Returns
84-- dot-normalized path
85local function remove_dot_components(path)
86 local marker = string.char(1)
87 repeat
88 local was = path
89 path = path:gsub('//', '/'..marker..'/', 1)
90 until path == was
91 repeat
92 local was = path
93 path = path:gsub('/%./', '/', 1)
94 until path == was
95 repeat
96 local was = path
97 path = path:gsub('[^/]+/%.%./([^/]+)', '%1', 1)
98 until path == was
99 path = path:gsub('[^/]+/%.%./*$', '')
100 path = path:gsub('/%.%.$', '/')
101 path = path:gsub('/%.$', '/')
102 path = path:gsub('^/%.%./', '/')
103 path = path:gsub(marker, '')
104 return path
105end
106
107-----------------------------------------------------------------------------
108-- Builds a path from a base path and a relative path
109-- Input
110-- base_path
111-- relative_path
112-- Returns
113-- corresponding absolute path
114-----------------------------------------------------------------------------
115local function absolute_path(base_path, relative_path)
116 if string.sub(relative_path, 1, 1) == "/" then
117 return remove_dot_components(relative_path) end
118 base_path = base_path:gsub("[^/]*$", "")
119 if not base_path:find'/$' then base_path = base_path .. '/' end
120 local path = base_path .. relative_path
121 path = remove_dot_components(path)
122 return path
123end
124
125-----------------------------------------------------------------------------
126-- Parses a url and returns a table with all its parts according to RFC 2396
127-- The following grammar describes the names given to the URL parts
128-- <url> ::= <scheme>://<authority>/<path>;<params>?<query>#<fragment>
129-- <authority> ::= <userinfo>@<host>:<port>
130-- <userinfo> ::= <user>[:<password>]
131-- <path> :: = {<segment>/}<segment>
132-- Input
133-- url: uniform resource locator of request
134-- default: table with default values for each field
135-- Returns
136-- table with the following fields, where RFC naming conventions have
137-- been preserved:
138-- scheme, authority, userinfo, user, password, host, port,
139-- path, params, query, fragment
140-- Obs:
141-- the leading '/' in {/<path>} is considered part of <path>
142-----------------------------------------------------------------------------
143function _M.parse(url, default)
144 -- initialize default parameters
145 local parsed = {}
146 for i,v in base.pairs(default or parsed) do parsed[i] = v end
147 -- empty url is parsed to nil
148 if not url or url == "" then return nil, "invalid url" end
149 -- remove whitespace
150 -- url = string.gsub(url, "%s", "")
151 -- get scheme
152 url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
153 function(s) parsed.scheme = s; return "" end)
154 -- get authority
155 url = string.gsub(url, "^//([^/]*)", function(n)
156 parsed.authority = n
157 return ""
158 end)
159 -- get fragment
160 url = string.gsub(url, "#(.*)$", function(f)
161 parsed.fragment = f
162 return ""
163 end)
164 -- get query string
165 url = string.gsub(url, "%?(.*)", function(q)
166 parsed.query = q
167 return ""
168 end)
169 -- get params
170 url = string.gsub(url, "%;(.*)", function(p)
171 parsed.params = p
172 return ""
173 end)
174 -- path is whatever was left
175 if url ~= "" then parsed.path = url end
176 local authority = parsed.authority
177 if not authority then return parsed end
178 authority = string.gsub(authority,"^([^@]*)@",
179 function(u) parsed.userinfo = u; return "" end)
180 authority = string.gsub(authority, ":([^:%]]*)$",
181 function(p) parsed.port = p; return "" end)
182 if authority ~= "" then
183 -- IPv6?
184 parsed.host = string.match(authority, "^%[(.+)%]$") or authority
185 end
186 local userinfo = parsed.userinfo
187 if not userinfo then return parsed end
188 userinfo = string.gsub(userinfo, ":([^:]*)$",
189 function(p) parsed.password = p; return "" end)
190 parsed.user = userinfo
191 return parsed
192end
193
194-----------------------------------------------------------------------------
195-- Rebuilds a parsed URL from its components.
196-- Components are protected if any reserved or unallowed characters are found
197-- Input
198-- parsed: parsed URL, as returned by parse
199-- Returns
200-- a stringing with the corresponding URL
201-----------------------------------------------------------------------------
202function _M.build(parsed)
203 --local ppath = _M.parse_path(parsed.path or "")
204 --local url = _M.build_path(ppath)
205 local url = parsed.path or ""
206 if parsed.params then url = url .. ";" .. parsed.params end
207 if parsed.query then url = url .. "?" .. parsed.query end
208 local authority = parsed.authority
209 if parsed.host then
210 authority = parsed.host
211 if string.find(authority, ":") then -- IPv6?
212 authority = "[" .. authority .. "]"
213 end
214 if parsed.port then authority = authority .. ":" .. base.tostring(parsed.port) end
215 local userinfo = parsed.userinfo
216 if parsed.user then
217 userinfo = parsed.user
218 if parsed.password then
219 userinfo = userinfo .. ":" .. parsed.password
220 end
221 end
222 if userinfo then authority = userinfo .. "@" .. authority end
223 end
224 if authority then url = "//" .. authority .. url end
225 if parsed.scheme then url = parsed.scheme .. ":" .. url end
226 if parsed.fragment then url = url .. "#" .. parsed.fragment end
227 -- url = string.gsub(url, "%s", "")
228 return url
229end
230
231-----------------------------------------------------------------------------
232-- Builds a absolute URL from a base and a relative URL according to RFC 2396
233-- Input
234-- base_url
235-- relative_url
236-- Returns
237-- corresponding absolute url
238-----------------------------------------------------------------------------
239function _M.absolute(base_url, relative_url)
240 local base_parsed
241 if base.type(base_url) == "table" then
242 base_parsed = base_url
243 base_url = _M.build(base_parsed)
244 else
245 base_parsed = _M.parse(base_url)
246 end
247 local result
248 local relative_parsed = _M.parse(relative_url)
249 if not base_parsed then
250 result = relative_url
251 elseif not relative_parsed then
252 result = base_url
253 elseif relative_parsed.scheme then
254 result = relative_url
255 else
256 relative_parsed.scheme = base_parsed.scheme
257 if not relative_parsed.authority then
258 relative_parsed.authority = base_parsed.authority
259 if not relative_parsed.path then
260 relative_parsed.path = base_parsed.path
261 if not relative_parsed.params then
262 relative_parsed.params = base_parsed.params
263 if not relative_parsed.query then
264 relative_parsed.query = base_parsed.query
265 end
266 end
267 else
268 relative_parsed.path = absolute_path(base_parsed.path or "",
269 relative_parsed.path)
270 end
271 end
272 result = _M.build(relative_parsed)
273 end
274 return remove_dot_components(result)
275end
276
277-----------------------------------------------------------------------------
278-- Breaks a path into its segments, unescaping the segments
279-- Input
280-- path
281-- Returns
282-- segment: a table with one entry per segment
283-----------------------------------------------------------------------------
284function _M.parse_path(path)
285 local parsed = {}
286 path = path or ""
287 --path = string.gsub(path, "%s", "")
288 string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
289 for i = 1, #parsed do
290 parsed[i] = _M.unescape(parsed[i])
291 end
292 if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
293 if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
294 return parsed
295end
296
297-----------------------------------------------------------------------------
298-- Builds a path component from its segments, escaping protected characters.
299-- Input
300-- parsed: path segments
301-- unsafe: if true, segments are not protected before path is built
302-- Returns
303-- path: corresponding path stringing
304-----------------------------------------------------------------------------
305function _M.build_path(parsed, unsafe)
306 local path = ""
307 local n = #parsed
308 if unsafe then
309 for i = 1, n-1 do
310 path = path .. parsed[i]
311 path = path .. "/"
312 end
313 if n > 0 then
314 path = path .. parsed[n]
315 if parsed.is_directory then path = path .. "/" end
316 end
317 else
318 for i = 1, n-1 do
319 path = path .. protect_segment(parsed[i])
320 path = path .. "/"
321 end
322 if n > 0 then
323 path = path .. protect_segment(parsed[n])
324 if parsed.is_directory then path = path .. "/" end
325 end
326 end
327 if parsed.is_absolute then path = "/" .. path end
328 return path
329end
330
331return _M
diff --git a/vendor/luasocket/src/usocket.c b/vendor/luasocket/src/usocket.c
new file mode 100644
index 00000000..69635daa
--- /dev/null
+++ b/vendor/luasocket/src/usocket.c
@@ -0,0 +1,454 @@
1/*=========================================================================*\
2* Socket compatibilization module for Unix
3* LuaSocket toolkit
4*
5* The code is now interrupt-safe.
6* The penalty of calling select to avoid busy-wait is only paid when
7* the I/O call fail in the first place.
8\*=========================================================================*/
9#include "luasocket.h"
10
11#include "socket.h"
12#include "pierror.h"
13
14#include <string.h>
15#include <signal.h>
16
17/*-------------------------------------------------------------------------*\
18* Wait for readable/writable/connected socket with timeout
19\*-------------------------------------------------------------------------*/
20#ifndef SOCKET_SELECT
21#include <sys/poll.h>
22
23#define WAITFD_R POLLIN
24#define WAITFD_W POLLOUT
25#define WAITFD_C (POLLIN|POLLOUT)
26int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
27 int ret;
28 struct pollfd pfd;
29 pfd.fd = *ps;
30 pfd.events = sw;
31 pfd.revents = 0;
32 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
33 do {
34 int t = (int)(timeout_getretry(tm)*1e3);
35 ret = poll(&pfd, 1, t >= 0? t: -1);
36 } while (ret == -1 && errno == EINTR);
37 if (ret == -1) return errno;
38 if (ret == 0) return IO_TIMEOUT;
39 if (sw == WAITFD_C && (pfd.revents & (POLLIN|POLLERR))) return IO_CLOSED;
40 return IO_DONE;
41}
42#else
43
44#define WAITFD_R 1
45#define WAITFD_W 2
46#define WAITFD_C (WAITFD_R|WAITFD_W)
47
48int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
49 int ret;
50 fd_set rfds, wfds, *rp, *wp;
51 struct timeval tv, *tp;
52 double t;
53 if (*ps >= FD_SETSIZE) return EINVAL;
54 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
55 do {
56 /* must set bits within loop, because select may have modifed them */
57 rp = wp = NULL;
58 if (sw & WAITFD_R) { FD_ZERO(&rfds); FD_SET(*ps, &rfds); rp = &rfds; }
59 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
60 t = timeout_getretry(tm);
61 tp = NULL;
62 if (t >= 0.0) {
63 tv.tv_sec = (int)t;
64 tv.tv_usec = (int)((t-tv.tv_sec)*1.0e6);
65 tp = &tv;
66 }
67 ret = select(*ps+1, rp, wp, NULL, tp);
68 } while (ret == -1 && errno == EINTR);
69 if (ret == -1) return errno;
70 if (ret == 0) return IO_TIMEOUT;
71 if (sw == WAITFD_C && FD_ISSET(*ps, &rfds)) return IO_CLOSED;
72 return IO_DONE;
73}
74#endif
75
76
77/*-------------------------------------------------------------------------*\
78* Initializes module
79\*-------------------------------------------------------------------------*/
80int socket_open(void) {
81 /* installs a handler to ignore sigpipe or it will crash us */
82 signal(SIGPIPE, SIG_IGN);
83 return 1;
84}
85
86/*-------------------------------------------------------------------------*\
87* Close module
88\*-------------------------------------------------------------------------*/
89int socket_close(void) {
90 return 1;
91}
92
93/*-------------------------------------------------------------------------*\
94* Close and inutilize socket
95\*-------------------------------------------------------------------------*/
96void socket_destroy(p_socket ps) {
97 if (*ps != SOCKET_INVALID) {
98 close(*ps);
99 *ps = SOCKET_INVALID;
100 }
101}
102
103/*-------------------------------------------------------------------------*\
104* Select with timeout control
105\*-------------------------------------------------------------------------*/
106int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
107 p_timeout tm) {
108 int ret;
109 do {
110 struct timeval tv;
111 double t = timeout_getretry(tm);
112 tv.tv_sec = (int) t;
113 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
114 /* timeout = 0 means no wait */
115 ret = select(n, rfds, wfds, efds, t >= 0.0 ? &tv: NULL);
116 } while (ret < 0 && errno == EINTR);
117 return ret;
118}
119
120/*-------------------------------------------------------------------------*\
121* Creates and sets up a socket
122\*-------------------------------------------------------------------------*/
123int socket_create(p_socket ps, int domain, int type, int protocol) {
124 *ps = socket(domain, type, protocol);
125 if (*ps != SOCKET_INVALID) return IO_DONE;
126 else return errno;
127}
128
129/*-------------------------------------------------------------------------*\
130* Binds or returns error message
131\*-------------------------------------------------------------------------*/
132int socket_bind(p_socket ps, SA *addr, socklen_t len) {
133 int err = IO_DONE;
134 socket_setblocking(ps);
135 if (bind(*ps, addr, len) < 0) err = errno;
136 socket_setnonblocking(ps);
137 return err;
138}
139
140/*-------------------------------------------------------------------------*\
141*
142\*-------------------------------------------------------------------------*/
143int socket_listen(p_socket ps, int backlog) {
144 int err = IO_DONE;
145 if (listen(*ps, backlog)) err = errno;
146 return err;
147}
148
149/*-------------------------------------------------------------------------*\
150*
151\*-------------------------------------------------------------------------*/
152void socket_shutdown(p_socket ps, int how) {
153 shutdown(*ps, how);
154}
155
156/*-------------------------------------------------------------------------*\
157* Connects or returns error message
158\*-------------------------------------------------------------------------*/
159int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
160 int err;
161 /* avoid calling on closed sockets */
162 if (*ps == SOCKET_INVALID) return IO_CLOSED;
163 /* call connect until done or failed without being interrupted */
164 do if (connect(*ps, addr, len) == 0) return IO_DONE;
165 while ((err = errno) == EINTR);
166 /* if connection failed immediately, return error code */
167 if (err != EINPROGRESS && err != EAGAIN) return err;
168 /* zero timeout case optimization */
169 if (timeout_iszero(tm)) return IO_TIMEOUT;
170 /* wait until we have the result of the connection attempt or timeout */
171 err = socket_waitfd(ps, WAITFD_C, tm);
172 if (err == IO_CLOSED) {
173 if (recv(*ps, (char *) &err, 0, 0) == 0) return IO_DONE;
174 else return errno;
175 } else return err;
176}
177
178/*-------------------------------------------------------------------------*\
179* Accept with timeout
180\*-------------------------------------------------------------------------*/
181int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len, p_timeout tm) {
182 if (*ps == SOCKET_INVALID) return IO_CLOSED;
183 for ( ;; ) {
184 int err;
185 if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE;
186 err = errno;
187 if (err == EINTR) continue;
188 if (err != EAGAIN && err != ECONNABORTED) return err;
189 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
190 }
191 /* can't reach here */
192 return IO_UNKNOWN;
193}
194
195/*-------------------------------------------------------------------------*\
196* Send with timeout
197\*-------------------------------------------------------------------------*/
198int socket_send(p_socket ps, const char *data, size_t count,
199 size_t *sent, p_timeout tm)
200{
201 int err;
202 *sent = 0;
203 /* avoid making system calls on closed sockets */
204 if (*ps == SOCKET_INVALID) return IO_CLOSED;
205 /* loop until we send something or we give up on error */
206 for ( ;; ) {
207 long put = (long) send(*ps, data, count, 0);
208 /* if we sent anything, we are done */
209 if (put >= 0) {
210 *sent = put;
211 return IO_DONE;
212 }
213 err = errno;
214 /* EPIPE means the connection was closed */
215 if (err == EPIPE) return IO_CLOSED;
216 /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/
217 if (err == EPROTOTYPE) continue;
218 /* we call was interrupted, just try again */
219 if (err == EINTR) continue;
220 /* if failed fatal reason, report error */
221 if (err != EAGAIN) return err;
222 /* wait until we can send something or we timeout */
223 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
224 }
225 /* can't reach here */
226 return IO_UNKNOWN;
227}
228
229/*-------------------------------------------------------------------------*\
230* Sendto with timeout
231\*-------------------------------------------------------------------------*/
232int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
233 SA *addr, socklen_t len, p_timeout tm)
234{
235 int err;
236 *sent = 0;
237 if (*ps == SOCKET_INVALID) return IO_CLOSED;
238 for ( ;; ) {
239 long put = (long) sendto(*ps, data, count, 0, addr, len);
240 if (put >= 0) {
241 *sent = put;
242 return IO_DONE;
243 }
244 err = errno;
245 if (err == EPIPE) return IO_CLOSED;
246 if (err == EPROTOTYPE) continue;
247 if (err == EINTR) continue;
248 if (err != EAGAIN) return err;
249 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
250 }
251 return IO_UNKNOWN;
252}
253
254/*-------------------------------------------------------------------------*\
255* Receive with timeout
256\*-------------------------------------------------------------------------*/
257int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) {
258 int err;
259 *got = 0;
260 if (*ps == SOCKET_INVALID) return IO_CLOSED;
261 for ( ;; ) {
262 long taken = (long) recv(*ps, data, count, 0);
263 if (taken > 0) {
264 *got = taken;
265 return IO_DONE;
266 }
267 err = errno;
268 if (taken == 0) return IO_CLOSED;
269 if (err == EINTR) continue;
270 if (err != EAGAIN) return err;
271 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
272 }
273 return IO_UNKNOWN;
274}
275
276/*-------------------------------------------------------------------------*\
277* Recvfrom with timeout
278\*-------------------------------------------------------------------------*/
279int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
280 SA *addr, socklen_t *len, p_timeout tm) {
281 int err;
282 *got = 0;
283 if (*ps == SOCKET_INVALID) return IO_CLOSED;
284 for ( ;; ) {
285 long taken = (long) recvfrom(*ps, data, count, 0, addr, len);
286 if (taken > 0) {
287 *got = taken;
288 return IO_DONE;
289 }
290 err = errno;
291 if (taken == 0) return IO_CLOSED;
292 if (err == EINTR) continue;
293 if (err != EAGAIN) return err;
294 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
295 }
296 return IO_UNKNOWN;
297}
298
299
300/*-------------------------------------------------------------------------*\
301* Write with timeout
302*
303* socket_read and socket_write are cut-n-paste of socket_send and socket_recv,
304* with send/recv replaced with write/read. We can't just use write/read
305* in the socket version, because behaviour when size is zero is different.
306\*-------------------------------------------------------------------------*/
307int socket_write(p_socket ps, const char *data, size_t count,
308 size_t *sent, p_timeout tm)
309{
310 int err;
311 *sent = 0;
312 /* avoid making system calls on closed sockets */
313 if (*ps == SOCKET_INVALID) return IO_CLOSED;
314 /* loop until we send something or we give up on error */
315 for ( ;; ) {
316 long put = (long) write(*ps, data, count);
317 /* if we sent anything, we are done */
318 if (put >= 0) {
319 *sent = put;
320 return IO_DONE;
321 }
322 err = errno;
323 /* EPIPE means the connection was closed */
324 if (err == EPIPE) return IO_CLOSED;
325 /* EPROTOTYPE means the connection is being closed (on Yosemite!)*/
326 if (err == EPROTOTYPE) continue;
327 /* we call was interrupted, just try again */
328 if (err == EINTR) continue;
329 /* if failed fatal reason, report error */
330 if (err != EAGAIN) return err;
331 /* wait until we can send something or we timeout */
332 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
333 }
334 /* can't reach here */
335 return IO_UNKNOWN;
336}
337
338/*-------------------------------------------------------------------------*\
339* Read with timeout
340* See note for socket_write
341\*-------------------------------------------------------------------------*/
342int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) {
343 int err;
344 *got = 0;
345 if (*ps == SOCKET_INVALID) return IO_CLOSED;
346 for ( ;; ) {
347 long taken = (long) read(*ps, data, count);
348 if (taken > 0) {
349 *got = taken;
350 return IO_DONE;
351 }
352 err = errno;
353 if (taken == 0) return IO_CLOSED;
354 if (err == EINTR) continue;
355 if (err != EAGAIN) return err;
356 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
357 }
358 return IO_UNKNOWN;
359}
360
361/*-------------------------------------------------------------------------*\
362* Put socket into blocking mode
363\*-------------------------------------------------------------------------*/
364void socket_setblocking(p_socket ps) {
365 int flags = fcntl(*ps, F_GETFL, 0);
366 flags &= (~(O_NONBLOCK));
367 fcntl(*ps, F_SETFL, flags);
368}
369
370/*-------------------------------------------------------------------------*\
371* Put socket into non-blocking mode
372\*-------------------------------------------------------------------------*/
373void socket_setnonblocking(p_socket ps) {
374 int flags = fcntl(*ps, F_GETFL, 0);
375 flags |= O_NONBLOCK;
376 fcntl(*ps, F_SETFL, flags);
377}
378
379/*-------------------------------------------------------------------------*\
380* DNS helpers
381\*-------------------------------------------------------------------------*/
382int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
383 *hp = gethostbyaddr(addr, len, AF_INET);
384 if (*hp) return IO_DONE;
385 else if (h_errno) return h_errno;
386 else if (errno) return errno;
387 else return IO_UNKNOWN;
388}
389
390int socket_gethostbyname(const char *addr, struct hostent **hp) {
391 *hp = gethostbyname(addr);
392 if (*hp) return IO_DONE;
393 else if (h_errno) return h_errno;
394 else if (errno) return errno;
395 else return IO_UNKNOWN;
396}
397
398/*-------------------------------------------------------------------------*\
399* Error translation functions
400* Make sure important error messages are standard
401\*-------------------------------------------------------------------------*/
402const char *socket_hoststrerror(int err) {
403 if (err <= 0) return io_strerror(err);
404 switch (err) {
405 case HOST_NOT_FOUND: return PIE_HOST_NOT_FOUND;
406 default: return hstrerror(err);
407 }
408}
409
410const char *socket_strerror(int err) {
411 if (err <= 0) return io_strerror(err);
412 switch (err) {
413 case EADDRINUSE: return PIE_ADDRINUSE;
414 case EISCONN: return PIE_ISCONN;
415 case EACCES: return PIE_ACCESS;
416 case ECONNREFUSED: return PIE_CONNREFUSED;
417 case ECONNABORTED: return PIE_CONNABORTED;
418 case ECONNRESET: return PIE_CONNRESET;
419 case ETIMEDOUT: return PIE_TIMEDOUT;
420 default: {
421 return strerror(err);
422 }
423 }
424}
425
426const char *socket_ioerror(p_socket ps, int err) {
427 (void) ps;
428 return socket_strerror(err);
429}
430
431const char *socket_gaistrerror(int err) {
432 if (err == 0) return NULL;
433 switch (err) {
434 case EAI_AGAIN: return PIE_AGAIN;
435 case EAI_BADFLAGS: return PIE_BADFLAGS;
436#ifdef EAI_BADHINTS
437 case EAI_BADHINTS: return PIE_BADHINTS;
438#endif
439 case EAI_FAIL: return PIE_FAIL;
440 case EAI_FAMILY: return PIE_FAMILY;
441 case EAI_MEMORY: return PIE_MEMORY;
442 case EAI_NONAME: return PIE_NONAME;
443#ifdef EAI_OVERFLOW
444 case EAI_OVERFLOW: return PIE_OVERFLOW;
445#endif
446#ifdef EAI_PROTOCOL
447 case EAI_PROTOCOL: return PIE_PROTOCOL;
448#endif
449 case EAI_SERVICE: return PIE_SERVICE;
450 case EAI_SOCKTYPE: return PIE_SOCKTYPE;
451 case EAI_SYSTEM: return strerror(errno);
452 default: return LUA_GAI_STRERROR(err);
453 }
454}
diff --git a/vendor/luasocket/src/usocket.h b/vendor/luasocket/src/usocket.h
new file mode 100644
index 00000000..45f2f99f
--- /dev/null
+++ b/vendor/luasocket/src/usocket.h
@@ -0,0 +1,59 @@
1#ifndef USOCKET_H
2#define USOCKET_H
3/*=========================================================================*\
4* Socket compatibilization module for Unix
5* LuaSocket toolkit
6\*=========================================================================*/
7
8/*=========================================================================*\
9* BSD include files
10\*=========================================================================*/
11/* error codes */
12#include <errno.h>
13/* close function */
14#include <unistd.h>
15/* fnctnl function and associated constants */
16#include <fcntl.h>
17/* struct sockaddr */
18#include <sys/types.h>
19/* socket function */
20#include <sys/socket.h>
21/* struct timeval */
22#include <sys/time.h>
23/* gethostbyname and gethostbyaddr functions */
24#include <netdb.h>
25/* sigpipe handling */
26#include <signal.h>
27/* IP stuff*/
28#include <netinet/in.h>
29#include <arpa/inet.h>
30/* TCP options (nagle algorithm disable) */
31#include <netinet/tcp.h>
32#include <net/if.h>
33
34#ifndef SO_REUSEPORT
35#define SO_REUSEPORT SO_REUSEADDR
36#endif
37
38/* Some platforms use IPV6_JOIN_GROUP instead if
39 * IPV6_ADD_MEMBERSHIP. The semantics are same, though. */
40#ifndef IPV6_ADD_MEMBERSHIP
41#ifdef IPV6_JOIN_GROUP
42#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
43#endif /* IPV6_JOIN_GROUP */
44#endif /* !IPV6_ADD_MEMBERSHIP */
45
46/* Same with IPV6_DROP_MEMBERSHIP / IPV6_LEAVE_GROUP. */
47#ifndef IPV6_DROP_MEMBERSHIP
48#ifdef IPV6_LEAVE_GROUP
49#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
50#endif /* IPV6_LEAVE_GROUP */
51#endif /* !IPV6_DROP_MEMBERSHIP */
52
53typedef int t_socket;
54typedef t_socket *p_socket;
55typedef struct sockaddr_storage t_sockaddr_storage;
56
57#define SOCKET_INVALID (-1)
58
59#endif /* USOCKET_H */
diff --git a/vendor/luasocket/src/wsocket.c b/vendor/luasocket/src/wsocket.c
new file mode 100755
index 00000000..6cb1e415
--- /dev/null
+++ b/vendor/luasocket/src/wsocket.c
@@ -0,0 +1,434 @@
1/*=========================================================================*\
2* Socket compatibilization module for Win32
3* LuaSocket toolkit
4*
5* The penalty of calling select to avoid busy-wait is only paid when
6* the I/O call fail in the first place.
7\*=========================================================================*/
8#include "luasocket.h"
9
10#include <string.h>
11
12#include "socket.h"
13#include "pierror.h"
14
15/* WinSock doesn't have a strerror... */
16static const char *wstrerror(int err);
17
18/*-------------------------------------------------------------------------*\
19* Initializes module
20\*-------------------------------------------------------------------------*/
21int socket_open(void) {
22 WSADATA wsaData;
23 WORD wVersionRequested = MAKEWORD(2, 0);
24 int err = WSAStartup(wVersionRequested, &wsaData );
25 if (err != 0) return 0;
26 if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) &&
27 (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) {
28 WSACleanup();
29 return 0;
30 }
31 return 1;
32}
33
34/*-------------------------------------------------------------------------*\
35* Close module
36\*-------------------------------------------------------------------------*/
37int socket_close(void) {
38 WSACleanup();
39 return 1;
40}
41
42/*-------------------------------------------------------------------------*\
43* Wait for readable/writable/connected socket with timeout
44\*-------------------------------------------------------------------------*/
45#define WAITFD_R 1
46#define WAITFD_W 2
47#define WAITFD_E 4
48#define WAITFD_C (WAITFD_E|WAITFD_W)
49
50int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
51 int ret;
52 fd_set rfds, wfds, efds, *rp = NULL, *wp = NULL, *ep = NULL;
53 struct timeval tv, *tp = NULL;
54 double t;
55 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
56 if (sw & WAITFD_R) {
57 FD_ZERO(&rfds);
58 FD_SET(*ps, &rfds);
59 rp = &rfds;
60 }
61 if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
62 if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; }
63 if ((t = timeout_get(tm)) >= 0.0) {
64 tv.tv_sec = (int) t;
65 tv.tv_usec = (int) ((t-tv.tv_sec)*1.0e6);
66 tp = &tv;
67 }
68 ret = select(0, rp, wp, ep, tp);
69 if (ret == -1) return WSAGetLastError();
70 if (ret == 0) return IO_TIMEOUT;
71 if (sw == WAITFD_C && FD_ISSET(*ps, &efds)) return IO_CLOSED;
72 return IO_DONE;
73}
74
75/*-------------------------------------------------------------------------*\
76* Select with int timeout in ms
77\*-------------------------------------------------------------------------*/
78int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
79 p_timeout tm) {
80 struct timeval tv;
81 double t = timeout_get(tm);
82 tv.tv_sec = (int) t;
83 tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
84 if (n <= 0) {
85 Sleep((DWORD) (1000*t));
86 return 0;
87 } else return select(0, rfds, wfds, efds, t >= 0.0? &tv: NULL);
88}
89
90/*-------------------------------------------------------------------------*\
91* Close and inutilize socket
92\*-------------------------------------------------------------------------*/
93void socket_destroy(p_socket ps) {
94 if (*ps != SOCKET_INVALID) {
95 socket_setblocking(ps); /* close can take a long time on WIN32 */
96 closesocket(*ps);
97 *ps = SOCKET_INVALID;
98 }
99}
100
101/*-------------------------------------------------------------------------*\
102*
103\*-------------------------------------------------------------------------*/
104void socket_shutdown(p_socket ps, int how) {
105 socket_setblocking(ps);
106 shutdown(*ps, how);
107 socket_setnonblocking(ps);
108}
109
110/*-------------------------------------------------------------------------*\
111* Creates and sets up a socket
112\*-------------------------------------------------------------------------*/
113int socket_create(p_socket ps, int domain, int type, int protocol) {
114 *ps = socket(domain, type, protocol);
115 if (*ps != SOCKET_INVALID) return IO_DONE;
116 else return WSAGetLastError();
117}
118
119/*-------------------------------------------------------------------------*\
120* Connects or returns error message
121\*-------------------------------------------------------------------------*/
122int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
123 int err;
124 /* don't call on closed socket */
125 if (*ps == SOCKET_INVALID) return IO_CLOSED;
126 /* ask system to connect */
127 if (connect(*ps, addr, len) == 0) return IO_DONE;
128 /* make sure the system is trying to connect */
129 err = WSAGetLastError();
130 if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS) return err;
131 /* zero timeout case optimization */
132 if (timeout_iszero(tm)) return IO_TIMEOUT;
133 /* we wait until something happens */
134 err = socket_waitfd(ps, WAITFD_C, tm);
135 if (err == IO_CLOSED) {
136 int elen = sizeof(err);
137 /* give windows time to set the error (yes, disgusting) */
138 Sleep(10);
139 /* find out why we failed */
140 getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &elen);
141 /* we KNOW there was an error. if 'why' is 0, we will return
142 * "unknown error", but it's not really our fault */
143 return err > 0? err: IO_UNKNOWN;
144 } else return err;
145
146}
147
148/*-------------------------------------------------------------------------*\
149* Binds or returns error message
150\*-------------------------------------------------------------------------*/
151int socket_bind(p_socket ps, SA *addr, socklen_t len) {
152 int err = IO_DONE;
153 socket_setblocking(ps);
154 if (bind(*ps, addr, len) < 0) err = WSAGetLastError();
155 socket_setnonblocking(ps);
156 return err;
157}
158
159/*-------------------------------------------------------------------------*\
160*
161\*-------------------------------------------------------------------------*/
162int socket_listen(p_socket ps, int backlog) {
163 int err = IO_DONE;
164 socket_setblocking(ps);
165 if (listen(*ps, backlog) < 0) err = WSAGetLastError();
166 socket_setnonblocking(ps);
167 return err;
168}
169
170/*-------------------------------------------------------------------------*\
171* Accept with timeout
172\*-------------------------------------------------------------------------*/
173int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len,
174 p_timeout tm) {
175 if (*ps == SOCKET_INVALID) return IO_CLOSED;
176 for ( ;; ) {
177 int err;
178 /* try to get client socket */
179 if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE;
180 /* find out why we failed */
181 err = WSAGetLastError();
182 /* if we failed because there was no connectoin, keep trying */
183 if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err;
184 /* call select to avoid busy wait */
185 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
186 }
187}
188
189/*-------------------------------------------------------------------------*\
190* Send with timeout
191* On windows, if you try to send 10MB, the OS will buffer EVERYTHING
192* this can take an awful lot of time and we will end up blocked.
193* Therefore, whoever calls this function should not pass a huge buffer.
194\*-------------------------------------------------------------------------*/
195int socket_send(p_socket ps, const char *data, size_t count,
196 size_t *sent, p_timeout tm)
197{
198 int err;
199 *sent = 0;
200 /* avoid making system calls on closed sockets */
201 if (*ps == SOCKET_INVALID) return IO_CLOSED;
202 /* loop until we send something or we give up on error */
203 for ( ;; ) {
204 /* try to send something */
205 int put = send(*ps, data, (int) count, 0);
206 /* if we sent something, we are done */
207 if (put > 0) {
208 *sent = put;
209 return IO_DONE;
210 }
211 /* deal with failure */
212 err = WSAGetLastError();
213 /* we can only proceed if there was no serious error */
214 if (err != WSAEWOULDBLOCK) return err;
215 /* avoid busy wait */
216 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
217 }
218}
219
220/*-------------------------------------------------------------------------*\
221* Sendto with timeout
222\*-------------------------------------------------------------------------*/
223int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
224 SA *addr, socklen_t len, p_timeout tm)
225{
226 int err;
227 *sent = 0;
228 if (*ps == SOCKET_INVALID) return IO_CLOSED;
229 for ( ;; ) {
230 int put = sendto(*ps, data, (int) count, 0, addr, len);
231 if (put > 0) {
232 *sent = put;
233 return IO_DONE;
234 }
235 err = WSAGetLastError();
236 if (err != WSAEWOULDBLOCK) return err;
237 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
238 }
239}
240
241/*-------------------------------------------------------------------------*\
242* Receive with timeout
243\*-------------------------------------------------------------------------*/
244int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
245 p_timeout tm)
246{
247 int err, prev = IO_DONE;
248 *got = 0;
249 if (*ps == SOCKET_INVALID) return IO_CLOSED;
250 for ( ;; ) {
251 int taken = recv(*ps, data, (int) count, 0);
252 if (taken > 0) {
253 *got = taken;
254 return IO_DONE;
255 }
256 if (taken == 0) return IO_CLOSED;
257 err = WSAGetLastError();
258 /* On UDP, a connreset simply means the previous send failed.
259 * So we try again.
260 * On TCP, it means our socket is now useless, so the error passes.
261 * (We will loop again, exiting because the same error will happen) */
262 if (err != WSAEWOULDBLOCK) {
263 if (err != WSAECONNRESET || prev == WSAECONNRESET) return err;
264 prev = err;
265 }
266 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
267 }
268}
269
270/*-------------------------------------------------------------------------*\
271* Recvfrom with timeout
272\*-------------------------------------------------------------------------*/
273int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
274 SA *addr, socklen_t *len, p_timeout tm)
275{
276 int err, prev = IO_DONE;
277 *got = 0;
278 if (*ps == SOCKET_INVALID) return IO_CLOSED;
279 for ( ;; ) {
280 int taken = recvfrom(*ps, data, (int) count, 0, addr, len);
281 if (taken > 0) {
282 *got = taken;
283 return IO_DONE;
284 }
285 if (taken == 0) return IO_CLOSED;
286 err = WSAGetLastError();
287 /* On UDP, a connreset simply means the previous send failed.
288 * So we try again.
289 * On TCP, it means our socket is now useless, so the error passes.
290 * (We will loop again, exiting because the same error will happen) */
291 if (err != WSAEWOULDBLOCK) {
292 if (err != WSAECONNRESET || prev == WSAECONNRESET) return err;
293 prev = err;
294 }
295 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
296 }
297}
298
299/*-------------------------------------------------------------------------*\
300* Put socket into blocking mode
301\*-------------------------------------------------------------------------*/
302void socket_setblocking(p_socket ps) {
303 u_long argp = 0;
304 ioctlsocket(*ps, FIONBIO, &argp);
305}
306
307/*-------------------------------------------------------------------------*\
308* Put socket into non-blocking mode
309\*-------------------------------------------------------------------------*/
310void socket_setnonblocking(p_socket ps) {
311 u_long argp = 1;
312 ioctlsocket(*ps, FIONBIO, &argp);
313}
314
315/*-------------------------------------------------------------------------*\
316* DNS helpers
317\*-------------------------------------------------------------------------*/
318int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
319 *hp = gethostbyaddr(addr, len, AF_INET);
320 if (*hp) return IO_DONE;
321 else return WSAGetLastError();
322}
323
324int socket_gethostbyname(const char *addr, struct hostent **hp) {
325 *hp = gethostbyname(addr);
326 if (*hp) return IO_DONE;
327 else return WSAGetLastError();
328}
329
330/*-------------------------------------------------------------------------*\
331* Error translation functions
332\*-------------------------------------------------------------------------*/
333const char *socket_hoststrerror(int err) {
334 if (err <= 0) return io_strerror(err);
335 switch (err) {
336 case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND;
337 default: return wstrerror(err);
338 }
339}
340
341const char *socket_strerror(int err) {
342 if (err <= 0) return io_strerror(err);
343 switch (err) {
344 case WSAEADDRINUSE: return PIE_ADDRINUSE;
345 case WSAECONNREFUSED : return PIE_CONNREFUSED;
346 case WSAEISCONN: return PIE_ISCONN;
347 case WSAEACCES: return PIE_ACCESS;
348 case WSAECONNABORTED: return PIE_CONNABORTED;
349 case WSAECONNRESET: return PIE_CONNRESET;
350 case WSAETIMEDOUT: return PIE_TIMEDOUT;
351 default: return wstrerror(err);
352 }
353}
354
355const char *socket_ioerror(p_socket ps, int err) {
356 (void) ps;
357 return socket_strerror(err);
358}
359
360static const char *wstrerror(int err) {
361 switch (err) {
362 case WSAEINTR: return "Interrupted function call";
363 case WSAEACCES: return PIE_ACCESS; /* "Permission denied"; */
364 case WSAEFAULT: return "Bad address";
365 case WSAEINVAL: return "Invalid argument";
366 case WSAEMFILE: return "Too many open files";
367 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
368 case WSAEINPROGRESS: return "Operation now in progress";
369 case WSAEALREADY: return "Operation already in progress";
370 case WSAENOTSOCK: return "Socket operation on nonsocket";
371 case WSAEDESTADDRREQ: return "Destination address required";
372 case WSAEMSGSIZE: return "Message too long";
373 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
374 case WSAENOPROTOOPT: return "Bad protocol option";
375 case WSAEPROTONOSUPPORT: return "Protocol not supported";
376 case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; /* "Socket type not supported"; */
377 case WSAEOPNOTSUPP: return "Operation not supported";
378 case WSAEPFNOSUPPORT: return "Protocol family not supported";
379 case WSAEAFNOSUPPORT: return PIE_FAMILY; /* "Address family not supported by protocol family"; */
380 case WSAEADDRINUSE: return PIE_ADDRINUSE; /* "Address already in use"; */
381 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
382 case WSAENETDOWN: return "Network is down";
383 case WSAENETUNREACH: return "Network is unreachable";
384 case WSAENETRESET: return "Network dropped connection on reset";
385 case WSAECONNABORTED: return "Software caused connection abort";
386 case WSAECONNRESET: return PIE_CONNRESET; /* "Connection reset by peer"; */
387 case WSAENOBUFS: return "No buffer space available";
388 case WSAEISCONN: return PIE_ISCONN; /* "Socket is already connected"; */
389 case WSAENOTCONN: return "Socket is not connected";
390 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
391 case WSAETIMEDOUT: return PIE_TIMEDOUT; /* "Connection timed out"; */
392 case WSAECONNREFUSED: return PIE_CONNREFUSED; /* "Connection refused"; */
393 case WSAEHOSTDOWN: return "Host is down";
394 case WSAEHOSTUNREACH: return "No route to host";
395 case WSAEPROCLIM: return "Too many processes";
396 case WSASYSNOTREADY: return "Network subsystem is unavailable";
397 case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range";
398 case WSANOTINITIALISED:
399 return "Successful WSAStartup not yet performed";
400 case WSAEDISCON: return "Graceful shutdown in progress";
401 case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; /* "Host not found"; */
402 case WSATRY_AGAIN: return "Nonauthoritative host not found";
403 case WSANO_RECOVERY: return PIE_FAIL; /* "Nonrecoverable name lookup error"; */
404 case WSANO_DATA: return "Valid name, no data record of requested type";
405 default: return "Unknown error";
406 }
407}
408
409const char *socket_gaistrerror(int err) {
410 if (err == 0) return NULL;
411 switch (err) {
412 case EAI_AGAIN: return PIE_AGAIN;
413 case EAI_BADFLAGS: return PIE_BADFLAGS;
414#ifdef EAI_BADHINTS
415 case EAI_BADHINTS: return PIE_BADHINTS;
416#endif
417 case EAI_FAIL: return PIE_FAIL;
418 case EAI_FAMILY: return PIE_FAMILY;
419 case EAI_MEMORY: return PIE_MEMORY;
420 case EAI_NONAME: return PIE_NONAME;
421#ifdef EAI_OVERFLOW
422 case EAI_OVERFLOW: return PIE_OVERFLOW;
423#endif
424#ifdef EAI_PROTOCOL
425 case EAI_PROTOCOL: return PIE_PROTOCOL;
426#endif
427 case EAI_SERVICE: return PIE_SERVICE;
428 case EAI_SOCKTYPE: return PIE_SOCKTYPE;
429#ifdef EAI_SYSTEM
430 case EAI_SYSTEM: return strerror(errno);
431#endif
432 default: return LUA_GAI_STRERROR(err);
433 }
434}
diff --git a/vendor/luasocket/src/wsocket.h b/vendor/luasocket/src/wsocket.h
new file mode 100644
index 00000000..39866402
--- /dev/null
+++ b/vendor/luasocket/src/wsocket.h
@@ -0,0 +1,33 @@
1#ifndef WSOCKET_H
2#define WSOCKET_H
3/*=========================================================================*\
4* Socket compatibilization module for Win32
5* LuaSocket toolkit
6\*=========================================================================*/
7
8/*=========================================================================*\
9* WinSock include files
10\*=========================================================================*/
11#include <winsock2.h>
12#include <ws2tcpip.h>
13
14typedef int socklen_t;
15typedef SOCKADDR_STORAGE t_sockaddr_storage;
16typedef SOCKET t_socket;
17typedef t_socket *p_socket;
18
19#ifndef IPV6_V6ONLY
20#define IPV6_V6ONLY 27
21#endif
22
23#define SOCKET_INVALID (INVALID_SOCKET)
24
25#ifndef SO_REUSEPORT
26#define SO_REUSEPORT SO_REUSEADDR
27#endif
28
29#ifndef AI_NUMERICSERV
30#define AI_NUMERICSERV (0)
31#endif
32
33#endif /* WSOCKET_H */
diff --git a/vendor/md5/.gitignore b/vendor/md5/.gitignore
new file mode 100644
index 00000000..9776091d
--- /dev/null
+++ b/vendor/md5/.gitignore
@@ -0,0 +1,4 @@
1*.o
2*.obj
3*.so
4*.dll
diff --git a/vendor/md5/README.md b/vendor/md5/README.md
new file mode 100644
index 00000000..d51492e0
--- /dev/null
+++ b/vendor/md5/README.md
@@ -0,0 +1,47 @@
1# MD5 - Cryptographic Library for Lua
2
3http://keplerproject.github.io/md5/
4
5MD5 offers basic cryptographic facilities for Lua 5.1: a hash (digest)
6function, a pair crypt/decrypt based on MD5 and CFB, and a pair crypt/decrypt based
7on DES with 56-bit keys.
8
9MD5 current version is 1.2.
10
11Please check the documentation at /doc/us/ for more information.
12
13## Installation
14
15To install using [LuaRocks](https://github.com/keplerproject/luarocks) run:
16
17```
18luarocks install md5
19```
20
21To install on Linux/OSX/BSD, please edit the config file and then call
22
23```
24make
25make install
26```
27
28The last step may require root privileges.
29
30## History
31
32Version 1.2 [06/Sep/2013]
33
34* Code adapted to compile for Lua 5.0, 5.1 and 5.2
35
36Version 1.1.2 [12/May/2008]
37
38* Fixed bug in 64-bit systems
39* Fixed the Windows makefile to accept longer directory names
40 (patch by Alessandro Hecht and Ignacio Burgueño).
41
42
43## License
44
45MD5 is free software and uses the same license as Lua (MIT).
46
47The DES 56 C library was implemented by Stuart Levy and uses a MIT license too (check the source).
diff --git a/vendor/md5/rockspec/md5-1.2-1.rockspec b/vendor/md5/rockspec/md5-1.2-1.rockspec
new file mode 100644
index 00000000..04f61ce4
--- /dev/null
+++ b/vendor/md5/rockspec/md5-1.2-1.rockspec
@@ -0,0 +1,35 @@
1package = "MD5"
2version = "1.2-1"
3source = {
4 url = "https://github.com/keplerproject/md5/archive/v1.2.tar.gz",
5 md5 = "c166f8a983401802a86655a8c733441e",
6 dir = "md5-1.2",
7}
8description = {
9 summary = "Basic cryptographic library",
10 detailed = [[
11 MD5 offers basic cryptographic facilities for Lua 5.X:
12 a hash (digest) function, a pair crypt/decrypt based on MD5 and CFB,
13 and a pair crypt/decrypt based on DES with 56-bit keys.
14 ]],
15 license = "MIT/X11",
16 homepage = "http://www.keplerproject.org/md5/",
17}
18dependencies = {
19 "lua >= 5.0"
20}
21build = {
22 type = "builtin",
23 modules = {
24 md5 = "src/md5.lua",
25 ["md5.core"] = {
26 sources = { "src/compat-5.2.c", "src/md5.c", "src/md5lib.c", },
27 incdirs = { "src/", },
28 },
29 des56 = {
30 sources = { "src/compat-5.2.c", "src/des56.c", "src/ldes56.c", },
31 incdirs = { "src/", },
32 },
33 },
34 copy_directories = { "doc", "tests", },
35}
diff --git a/vendor/md5/src/compat-5.2.c b/vendor/md5/src/compat-5.2.c
new file mode 100644
index 00000000..ce57660b
--- /dev/null
+++ b/vendor/md5/src/compat-5.2.c
@@ -0,0 +1,21 @@
1#include "lua.h"
2#include "lauxlib.h"
3#include "compat-5.2.h"
4
5#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501
6/*
7** Adapted from Lua 5.2.0
8*/
9void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
10 luaL_checkstack(L, nup+1, "too many upvalues");
11 for (; l->name != NULL; l++) { /* fill the table with given functions */
12 int i;
13 lua_pushstring(L, l->name);
14 for (i = 0; i < nup; i++) /* copy upvalues to the top */
15 lua_pushvalue(L, -(nup + 1));
16 lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
17 lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */
18 }
19 lua_pop(L, nup); /* remove upvalues */
20}
21#endif
diff --git a/vendor/md5/src/compat-5.2.h b/vendor/md5/src/compat-5.2.h
new file mode 100644
index 00000000..c80fd616
--- /dev/null
+++ b/vendor/md5/src/compat-5.2.h
@@ -0,0 +1,15 @@
1#if !defined LUA_VERSION_NUM
2/* Lua 5.0 */
3#define luaL_Reg luaL_reg
4
5#define luaL_addchar(B,c) \
6 ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
7 (*(B)->p++ = (char)(c)))
8#endif
9
10#if LUA_VERSION_NUM==501
11/* Lua 5.1 */
12#define lua_rawlen lua_objlen
13#endif
14
15void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
diff --git a/vendor/md5/src/des56.c b/vendor/md5/src/des56.c
new file mode 100755
index 00000000..1fb377b9
--- /dev/null
+++ b/vendor/md5/src/des56.c
@@ -0,0 +1,548 @@
1
2/*
3 * Fast implementation of the DES, as described in the Federal Register,
4 * Vol. 40, No. 52, p. 12134, March 17, 1975.
5 *
6 * Stuart Levy, Minnesota Supercomputer Center, April 1988.
7 * Currently (2007) slevy@ncsa.uiuc.edu
8 * NCSA, University of Illinois Urbana-Champaign
9 *
10 * Calling sequence:
11 *
12 * typedef unsigned long keysched[32];
13 *
14 * fsetkey(key, keysched) / * Converts a DES key to a "key schedule" * /
15 * unsigned char key[8];
16 * keysched *ks;
17 *
18 * fencrypt(block, decrypt, keysched) / * En/decrypts one 64-bit block * /
19 * unsigned char block[8]; / * data, en/decrypted in place * /
20 * int decrypt; / * 0=>encrypt, 1=>decrypt * /
21 * keysched *ks; / * key schedule, as set by fsetkey * /
22 *
23 * Key and data block representation:
24 * The 56-bit key (bits 1..64 including "parity" bits 8, 16, 24, ..., 64)
25 * and the 64-bit data block (bits 1..64)
26 * are each stored in arrays of 8 bytes.
27 * Following the NBS numbering, the MSB has the bit number 1, so
28 * key[0] = 128*bit1 + 64*bit2 + ... + 1*bit8, ... through
29 * key[7] = 128*bit57 + 64*bit58 + ... + 1*bit64.
30 * In the key, "parity" bits are not checked; their values are ignored.
31 *
32*/
33
34/*
35===============================================================================
36License
37
38des56.c is licensed under the terms of the MIT license reproduced below.
39This means that des56.c is free software and can be used for both academic
40and commercial purposes at absolutely no cost.
41===============================================================================
42Copyright (C) 1988 Stuart Levy
43
44Permission is hereby granted, free of charge, to any person obtaining a copy
45of this software and associated documentation files (the "Software"), to deal
46in the Software without restriction, including without limitation the rights
47to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
48copies of the Software, and to permit persons to whom the Software is
49furnished to do so, subject to the following conditions:
50
51The above copyright notice and this permission notice shall be included in
52all copies or substantial portions of the Software.
53
54THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
55IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
56FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
58LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
59OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
60THE SOFTWARE.
61 */
62
63
64#include "des56.h"
65
66
67/*
68 * Key schedule generation.
69 * We begin by pointlessly permuting the 56 useful key bits into
70 * two groups of 28 bits called C and D.
71 * bK_C and bK_D are indexed by C and D bit numbers, respectively,
72 * and give the key bit number (1..64) which should initialize that C/D bit.
73 * This is the "permuted choice 1" table.
74 */
75
76static tiny bK_C[28] = {
77 57, 49, 41, 33, 25, 17, 9,
78 1, 58, 50, 42, 34, 26, 18,
79 10, 2, 59, 51, 43, 35, 27,
80 19, 11, 3, 60, 52, 44, 36,
81};
82static tiny bK_D[28] = {
83 63, 55, 47, 39, 31, 23, 15,
84 7, 62, 54, 46, 38, 30, 22,
85 14, 6, 61, 53, 45, 37, 29,
86 21, 13, 5, 28, 20, 12, 4,
87};
88
89/*
90 * For speed, we invert these, building tables to map groups of
91 * key bits into the corresponding C and D bits.
92 * We represent C and D each as 28 contiguous bits right-justified in a
93 * word, padded on the left with zeros.
94 * If key byte `i' is said to contain bits Ki,0 (MSB) Ki,1 ... Ki,7 (LSB)
95 * then
96 * wC_K4[i][Ki,0 Ki,1 Ki,2 Ki,3] gives the C bits for Ki,0..3,
97 * wD_K4[i][Ki,0 Ki,1 Ki,2 Ki,3] the corresponding D bits,
98 * wC_K3[i][Ki,4 Ki,5 Ki,6] the C bits for Ki,4..6,
99 * and wD_K3[i][Ki,4 Ki,5 Ki,6] the D bits for Ki,4..6.
100 * Ki,7 is ignored since it is the nominal parity bit.
101 * We could just use a single table for [i][Ki,0 .. Ki,6] but that
102 * would take a lot of storage for such a rarely-used function.
103 */
104
105static word32 wC_K4[8][16], wC_K3[8][8];
106static word32 wD_K4[8][16], wD_K3[8][8];
107
108/*
109 * Successive Ci and Di for the sixteen steps in the key schedule are
110 * created by independent 28-bit left circular shifts on C and D.
111 * The shift count varies with the step number.
112 */
113static tiny preshift[16] = {
114 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
115};
116
117/*
118 * Each step in the key schedule is generated by selecting 48 bits
119 * (8 groups of 6 bits) from the appropriately shifted Ci and Di.
120 * bCD_KS, indexed by the key schedule bit number, gives the bit number
121 * in CD (CD1 = MSB of C, CD28 = LSB of C, CD29 = MSB of D, CD56 = LSB of D)
122 * which determines that bit of the key schedule.
123 * Note that only C bits (1..28) appear in the first (upper) 24 bits of
124 * the key schedule, and D bits (29..56) in the second (lower) 24 bits.
125 * This is the "permuted-choice-2" table.
126 */
127
128static tiny bCD_KS[48] = {
129 14, 17, 11, 24, 1, 5,
130 3, 28, 15, 6, 21, 10,
131 23, 19, 12, 4, 26, 8,
132 16, 7, 27, 20, 13, 2,
133 41, 52, 31, 37, 47, 55,
134 30, 40, 51, 45, 33, 48,
135 44, 49, 39, 56, 34, 53,
136 46, 42, 50, 36, 29, 32,
137};
138
139/*
140 * We invert bCD_KS into a pair of tables which map groups of 4
141 * C or D bits into corresponding key schedule bits.
142 * We represent each step of the key schedule as 8 groups of 8 bits,
143 * with the 6 real bits right-justified in each 8-bit group.
144 * hKS_C4[i][C4i+1 .. C4i+4] gives the bits in the high order (first four)
145 * key schedule "bytes" which correspond to C bits 4i+1 .. 4i+4.
146 * lKS_D4[i][D4i+1 .. D4i+4] gives the appropriate bits in the latter (last 4)
147 * key schedule bytes, from the corresponding D bits.
148 */
149
150static word32 hKS_C4[7][16];
151static word32 lKS_D4[7][16];
152
153/*
154 * Encryption/decryption.
155 * Before beginning, and after ending, we perform another useless permutation
156 * on the bits in the data block.
157 *
158 * The initial permutation and its inverse, final permutation
159 * are too simple to need a table for. If we break the input I1 .. I64 into
160 * 8-bit chunks I0,0 I0,1 ... I0,7 I1,0 I1,1 ... I7,7
161 * then the initial permutation sets LR as follows:
162 * L = I7,1 I6,1 I5,1 ... I0,1 I7,3 I6,3 ... I0,3 I7,5 ... I0,5 I7,7 ... I0,7
163 * and
164 * R = I7,0 I6,0 I5,0 ... I0,0 I7,2 I6,2 ... I0,2 I7,4 ... I0,4 I7,6 ... I0,6
165 *
166 * If we number the bits in the final LR similarly,
167 * L = L0,0 L0,1 ... L3,7 R = R0,0 R0,1 ... R3,7
168 * then the output is
169 * O = R0,7 L0,7 R1,7 L1,7 ... R3,7 L3,7 R0,6 L0,6 ... L3,6 R0,5 ... R3,0 L3,0
170 *
171 * To speed I => LR shuffling we use an array of 32-bit values indexed by
172 * 8-bit input bytes.
173 * wL_I8[ 0 I0,1 0 I0,3 0 I0,5 0 I0,7 ] = the corresponding L bits.
174 * Other R and L bits are derived from wL_I8 by shifting.
175 *
176 * To speed LR => O shuffling, an array of 32-bit values indexed by 4-bit lumps:
177 * wO_L4[ L0,4 L0,5 L0,6 L0,7 ] = the corresponding high-order 32 O bits.
178 */
179
180static word32 wL_I8[0x55 + 1];
181static word32 wO_L4[16];
182
183/*
184 * Core of encryption/decryption.
185 * In each key schedule stage, we:
186 * take 8 overlapping groups of 6 bits each from R
187 * (the NBS tabulates the bit selections in the E table,
188 * but it's so simple we just use shifting to get the right bits)
189 * XOR each group with the corresponding bits from the key schedule
190 * Use the resulting 6 bits as an index into the appropriate S table
191 * (there are 8 such tables, one per group of 6 bits)
192 * Each S entry yields 4 bits.
193 * The 8 groups of 4 bits are catenated into a 32-bit value.
194 * Those 32 bits are permuted according to the P table.
195 * Finally the permuted 32-bit value is XORed with L and becomes
196 * the R value for the next stage, while the previous R becomes the new L.
197 *
198 * Here, we merge the P permutation with the S tables by making the
199 * S entries be 32-bit masks, already suitably permuted.
200 * Also, the bits in each six-bit group must be permuted before use as
201 * an index into the NBS-tabulated S tables.
202 * We rearrange entries in wPS so that natural bit order can be used.
203 */
204
205static word32 wPS[8][64];
206
207static tiny P[32] = {
208 16, 7, 20, 21,
209 29, 12, 28, 17,
210 1, 15, 23, 26,
211 5, 18, 31, 10,
212 2, 8, 24, 14,
213 32, 27, 3, 9,
214 19, 13, 30, 6,
215 22, 11, 4, 25,
216};
217
218static tiny S[8][64] = {
219 {
220 14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
221 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
222 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
223 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
224 },
225
226 {
227 15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
228 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
229 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
230 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
231 },
232
233 {
234 10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
235 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
236 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
237 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
238 },
239
240 {
241 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
242 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
243 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
244 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
245 },
246
247 {
248 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
249 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
250 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
251 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
252 },
253
254 {
255 12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
256 10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
257 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
258 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
259 },
260
261 {
262 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
263 13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
264 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
265 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
266 },
267
268 {
269 13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
270 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
271 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
272 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
273 },
274};
275
276static void buildtables( void )
277{
278 register int i, j;
279 register word32 v;
280 word32 wC_K[64], wD_K[64];
281 word32 hKS_C[28], lKS_D[28];
282 int Smap[64];
283 word32 wP[32];
284
285#if USG
286# define ZERO(array) memset((char *)(array), '\0', sizeof(array))
287#else
288# if BSD
289# define ZERO(array) bzero((char *)(array), sizeof(array))
290# else
291# define ZERO(array) { register word32 *p = (word32 *)(array); \
292 i = sizeof(array) / sizeof(*p); \
293 do { *p++ = 0; } while(--i > 0); \
294 }
295# endif
296#endif
297
298
299 /* Invert permuted-choice-1 (key => C,D) */
300
301 ZERO(wC_K);
302 ZERO(wD_K);
303 v = 1;
304 for(j = 28; --j >= 0; ) {
305 wC_K[ bK_C[j] - 1 ] = wD_K[ bK_D[j] - 1 ] = v;
306 v += v; /* (i.e. v <<= 1) */
307 }
308
309 for(i = 0; i < 64; i++) {
310 int t = 8 >> (i & 3);
311 for(j = 0; j < 16; j++) {
312 if(j & t) {
313 wC_K4[i >> 3][j] |= wC_K[i];
314 wD_K4[i >> 3][j] |= wD_K[i];
315 if(j < 8) {
316 wC_K3[i >> 3][j] |= wC_K[i + 3];
317 wD_K3[i >> 3][j] |= wD_K[i + 3];
318 }
319 }
320 }
321 /* Generate the sequence 0,1,2,3, 8,9,10,11, ..., 56,57,58,59. */
322 if(t == 1) i += 4;
323 }
324
325 /* Invert permuted-choice-2 */
326
327 ZERO(hKS_C);
328 ZERO(lKS_D);
329 v = 1;
330 for(i = 24; (i -= 6) >= 0; ) {
331 j = i+5;
332 do {
333 hKS_C[ bCD_KS[j] - 1 ] = lKS_D[ bCD_KS[j+24] - 28 - 1 ] = v;
334 v += v; /* Like v <<= 1 but may be faster */
335 } while(--j >= i);
336 v <<= 2; /* Keep byte aligned */
337 }
338
339 for(i = 0; i < 28; i++) {
340 v = 8 >> (i & 3);
341 for(j = 0; j < 16; j++) {
342 if(j & v) {
343 hKS_C4[i >> 2][j] |= hKS_C[i];
344 lKS_D4[i >> 2][j] |= lKS_D[i];
345 }
346 }
347 }
348
349 /* Initial permutation */
350
351 for(i = 0; i <= 0x55; i++) {
352 v = 0;
353 if(i & 64) v = (word32) 1 << 24;
354 if(i & 16) v |= (word32) 1 << 16;
355 if(i & 4) v |= (word32) 1 << 8;
356 if(i & 1) v |= 1;
357 wL_I8[i] = v;
358 }
359
360 /* Final permutation */
361
362 for(i = 0; i < 16; i++) {
363 v = 0;
364 if(i & 1) v = (word32) 1 << 24;
365 if(i & 2) v |= (word32) 1 << 16;
366 if(i & 4) v |= (word32) 1 << 8;
367 if(i & 8) v |= (word32) 1;
368 wO_L4[i] = v;
369 }
370
371 /* Funny bit rearrangement on second index into S tables */
372
373 for(i = 0; i < 64; i++) {
374 Smap[i] = (i & 0x20) | (i & 1) << 4 | (i & 0x1e) >> 1;
375 }
376
377 /* Invert permutation P into mask indexed by R bit number */
378
379 v = 1;
380 for(i = 32; --i >= 0; ) {
381 wP[ P[i] - 1 ] = v;
382 v += v;
383 }
384
385 /* Build bit-mask versions of S tables, indexed in natural bit order */
386
387 for(i = 0; i < 8; i++) {
388 for(j = 0; j < 64; j++) {
389 int k, t;
390
391 t = S[i][ Smap[j] ];
392 for(k = 0; k < 4; k++) {
393 if(t & 8)
394 wPS[i][j] |= wP[4*i + k];
395 t += t;
396 }
397 }
398 }
399}
400
401
402void fsetkey(char key[8], keysched *ks)
403{
404 register int i;
405 register word32 C, D;
406 static int built = 0;
407
408 if(!built) {
409 buildtables();
410 built = 1;
411 }
412
413 C = D = 0;
414 for(i = 0; i < 8; i++) {
415 register int v;
416
417 v = key[i] >> 1; /* Discard "parity" bit */
418 C |= wC_K4[i][(v>>3) & 15] | wC_K3[i][v & 7];
419 D |= wD_K4[i][(v>>3) & 15] | wD_K3[i][v & 7];
420 }
421
422 /*
423 * C and D now hold the suitably right-justified
424 * 28 permuted key bits each.
425 */
426 for(i = 0; i < 16; i++) {
427#ifdef CRAY
428#define choice2(x, v) x[6][v&15] | x[5][(v>>4)&15] | x[4][(v>>8)&15] | \
429 x[3][(v>>12)&15] | x[2][(v>>16)&15] | x[1][(v>>20)&15] | \
430 x[0][(v>>24)&15]
431#else
432 register word32 *ap;
433
434# define choice2(x, v) ( \
435 ap = &(x)[0][0], \
436 ap[16*6 + (v&15)] | \
437 ap[16*5 + ((v>>4)&15)] | ap[16*4 + ((v>>8)&15)] | \
438 ap[16*3 + ((v>>12)&15)] | ap[16*2 + ((v>>16)&15)] | \
439 ap[16*1 + ((v>>20)&15)] | ap[16*0 + ((v>>24)&15)] )
440#endif
441
442
443 /* 28-bit left circular shift */
444 C <<= preshift[i];
445 C = ((C >> 28) & 3) | (C & (((word32)1<<28) - 1));
446 ks->KS[i].h = choice2(hKS_C4, C);
447
448 D <<= preshift[i];
449 D = ((D >> 28) & 3) | (D & (((word32)1<<28) - 1));
450 ks->KS[i].l = choice2(lKS_D4, D);
451 }
452}
453
454void
455fencrypt(char block[8], int decrypt, keysched *ks)
456{
457 int i;
458 register word32 L, R;
459 register struct keystage *ksp;
460 register word32 *ap;
461
462 /* Initial permutation */
463
464 L = R = 0;
465 i = 7;
466 ap = wL_I8;
467 do {
468 register int v;
469
470 v = block[i]; /* Could optimize according to ENDIAN */
471 L = ap[v & 0x55] | (L << 1);
472 R = ap[(v >> 1) & 0x55] | (R << 1);
473 } while(--i >= 0);
474
475 if(decrypt) {
476 ksp = &ks->KS[15];
477 } else {
478 ksp = &ks->KS[0];
479 }
480
481#ifdef CRAY
482# define PS(i,j) wPS[i][j]
483#else
484# define PS(i,j) ap[64*(i) + (j)]
485 ap = &wPS[0][0];
486#endif
487
488 i = 16;
489 do {
490 register word32 k, tR;
491
492 tR = (R >> 15) | (R << 17);
493
494 k = ksp->h;
495 L ^= PS(0, ((tR >> 12) ^ (k >> 24)) & 63)
496 | PS(1, ((tR >> 8) ^ (k >> 16)) & 63)
497 | PS(2, ((tR >> 4) ^ (k >> 8)) & 63)
498 | PS(3, (tR ^ k) & 63);
499
500 k = ksp->l;
501 L ^= PS(4, ((R >> 11) ^ (k >> 24)) & 63)
502 | PS(5, ((R >> 7) ^ (k >> 16)) & 63)
503 | PS(6, ((R >> 3) ^ (k >> 8)) & 63)
504 | PS(7, ((tR >> 16) ^ k) & 63);
505
506 tR = L;
507 L = R;
508 R = tR;
509
510
511 if(decrypt)
512 ksp--;
513 else
514 ksp++;
515 } while(--i > 0);
516 {
517 register word32 t;
518
519#ifdef CRAY
520# define FP(k) (wO_L4[ (L >> (k)) & 15 ] << 1 | wO_L4[ (R >> (k)) & 15 ])
521#else
522# define FP(k) (ap[ (L >> (k)) & 15 ] << 1 | ap[ (R >> (k)) & 15 ])
523
524 ap = wO_L4;
525#endif
526
527 t = FP(0) | (FP(8) | (FP(16) | (FP(24) << 2)) << 2) << 2;
528 R = FP(4) | (FP(12) | (FP(20) | (FP(28) << 2)) << 2) << 2;
529 L = t;
530 }
531 {
532 register word32 t;
533 register char *bp;
534
535 bp = &block[7];
536 t = R;
537 *bp = t & 255;
538 *--bp = (t >>= 8) & 255;
539 *--bp = (t >>= 8) & 255;
540 *--bp = (t >> 8) & 255;
541 t = L;
542 *--bp = t & 255;
543 *--bp = (t >>= 8) & 255;
544 *--bp = (t >>= 8) & 255;
545 *--bp = (t >> 8) & 255;
546 }
547}
548
diff --git a/vendor/md5/src/des56.def b/vendor/md5/src/des56.def
new file mode 100644
index 00000000..c0493a73
--- /dev/null
+++ b/vendor/md5/src/des56.def
@@ -0,0 +1,5 @@
1LIBRARY des56.dll
2DESCRIPTION "DES56"
3VERSION 1.3
4EXPORTS
5luaopen_des56
diff --git a/vendor/md5/src/des56.h b/vendor/md5/src/des56.h
new file mode 100755
index 00000000..88e5f137
--- /dev/null
+++ b/vendor/md5/src/des56.h
@@ -0,0 +1,77 @@
1#ifndef DES56_H
2#define DES56_H 1
3/*
4 * Fast implementation of the DES, as described in the Federal Register,
5 * Vol. 40, No. 52, p. 12134, March 17, 1975.
6 *
7 * Stuart Levy, Minnesota Supercomputer Center, April 1988.
8 * Currently (2007) slevy@ncsa.uiuc.edu
9 * NCSA, University of Illinois Urbana-Champaign
10 *
11 * Calling sequence:
12 *
13 * typedef unsigned long keysched[32];
14 *
15 * fsetkey(key, keysched) / * Converts a DES key to a "key schedule" * /
16 * unsigned char key[8];
17 * keysched *ks;
18 *
19 * fencrypt(block, decrypt, keysched) / * En/decrypts one 64-bit block * /
20 * unsigned char block[8]; / * data, en/decrypted in place * /
21 * int decrypt; / * 0=>encrypt, 1=>decrypt * /
22 * keysched *ks; / * key schedule, as set by fsetkey * /
23 *
24 * Key and data block representation:
25 * The 56-bit key (bits 1..64 including "parity" bits 8, 16, 24, ..., 64)
26 * and the 64-bit data block (bits 1..64)
27 * are each stored in arrays of 8 bytes.
28 * Following the NBS numbering, the MSB has the bit number 1, so
29 * key[0] = 128*bit1 + 64*bit2 + ... + 1*bit8, ... through
30 * key[7] = 128*bit57 + 64*bit58 + ... + 1*bit64.
31 * In the key, "parity" bits are not checked; their values are ignored.
32 *
33*/
34
35/*
36===============================================================================
37License
38
39des56.c is licensed under the terms of the MIT license reproduced below.
40This means that des56.c is free software and can be used for both academic
41and commercial purposes at absolutely no cost.
42===============================================================================
43Copyright (C) 1988 Stuart Levy
44
45Permission is hereby granted, free of charge, to any person obtaining a copy
46of this software and associated documentation files (the "Software"), to deal
47in the Software without restriction, including without limitation the rights
48to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
49copies of the Software, and to permit persons to whom the Software is
50furnished to do so, subject to the following conditions:
51
52The above copyright notice and this permission notice shall be included in
53all copies or substantial portions of the Software.
54
55THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
56IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
58AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
59LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
60OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
61THE SOFTWARE.
62 */
63
64typedef unsigned long word32;
65typedef unsigned char tiny;
66
67typedef struct keysched {
68 struct keystage {
69 word32 h, l;
70 } KS[16];
71} keysched;
72
73extern void fsetkey(char key[8], keysched *ks);
74
75extern void fencrypt(char block[8], int decrypt, keysched *ks);
76
77#endif /*DES56_H*/
diff --git a/vendor/md5/src/ldes56.c b/vendor/md5/src/ldes56.c
new file mode 100644
index 00000000..8c29ec1d
--- /dev/null
+++ b/vendor/md5/src/ldes56.c
@@ -0,0 +1,152 @@
1#include <stdlib.h>
2#include <string.h>
3
4#include "des56.h"
5
6#include "lua.h"
7#include "lauxlib.h"
8
9#include "compat-5.2.h"
10#include "ldes56.h"
11
12static int des56_decrypt( lua_State *L )
13{
14 char* decypheredText;
15 keysched KS;
16 int rel_index, abs_index;
17 size_t cypherlen;
18 const char *cypheredText =
19 luaL_checklstring( L, 1, &cypherlen );
20 const char *key = luaL_optstring( L, 2, NULL );
21 int padinfo;
22
23 padinfo = cypheredText[cypherlen-1];
24 cypherlen--;
25
26 /* Aloca array */
27 decypheredText =
28 (char *) malloc( (cypherlen+1) * sizeof(char));
29 if(decypheredText == NULL) {
30 lua_pushstring(L, "Error decrypting file. Not enough memory.");
31 lua_error(L);
32 }
33
34 /* Inicia decifragem */
35 if (key && strlen(key) >= 8)
36 {
37 char k[8];
38 int i;
39
40 for (i=0; i<8; i++)
41 k[i] = (unsigned char)key[i];
42 fsetkey(k, &KS);
43 } else {
44 lua_pushstring(L, "Error decrypting file. Invalid key.");
45 lua_error(L);
46 }
47
48 rel_index = 0;
49 abs_index = 0;
50
51 while (abs_index < (int) cypherlen)
52 {
53 decypheredText[abs_index] = cypheredText[abs_index];
54 abs_index++;
55 rel_index++;
56 if( rel_index == 8 )
57 {
58 rel_index = 0;
59 fencrypt(&(decypheredText[abs_index - 8]), 1, &KS);
60 }
61 }
62 decypheredText[abs_index] = 0;
63
64 lua_pushlstring(L, decypheredText, (abs_index-padinfo));
65 free( decypheredText );
66 return 1;
67}
68
69static int des56_crypt( lua_State *L )
70{
71 char *cypheredText;
72 keysched KS;
73 int rel_index, pad, abs_index;
74 size_t plainlen;
75 const char *plainText = luaL_checklstring( L, 1, &plainlen );
76 const char *key = luaL_optstring( L, 2, NULL );
77
78 cypheredText = (char *) malloc( (plainlen+8) * sizeof(char));
79 if(cypheredText == NULL) {
80 lua_pushstring(L, "Error encrypting file. Not enough memory.");
81 lua_error(L);
82 }
83
84 if (key && strlen(key) >= 8)
85 {
86 char k[8];
87 int i;
88
89 for (i=0; i<8; i++)
90 k[i] = (unsigned char)key[i];
91 fsetkey(k, &KS);
92 } else {
93 lua_pushstring(L, "Error encrypting file. Invalid key.");
94 lua_error(L);
95 }
96
97 rel_index = 0;
98 abs_index = 0;
99 while (abs_index < (int) plainlen) {
100 cypheredText[abs_index] = plainText[abs_index];
101 abs_index++;
102 rel_index++;
103 if( rel_index == 8 ) {
104 rel_index = 0;
105 fencrypt(&(cypheredText[abs_index - 8]), 0, &KS);
106 }
107 }
108
109 pad = 0;
110 if(rel_index != 0) { /* Pads remaining bytes with zeroes */
111 while(rel_index < 8)
112 {
113 pad++;
114 cypheredText[abs_index++] = 0;
115 rel_index++;
116 }
117 fencrypt(&(cypheredText[abs_index - 8]), 0, &KS);
118 }
119 cypheredText[abs_index] = pad;
120
121 lua_pushlstring( L, cypheredText, abs_index+1 );
122 free( cypheredText );
123 return 1;
124}
125
126/*
127** Assumes the table is on top of the stack.
128*/
129static void set_info (lua_State *L) {
130 lua_pushliteral (L, "_COPYRIGHT");
131 lua_pushliteral (L, "Copyright (C) 2007-2019 PUC-Rio");
132 lua_settable (L, -3);
133 lua_pushliteral (L, "_DESCRIPTION");
134 lua_pushliteral (L, "DES 56 cryptographic facilities for Lua");
135 lua_settable (L, -3);
136 lua_pushliteral (L, "_VERSION");
137 lua_pushliteral (L, "DES56 1.3");
138 lua_settable (L, -3);
139}
140
141static const struct luaL_Reg des56lib[] = {
142 {"crypt", des56_crypt},
143 {"decrypt", des56_decrypt},
144 {NULL, NULL},
145};
146
147int luaopen_des56 (lua_State *L) {
148 lua_newtable(L);
149 luaL_setfuncs(L, des56lib, 0);
150 set_info (L);
151 return 1;
152}
diff --git a/vendor/md5/src/ldes56.h b/vendor/md5/src/ldes56.h
new file mode 100755
index 00000000..8c2e86a8
--- /dev/null
+++ b/vendor/md5/src/ldes56.h
@@ -0,0 +1 @@
int luaopen_des56 (lua_State *L);
diff --git a/vendor/md5/src/md5.c b/vendor/md5/src/md5.c
new file mode 100755
index 00000000..f35c8e14
--- /dev/null
+++ b/vendor/md5/src/md5.c
@@ -0,0 +1,262 @@
1/**
2* $Id: md5.c,v 1.2 2008/03/24 20:59:12 mascarenhas Exp $
3* Hash function MD5
4* @author Marcela Ozorio Suarez, Roberto I.
5*/
6
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <time.h>
12
13#include "md5.h"
14
15
16#define WORD 32
17#define MASK 0xFFFFFFFF
18
19
20/**
21* md5 hash function.
22* @param message: aribtary string.
23* @param len: message length.
24* @param output: buffer to receive the hash value. Its size must be
25* (at least) HASHSIZE.
26*/
27void md5 (const char *message, size_t len, char output[HASHSIZE]);
28
29/**
30* init a new md5 calculate context
31* @param m a uninitialized md5_t type context
32*/
33void md5_init (md5_t *m);
34
35/**
36* update message to md5 context
37* @param m a initialized md5_t type context
38* @param message aribtary string
39* @param len message length
40* @return true if update completed, means len is not the multiples of 64.
41* false if you can continue update.
42*/
43int md5_update (md5_t *m, const char *message, size_t len);
44
45/**
46 * finish md5 calculate.
47 * @param m a md5_type context which previous md5_update on it return true.
48 * @param output buffer to receive the hash value. its size must be
49 * (at least) HASHSIZE.
50 */
51void md5_finish (md5_t *m, char output[HASHSIZE]);
52
53/*
54** Realiza a rotacao no sentido horario dos bits da variavel 'D' do tipo WORD32.
55** Os bits sao deslocados de 'num' posicoes
56*/
57#define rotate(D, num) (D<<num) | (D>>(WORD-num))
58
59/*Macros que definem operacoes relizadas pelo algoritmo md5 */
60#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
61#define G(x, y, z) (((x) & (z)) | ((y) & (~(z))))
62#define H(x, y, z) ((x) ^ (y) ^ (z))
63#define I(x, y, z) ((y) ^ ((x) | (~(z))))
64
65
66/*vetor de numeros utilizados pelo algoritmo md5 para embaralhar bits */
67static const WORD32 T[64]={
68 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
69 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
70 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
71 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
72 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
73 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
74 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
75 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
76 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
77 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
78 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
79 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
80 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
81 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
82 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
83 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
84};
85
86
87static void word32tobytes (const WORD32 *input, char *output) {
88 int j = 0;
89 while (j<4*4) {
90 WORD32 v = *input++;
91 output[j++] = (char)(v & 0xff); v >>= 8;
92 output[j++] = (char)(v & 0xff); v >>= 8;
93 output[j++] = (char)(v & 0xff); v >>= 8;
94 output[j++] = (char)(v & 0xff);
95 }
96}
97
98
99static void inic_digest(WORD32 *d) {
100 d[0] = 0x67452301;
101 d[1] = 0xEFCDAB89;
102 d[2] = 0x98BADCFE;
103 d[3] = 0x10325476;
104}
105
106
107/*funcao que implemeta os quatro passos principais do algoritmo MD5 */
108static void digest(const WORD32 *m, WORD32 *d) {
109 int j;
110 /*MD5 PASSO1 */
111 for (j=0; j<4*4; j+=4) {
112 d[0] = d[0]+ F(d[1], d[2], d[3])+ m[j] + T[j]; d[0]=rotate(d[0], 7);
113 d[0]+=d[1];
114 d[3] = d[3]+ F(d[0], d[1], d[2])+ m[(j)+1] + T[j+1]; d[3]=rotate(d[3], 12);
115 d[3]+=d[0];
116 d[2] = d[2]+ F(d[3], d[0], d[1])+ m[(j)+2] + T[j+2]; d[2]=rotate(d[2], 17);
117 d[2]+=d[3];
118 d[1] = d[1]+ F(d[2], d[3], d[0])+ m[(j)+3] + T[j+3]; d[1]=rotate(d[1], 22);
119 d[1]+=d[2];
120 }
121 /*MD5 PASSO2 */
122 for (j=0; j<4*4; j+=4) {
123 d[0] = d[0]+ G(d[1], d[2], d[3])+ m[(5*j+1)&0x0f] + T[(j-1)+17];
124 d[0] = rotate(d[0],5);
125 d[0]+=d[1];
126 d[3] = d[3]+ G(d[0], d[1], d[2])+ m[((5*(j+1)+1)&0x0f)] + T[(j+0)+17];
127 d[3] = rotate(d[3], 9);
128 d[3]+=d[0];
129 d[2] = d[2]+ G(d[3], d[0], d[1])+ m[((5*(j+2)+1)&0x0f)] + T[(j+1)+17];
130 d[2] = rotate(d[2], 14);
131 d[2]+=d[3];
132 d[1] = d[1]+ G(d[2], d[3], d[0])+ m[((5*(j+3)+1)&0x0f)] + T[(j+2)+17];
133 d[1] = rotate(d[1], 20);
134 d[1]+=d[2];
135 }
136 /*MD5 PASSO3 */
137 for (j=0; j<4*4; j+=4) {
138 d[0] = d[0]+ H(d[1], d[2], d[3])+ m[(3*j+5)&0x0f] + T[(j-1)+33];
139 d[0] = rotate(d[0], 4);
140 d[0]+=d[1];
141 d[3] = d[3]+ H(d[0], d[1], d[2])+ m[(3*(j+1)+5)&0x0f] + T[(j+0)+33];
142 d[3] = rotate(d[3], 11);
143 d[3]+=d[0];
144 d[2] = d[2]+ H(d[3], d[0], d[1])+ m[(3*(j+2)+5)&0x0f] + T[(j+1)+33];
145 d[2] = rotate(d[2], 16);
146 d[2]+=d[3];
147 d[1] = d[1]+ H(d[2], d[3], d[0])+ m[(3*(j+3)+5)&0x0f] + T[(j+2)+33];
148 d[1] = rotate(d[1], 23);
149 d[1]+=d[2];
150 }
151 /*MD5 PASSO4 */
152 for (j=0; j<4*4; j+=4) {
153 d[0] = d[0]+ I(d[1], d[2], d[3])+ m[(7*j)&0x0f] + T[(j-1)+49];
154 d[0] = rotate(d[0], 6);
155 d[0]+=d[1];
156 d[3] = d[3]+ I(d[0], d[1], d[2])+ m[(7*(j+1))&0x0f] + T[(j+0)+49];
157 d[3] = rotate(d[3], 10);
158 d[3]+=d[0];
159 d[2] = d[2]+ I(d[3], d[0], d[1])+ m[(7*(j+2))&0x0f] + T[(j+1)+49];
160 d[2] = rotate(d[2], 15);
161 d[2]+=d[3];
162 d[1] = d[1]+ I(d[2], d[3], d[0])+ m[(7*(j+3))&0x0f] + T[(j+2)+49];
163 d[1] = rotate(d[1], 21);
164 d[1]+=d[2];
165 }
166}
167
168
169static void bytestoword32 (WORD32 *x, const char *pt) {
170 int i;
171 for (i=0; i<16; i++) {
172 int j=i*4;
173 x[i] = (((WORD32)(unsigned char)pt[j+3] << 8 |
174 (WORD32)(unsigned char)pt[j+2]) << 8 |
175 (WORD32)(unsigned char)pt[j+1]) << 8 |
176 (WORD32)(unsigned char)pt[j];
177 }
178
179}
180
181
182static void put_length(WORD32 *x, long len) {
183 /* in bits! */
184 x[14] = (WORD32)((len<<3) & MASK);
185 x[15] = (WORD32)(len>>(32-3) & 0x7);
186}
187
188
189/*
190** returned status:
191* 0 - normal message (full 64 bytes)
192* 1 - enough room for 0x80, but not for message length (two 4-byte words)
193* 2 - enough room for 0x80 plus message length (at least 9 bytes free)
194*/
195static int converte (WORD32 *x, const char *pt, int num, int old_status) {
196 int new_status = 0;
197 char buff[64];
198 if (num<64) {
199 memcpy(buff, pt, num); /* to avoid changing original string */
200 memset(buff+num, 0, 64-num);
201 if (old_status == 0)
202 buff[num] = '\200';
203 new_status = 1;
204 pt = buff;
205 }
206 bytestoword32(x, pt);
207 if (num <= (64 - 9))
208 new_status = 2;
209 return new_status;
210}
211
212
213void md5 (const char *message, size_t len, char output[HASHSIZE]) {
214 WORD32 d[4];
215 int status = 0;
216 long i = 0;
217 inic_digest(d);
218 while (status != 2) {
219 WORD32 d_old[4];
220 WORD32 wbuff[16];
221 int numbytes = (len-i >= 64) ? 64 : len-i;
222 /*salva os valores do vetor digest*/
223 d_old[0]=d[0]; d_old[1]=d[1]; d_old[2]=d[2]; d_old[3]=d[3];
224 status = converte(wbuff, message+i, numbytes, status);
225 if (status == 2) put_length(wbuff, len);
226 digest(wbuff, d);
227 d[0]+=d_old[0]; d[1]+=d_old[1]; d[2]+=d_old[2]; d[3]+=d_old[3];
228 i += numbytes;
229 }
230 word32tobytes(d, output);
231}
232
233void md5_init(md5_t *m) {
234 inic_digest(m->d);
235 m->len = 0;
236}
237
238int md5_update(md5_t *m, const char *message, size_t len) {
239 WORD32 *d = m->d;
240 size_t addlen = m->len;
241 int status = 0, i = 0;
242 while (status != 2) {
243 WORD32 d_old[4];
244 WORD32 wbuff[16];
245 int numbytes = (len-i >= 64) ? 64 : len-i;
246 if (status != 1 && numbytes == 0 && len != 0)
247 break;
248 /*salva os valores do vetor digest*/
249 d_old[0]=d[0]; d_old[1]=d[1]; d_old[2]=d[2]; d_old[3]=d[3];
250 status = converte(wbuff, message+i, numbytes, status);
251 if (status == 2) put_length(wbuff, addlen+len);
252 digest(wbuff, d);
253 d[0]+=d_old[0]; d[1]+=d_old[1]; d[2]+=d_old[2]; d[3]+=d_old[3];
254 i += numbytes;
255 }
256 m->len += len;
257 return status == 2;
258}
259
260void md5_finish (md5_t *m, char output[HASHSIZE]) {
261 word32tobytes(m->d, output);
262}
diff --git a/vendor/md5/src/md5.def b/vendor/md5/src/md5.def
new file mode 100644
index 00000000..8ab09e76
--- /dev/null
+++ b/vendor/md5/src/md5.def
@@ -0,0 +1,5 @@
1LIBRARY core.dll
2DESCRIPTION "LuaMD5"
3VERSION 1.3
4EXPORTS
5luaopen_md5_core
diff --git a/vendor/md5/src/md5.h b/vendor/md5/src/md5.h
new file mode 100755
index 00000000..522ede81
--- /dev/null
+++ b/vendor/md5/src/md5.h
@@ -0,0 +1,40 @@
1/**
2* $Id: md5.h,v 1.2 2006/03/03 15:04:49 tomas Exp $
3* Cryptographic module for Lua.
4* @author Roberto Ierusalimschy
5*/
6
7
8#ifndef md5_h
9#define md5_h
10
11#include <lua.h>
12#include <stddef.h>
13
14
15#define HASHSIZE 16
16
17#if __STDC_VERSION__ >= 199901L
18#include <stdint.h>
19typedef uint32_t WORD32;
20#else
21/* static assert that int equal or greater than 32bit. */
22typedef char static_assert_sizeof_int
23 [sizeof(unsigned int) >= 4 ? 1 : -1];
24typedef unsigned int WORD32;
25#endif
26
27typedef struct md5_t {
28 WORD32 d[4];
29 size_t len;
30} md5_t;
31
32void md5_init (md5_t *m);
33int md5_update (md5_t *m, const char *message, size_t len);
34void md5_finish (md5_t *m, char output[HASHSIZE]);
35void md5 (const char *message, size_t len, char output[HASHSIZE]);
36
37LUALIB_API int luaopen_md5_core (lua_State *L);
38
39
40#endif
diff --git a/vendor/md5/src/md5.lua b/vendor/md5/src/md5.lua
new file mode 100644
index 00000000..4eeda2dd
--- /dev/null
+++ b/vendor/md5/src/md5.lua
@@ -0,0 +1,26 @@
1----------------------------------------------------------------------------
2-- $Id: md5.lua,v 1.4 2006/08/21 19:24:21 carregal Exp $
3----------------------------------------------------------------------------
4
5local core
6local string = string or require"string"
7if string.find(_VERSION, "Lua 5.0") then
8 local cpath = os.getenv"LUA_CPATH" or "/usr/local/lib/lua/5.0/"
9 core = loadlib(cpath.."md5/core.so", "luaopen_md5_core")()
10else
11 core = require"md5.core"
12end
13
14
15----------------------------------------------------------------------------
16-- @param k String with original message.
17-- @return String with the md5 hash value converted to hexadecimal digits
18
19function core.sumhexa (k)
20 k = core.sum(k)
21 return (string.gsub(k, ".", function (c)
22 return string.format("%02x", string.byte(c))
23 end))
24end
25
26return core
diff --git a/vendor/md5/src/md5lib.c b/vendor/md5/src/md5lib.c
new file mode 100644
index 00000000..19abc85f
--- /dev/null
+++ b/vendor/md5/src/md5lib.c
@@ -0,0 +1,200 @@
1/**
2* $Id: md5lib.c,v 1.10 2008/05/12 20:51:27 carregal Exp $
3* Cryptographic and Hash functions for Lua
4* @author Roberto Ierusalimschy
5*/
6
7
8#include <stdlib.h>
9#include <string.h>
10#include <time.h>
11
12#include <lua.h>
13#include <lauxlib.h>
14
15#include "md5.h"
16#include "compat-5.2.h"
17
18
19/**
20* Hash function. Returns a hash for a given string.
21* @param message: arbitrary binary string.
22* @return A 128-bit hash string.
23*/
24static int lmd5 (lua_State *L) {
25 char buff[16];
26 size_t l;
27 const char *message = luaL_checklstring(L, 1, &l);
28 md5(message, l, buff);
29 lua_pushlstring(L, buff, 16L);
30 return 1;
31}
32
33
34/**
35* X-Or. Does a bit-a-bit exclusive-or of two strings.
36* @param s1: arbitrary binary string.
37* @param s2: arbitrary binary string with same length as s1.
38* @return a binary string with same length as s1 and s2,
39* where each bit is the exclusive-or of the corresponding bits in s1-s2.
40*/
41static int ex_or (lua_State *L) {
42 size_t l1, l2;
43 const char *s1 = luaL_checklstring(L, 1, &l1);
44 const char *s2 = luaL_checklstring(L, 2, &l2);
45 luaL_Buffer b;
46 luaL_argcheck( L, l1 == l2, 2, "lengths must be equal" );
47 luaL_buffinit(L, &b);
48 while (l1--) luaL_addchar(&b, (*s1++)^(*s2++));
49 luaL_pushresult(&b);
50 return 1;
51}
52
53
54static void checkseed (lua_State *L) {
55 if (lua_isnone(L, 3)) { /* no seed? */
56 time_t tm = time(NULL); /* for `random' seed */
57 lua_pushlstring(L, (char *)&tm, sizeof(tm));
58 }
59}
60
61
62#define MAXKEY 256
63#define BLOCKSIZE 16
64
65
66
67static int initblock (lua_State *L, const char *seed, int lseed, char *block) {
68 size_t lkey;
69 const char *key = luaL_checklstring(L, 2, &lkey);
70 if (lkey > MAXKEY)
71 luaL_error(L, "key too long (> %d)", MAXKEY);
72 memset(block, 0, BLOCKSIZE);
73 memcpy(block, seed, lseed);
74 memcpy(block+BLOCKSIZE, key, lkey);
75 return (int)lkey+BLOCKSIZE;
76}
77
78
79static void codestream (lua_State *L, const char *msg, size_t lmsg,
80 char *block, int lblock) {
81 luaL_Buffer b;
82 luaL_buffinit(L, &b);
83 while (lmsg > 0) {
84 char code[BLOCKSIZE];
85 int i;
86 md5(block, lblock, code);
87 for (i=0; i<BLOCKSIZE && lmsg > 0; i++, lmsg--)
88 code[i] ^= *msg++;
89 luaL_addlstring(&b, code, i);
90 memcpy(block, code, i); /* update seed */
91 }
92 luaL_pushresult(&b);
93}
94
95
96static void decodestream (lua_State *L, const char *cypher, size_t lcypher,
97 char *block, int lblock) {
98 luaL_Buffer b;
99 luaL_buffinit(L, &b);
100 while (lcypher > 0) {
101 char code[BLOCKSIZE];
102 int i;
103 md5(block, lblock, code); /* update seed */
104 for (i=0; i<BLOCKSIZE && lcypher > 0; i++, lcypher--)
105 code[i] ^= *cypher++;
106 luaL_addlstring(&b, code, i);
107 memcpy(block, cypher-i, i);
108 }
109 luaL_pushresult(&b);
110}
111
112
113/**
114* Encrypts a string. Uses the hash function md5 in CFB (Cipher-feedback
115* mode).
116* @param message: arbitrary binary string to be encrypted.
117* @param key: arbitrary binary string to be used as a key.
118* @param [seed]: optional arbitrary binary string to be used as a seed.
119* if no seed is provided, the function uses the result of
120* <code>time()</code> as a seed.
121* @return The cyphertext (as a binary string).
122*/
123static int crypt (lua_State *L) {
124 size_t lmsg;
125 const char *msg = luaL_checklstring(L, 1, &lmsg);
126 size_t lseed;
127 const char *seed;
128 int lblock;
129 char block[BLOCKSIZE+MAXKEY];
130 checkseed(L);
131 seed = luaL_checklstring(L, 3, &lseed);
132 if (lseed > BLOCKSIZE)
133 luaL_error(L, "seed too long (> %d)", BLOCKSIZE);
134 /* put seed and seed length at the beginning of result */
135 block[0] = (char)lseed;
136 memcpy(block+1, seed, lseed);
137 lua_pushlstring(L, block, lseed+1); /* to concat with result */
138 lblock = initblock(L, seed, lseed, block);
139 codestream(L, msg, lmsg, block, lblock);
140 lua_concat(L, 2);
141 return 1;
142}
143
144
145/**
146* Decrypts a string. For any message, key, and seed, we have that
147* <code>decrypt(crypt(msg, key, seed), key) == msg</code>.
148* @param cyphertext: message to be decrypted (this must be the result of
149 a previous call to <code>crypt</code>.
150* @param key: arbitrary binary string to be used as a key.
151* @return The plaintext.
152*/
153static int decrypt (lua_State *L) {
154 size_t lcyphertext;
155 const char *cyphertext = luaL_checklstring(L, 1, &lcyphertext);
156 size_t lseed = cyphertext[0];
157 const char *seed = cyphertext+1;
158 int lblock;
159 char block[BLOCKSIZE+MAXKEY];
160 luaL_argcheck(L, lcyphertext >= lseed+1 && lseed <= BLOCKSIZE, 1,
161 "invalid cyphered string");
162 cyphertext += lseed+1;
163 lcyphertext -= lseed+1;
164 lblock = initblock(L, seed, lseed, block);
165 decodestream(L, cyphertext, lcyphertext, block, lblock);
166 return 1;
167}
168
169
170/*
171** Assumes the table is on top of the stack.
172*/
173static void set_info (lua_State *L) {
174 lua_pushliteral (L, "_COPYRIGHT");
175 lua_pushliteral (L, "Copyright (C) 2003-2019 PUC-Rio");
176 lua_settable (L, -3);
177 lua_pushliteral (L, "_DESCRIPTION");
178 lua_pushliteral (L, "Checksum facilities for Lua");
179 lua_settable (L, -3);
180 lua_pushliteral (L, "_VERSION");
181 lua_pushliteral (L, "MD5 1.3");
182 lua_settable (L, -3);
183}
184
185
186static struct luaL_Reg md5lib[] = {
187 {"sum", lmd5},
188 {"exor", ex_or},
189 {"crypt", crypt},
190 {"decrypt", decrypt},
191 {NULL, NULL}
192};
193
194
195int luaopen_md5_core (lua_State *L) {
196 lua_newtable(L);
197 luaL_setfuncs(L, md5lib, 0);
198 set_info (L);
199 return 1;
200}