immunio 0.15.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +234 -0
  3. data/README.md +147 -0
  4. data/bin/immunio +5 -0
  5. data/lib/immunio.rb +29 -0
  6. data/lib/immunio/agent.rb +260 -0
  7. data/lib/immunio/authentication.rb +96 -0
  8. data/lib/immunio/blocked_app.rb +38 -0
  9. data/lib/immunio/channel.rb +432 -0
  10. data/lib/immunio/cli.rb +39 -0
  11. data/lib/immunio/context.rb +114 -0
  12. data/lib/immunio/errors.rb +43 -0
  13. data/lib/immunio/immunio_ca.crt +45 -0
  14. data/lib/immunio/logger.rb +87 -0
  15. data/lib/immunio/plugins/action_dispatch.rb +45 -0
  16. data/lib/immunio/plugins/action_view.rb +431 -0
  17. data/lib/immunio/plugins/active_record.rb +707 -0
  18. data/lib/immunio/plugins/active_record_relation.rb +370 -0
  19. data/lib/immunio/plugins/authlogic.rb +80 -0
  20. data/lib/immunio/plugins/csrf.rb +24 -0
  21. data/lib/immunio/plugins/devise.rb +40 -0
  22. data/lib/immunio/plugins/environment_reporter.rb +69 -0
  23. data/lib/immunio/plugins/eval.rb +51 -0
  24. data/lib/immunio/plugins/exception_handler.rb +55 -0
  25. data/lib/immunio/plugins/gems_tracker.rb +5 -0
  26. data/lib/immunio/plugins/haml.rb +36 -0
  27. data/lib/immunio/plugins/http_finisher.rb +50 -0
  28. data/lib/immunio/plugins/http_tracker.rb +203 -0
  29. data/lib/immunio/plugins/io.rb +96 -0
  30. data/lib/immunio/plugins/redirect.rb +42 -0
  31. data/lib/immunio/plugins/warden.rb +66 -0
  32. data/lib/immunio/processor.rb +234 -0
  33. data/lib/immunio/rails.rb +26 -0
  34. data/lib/immunio/request.rb +139 -0
  35. data/lib/immunio/rufus_lua_ext/ref.rb +27 -0
  36. data/lib/immunio/rufus_lua_ext/state.rb +157 -0
  37. data/lib/immunio/rufus_lua_ext/table.rb +137 -0
  38. data/lib/immunio/rufus_lua_ext/utils.rb +13 -0
  39. data/lib/immunio/version.rb +5 -0
  40. data/lib/immunio/vm.rb +291 -0
  41. data/lua-hooks/ext/all.c +78 -0
  42. data/lua-hooks/ext/bitop/README +22 -0
  43. data/lua-hooks/ext/bitop/bit.c +189 -0
  44. data/lua-hooks/ext/extconf.rb +38 -0
  45. data/lua-hooks/ext/libinjection/COPYING +37 -0
  46. data/lua-hooks/ext/libinjection/libinjection.h +65 -0
  47. data/lua-hooks/ext/libinjection/libinjection_html5.c +847 -0
  48. data/lua-hooks/ext/libinjection/libinjection_html5.h +54 -0
  49. data/lua-hooks/ext/libinjection/libinjection_sqli.c +2301 -0
  50. data/lua-hooks/ext/libinjection/libinjection_sqli.h +295 -0
  51. data/lua-hooks/ext/libinjection/libinjection_sqli_data.h +9349 -0
  52. data/lua-hooks/ext/libinjection/libinjection_xss.c +531 -0
  53. data/lua-hooks/ext/libinjection/libinjection_xss.h +21 -0
  54. data/lua-hooks/ext/libinjection/lualib.c +109 -0
  55. data/lua-hooks/ext/lpeg/HISTORY +90 -0
  56. data/lua-hooks/ext/lpeg/lpcap.c +537 -0
  57. data/lua-hooks/ext/lpeg/lpcap.h +43 -0
  58. data/lua-hooks/ext/lpeg/lpcode.c +986 -0
  59. data/lua-hooks/ext/lpeg/lpcode.h +34 -0
  60. data/lua-hooks/ext/lpeg/lpeg-128.gif +0 -0
  61. data/lua-hooks/ext/lpeg/lpeg.html +1429 -0
  62. data/lua-hooks/ext/lpeg/lpprint.c +244 -0
  63. data/lua-hooks/ext/lpeg/lpprint.h +35 -0
  64. data/lua-hooks/ext/lpeg/lptree.c +1238 -0
  65. data/lua-hooks/ext/lpeg/lptree.h +77 -0
  66. data/lua-hooks/ext/lpeg/lptypes.h +149 -0
  67. data/lua-hooks/ext/lpeg/lpvm.c +355 -0
  68. data/lua-hooks/ext/lpeg/lpvm.h +58 -0
  69. data/lua-hooks/ext/lpeg/makefile +55 -0
  70. data/lua-hooks/ext/lpeg/re.html +498 -0
  71. data/lua-hooks/ext/lpeg/test.lua +1409 -0
  72. data/lua-hooks/ext/lua-cmsgpack/CMakeLists.txt +45 -0
  73. data/lua-hooks/ext/lua-cmsgpack/README.md +115 -0
  74. data/lua-hooks/ext/lua-cmsgpack/lua_cmsgpack.c +957 -0
  75. data/lua-hooks/ext/lua-cmsgpack/test.lua +570 -0
  76. data/lua-hooks/ext/lua-snapshot/LICENSE +7 -0
  77. data/lua-hooks/ext/lua-snapshot/Makefile +12 -0
  78. data/lua-hooks/ext/lua-snapshot/README.md +18 -0
  79. data/lua-hooks/ext/lua-snapshot/dump.lua +15 -0
  80. data/lua-hooks/ext/lua-snapshot/snapshot.c +455 -0
  81. data/lua-hooks/ext/lua/COPYRIGHT +34 -0
  82. data/lua-hooks/ext/lua/lapi.c +1087 -0
  83. data/lua-hooks/ext/lua/lapi.h +16 -0
  84. data/lua-hooks/ext/lua/lauxlib.c +652 -0
  85. data/lua-hooks/ext/lua/lauxlib.h +174 -0
  86. data/lua-hooks/ext/lua/lbaselib.c +659 -0
  87. data/lua-hooks/ext/lua/lcode.c +831 -0
  88. data/lua-hooks/ext/lua/lcode.h +76 -0
  89. data/lua-hooks/ext/lua/ldblib.c +398 -0
  90. data/lua-hooks/ext/lua/ldebug.c +638 -0
  91. data/lua-hooks/ext/lua/ldebug.h +33 -0
  92. data/lua-hooks/ext/lua/ldo.c +519 -0
  93. data/lua-hooks/ext/lua/ldo.h +57 -0
  94. data/lua-hooks/ext/lua/ldump.c +164 -0
  95. data/lua-hooks/ext/lua/lfunc.c +174 -0
  96. data/lua-hooks/ext/lua/lfunc.h +34 -0
  97. data/lua-hooks/ext/lua/lgc.c +710 -0
  98. data/lua-hooks/ext/lua/lgc.h +110 -0
  99. data/lua-hooks/ext/lua/linit.c +38 -0
  100. data/lua-hooks/ext/lua/liolib.c +556 -0
  101. data/lua-hooks/ext/lua/llex.c +463 -0
  102. data/lua-hooks/ext/lua/llex.h +81 -0
  103. data/lua-hooks/ext/lua/llimits.h +128 -0
  104. data/lua-hooks/ext/lua/lmathlib.c +263 -0
  105. data/lua-hooks/ext/lua/lmem.c +86 -0
  106. data/lua-hooks/ext/lua/lmem.h +49 -0
  107. data/lua-hooks/ext/lua/loadlib.c +705 -0
  108. data/lua-hooks/ext/lua/loadlib_rel.c +760 -0
  109. data/lua-hooks/ext/lua/lobject.c +214 -0
  110. data/lua-hooks/ext/lua/lobject.h +381 -0
  111. data/lua-hooks/ext/lua/lopcodes.c +102 -0
  112. data/lua-hooks/ext/lua/lopcodes.h +268 -0
  113. data/lua-hooks/ext/lua/loslib.c +243 -0
  114. data/lua-hooks/ext/lua/lparser.c +1339 -0
  115. data/lua-hooks/ext/lua/lparser.h +82 -0
  116. data/lua-hooks/ext/lua/lstate.c +214 -0
  117. data/lua-hooks/ext/lua/lstate.h +169 -0
  118. data/lua-hooks/ext/lua/lstring.c +111 -0
  119. data/lua-hooks/ext/lua/lstring.h +31 -0
  120. data/lua-hooks/ext/lua/lstrlib.c +871 -0
  121. data/lua-hooks/ext/lua/ltable.c +588 -0
  122. data/lua-hooks/ext/lua/ltable.h +40 -0
  123. data/lua-hooks/ext/lua/ltablib.c +287 -0
  124. data/lua-hooks/ext/lua/ltm.c +75 -0
  125. data/lua-hooks/ext/lua/ltm.h +54 -0
  126. data/lua-hooks/ext/lua/lua.c +392 -0
  127. data/lua-hooks/ext/lua/lua.def +131 -0
  128. data/lua-hooks/ext/lua/lua.h +388 -0
  129. data/lua-hooks/ext/lua/lua.rc +28 -0
  130. data/lua-hooks/ext/lua/lua_dll.rc +26 -0
  131. data/lua-hooks/ext/lua/luac.c +200 -0
  132. data/lua-hooks/ext/lua/luac.rc +1 -0
  133. data/lua-hooks/ext/lua/luaconf.h +763 -0
  134. data/lua-hooks/ext/lua/luaconf.h.in +724 -0
  135. data/lua-hooks/ext/lua/luaconf.h.orig +763 -0
  136. data/lua-hooks/ext/lua/lualib.h +53 -0
  137. data/lua-hooks/ext/lua/lundump.c +227 -0
  138. data/lua-hooks/ext/lua/lundump.h +36 -0
  139. data/lua-hooks/ext/lua/lvm.c +767 -0
  140. data/lua-hooks/ext/lua/lvm.h +36 -0
  141. data/lua-hooks/ext/lua/lzio.c +82 -0
  142. data/lua-hooks/ext/lua/lzio.h +67 -0
  143. data/lua-hooks/ext/lua/print.c +227 -0
  144. data/lua-hooks/ext/luautf8/README.md +152 -0
  145. data/lua-hooks/ext/luautf8/lutf8lib.c +1274 -0
  146. data/lua-hooks/ext/luautf8/unidata.h +3064 -0
  147. data/lua-hooks/lib/boot.lua +254 -0
  148. data/lua-hooks/lib/encode.lua +4 -0
  149. data/lua-hooks/lib/lexers/LICENSE +21 -0
  150. data/lua-hooks/lib/lexers/bash.lua +134 -0
  151. data/lua-hooks/lib/lexers/bash_dqstr.lua +62 -0
  152. data/lua-hooks/lib/lexers/css.lua +216 -0
  153. data/lua-hooks/lib/lexers/html.lua +106 -0
  154. data/lua-hooks/lib/lexers/javascript.lua +68 -0
  155. data/lua-hooks/lib/lexers/lexer.lua +1575 -0
  156. data/lua-hooks/lib/lexers/markers.lua +33 -0
  157. metadata +308 -0
@@ -0,0 +1,110 @@
1
+ /*
2
+ ** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $
3
+ ** Garbage Collector
4
+ ** See Copyright Notice in lua.h
5
+ */
6
+
7
+ #ifndef lgc_h
8
+ #define lgc_h
9
+
10
+
11
+ #include "lobject.h"
12
+
13
+
14
+ /*
15
+ ** Possible states of the Garbage Collector
16
+ */
17
+ #define GCSpause 0
18
+ #define GCSpropagate 1
19
+ #define GCSsweepstring 2
20
+ #define GCSsweep 3
21
+ #define GCSfinalize 4
22
+
23
+
24
+ /*
25
+ ** some userful bit tricks
26
+ */
27
+ #define resetbits(x,m) ((x) &= cast(lu_byte, ~(m)))
28
+ #define setbits(x,m) ((x) |= (m))
29
+ #define testbits(x,m) ((x) & (m))
30
+ #define bitmask(b) (1<<(b))
31
+ #define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2))
32
+ #define l_setbit(x,b) setbits(x, bitmask(b))
33
+ #define resetbit(x,b) resetbits(x, bitmask(b))
34
+ #define testbit(x,b) testbits(x, bitmask(b))
35
+ #define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2)))
36
+ #define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2)))
37
+ #define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2)))
38
+
39
+
40
+
41
+ /*
42
+ ** Layout for bit use in `marked' field:
43
+ ** bit 0 - object is white (type 0)
44
+ ** bit 1 - object is white (type 1)
45
+ ** bit 2 - object is black
46
+ ** bit 3 - for userdata: has been finalized
47
+ ** bit 3 - for tables: has weak keys
48
+ ** bit 4 - for tables: has weak values
49
+ ** bit 5 - object is fixed (should not be collected)
50
+ ** bit 6 - object is "super" fixed (only the main thread)
51
+ */
52
+
53
+
54
+ #define WHITE0BIT 0
55
+ #define WHITE1BIT 1
56
+ #define BLACKBIT 2
57
+ #define FINALIZEDBIT 3
58
+ #define KEYWEAKBIT 3
59
+ #define VALUEWEAKBIT 4
60
+ #define FIXEDBIT 5
61
+ #define SFIXEDBIT 6
62
+ #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
63
+
64
+
65
+ #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)
66
+ #define isblack(x) testbit((x)->gch.marked, BLACKBIT)
67
+ #define isgray(x) (!isblack(x) && !iswhite(x))
68
+
69
+ #define otherwhite(g) (g->currentwhite ^ WHITEBITS)
70
+ #define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS)
71
+
72
+ #define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
73
+ #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT)
74
+
75
+ #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x)))
76
+
77
+ #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
78
+
79
+
80
+ #define luaC_checkGC(L) { \
81
+ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \
82
+ if (G(L)->totalbytes >= G(L)->GCthreshold) \
83
+ luaC_step(L); }
84
+
85
+
86
+ #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \
87
+ luaC_barrierf(L,obj2gco(p),gcvalue(v)); }
88
+
89
+ #define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \
90
+ luaC_barrierback(L,t); }
91
+
92
+ #define luaC_objbarrier(L,p,o) \
93
+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
94
+ luaC_barrierf(L,obj2gco(p),obj2gco(o)); }
95
+
96
+ #define luaC_objbarriert(L,t,o) \
97
+ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }
98
+
99
+ LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);
100
+ LUAI_FUNC void luaC_callGCTM (lua_State *L);
101
+ LUAI_FUNC void luaC_freeall (lua_State *L);
102
+ LUAI_FUNC void luaC_step (lua_State *L);
103
+ LUAI_FUNC void luaC_fullgc (lua_State *L);
104
+ LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);
105
+ LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);
106
+ LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);
107
+ LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);
108
+
109
+
110
+ #endif
@@ -0,0 +1,38 @@
1
+ /*
2
+ ** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $
3
+ ** Initialization of libraries for lua.c
4
+ ** See Copyright Notice in lua.h
5
+ */
6
+
7
+
8
+ #define linit_c
9
+ #define LUA_LIB
10
+
11
+ #include "lua.h"
12
+
13
+ #include "lualib.h"
14
+ #include "lauxlib.h"
15
+
16
+ // This is customised in ../lua.c
17
+ // static const luaL_Reg lualibs[] = {
18
+ // {"", luaopen_base},
19
+ // {LUA_LOADLIBNAME, luaopen_package},
20
+ // {LUA_TABLIBNAME, luaopen_table},
21
+ // {LUA_IOLIBNAME, luaopen_io},
22
+ // {LUA_OSLIBNAME, luaopen_os},
23
+ // {LUA_STRLIBNAME, luaopen_string},
24
+ // {LUA_MATHLIBNAME, luaopen_math},
25
+ // {LUA_DBLIBNAME, luaopen_debug},
26
+ // {NULL, NULL}
27
+ // };
28
+
29
+
30
+ LUALIB_API void luaL_openlibs (lua_State *L) {
31
+ const luaL_Reg *lib = lualibs;
32
+ for (; lib->func; lib++) {
33
+ lua_pushcfunction(L, lib->func);
34
+ lua_pushstring(L, lib->name);
35
+ lua_call(L, 1, 0);
36
+ }
37
+ }
38
+
@@ -0,0 +1,556 @@
1
+ /*
2
+ ** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $
3
+ ** Standard I/O (and system) library
4
+ ** See Copyright Notice in lua.h
5
+ */
6
+
7
+
8
+ #include <errno.h>
9
+ #include <stdio.h>
10
+ #include <stdlib.h>
11
+ #include <string.h>
12
+
13
+ #define liolib_c
14
+ #define LUA_LIB
15
+
16
+ #include "lua.h"
17
+
18
+ #include "lauxlib.h"
19
+ #include "lualib.h"
20
+
21
+
22
+
23
+ #define IO_INPUT 1
24
+ #define IO_OUTPUT 2
25
+
26
+
27
+ static const char *const fnames[] = {"input", "output"};
28
+
29
+
30
+ static int pushresult (lua_State *L, int i, const char *filename) {
31
+ int en = errno; /* calls to Lua API may change this value */
32
+ if (i) {
33
+ lua_pushboolean(L, 1);
34
+ return 1;
35
+ }
36
+ else {
37
+ lua_pushnil(L);
38
+ if (filename)
39
+ lua_pushfstring(L, "%s: %s", filename, strerror(en));
40
+ else
41
+ lua_pushfstring(L, "%s", strerror(en));
42
+ lua_pushinteger(L, en);
43
+ return 3;
44
+ }
45
+ }
46
+
47
+
48
+ static void fileerror (lua_State *L, int arg, const char *filename) {
49
+ lua_pushfstring(L, "%s: %s", filename, strerror(errno));
50
+ luaL_argerror(L, arg, lua_tostring(L, -1));
51
+ }
52
+
53
+
54
+ #define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
55
+
56
+
57
+ static int io_type (lua_State *L) {
58
+ void *ud;
59
+ luaL_checkany(L, 1);
60
+ ud = lua_touserdata(L, 1);
61
+ lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
62
+ if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
63
+ lua_pushnil(L); /* not a file */
64
+ else if (*((FILE **)ud) == NULL)
65
+ lua_pushliteral(L, "closed file");
66
+ else
67
+ lua_pushliteral(L, "file");
68
+ return 1;
69
+ }
70
+
71
+
72
+ static FILE *tofile (lua_State *L) {
73
+ FILE **f = tofilep(L);
74
+ if (*f == NULL)
75
+ luaL_error(L, "attempt to use a closed file");
76
+ return *f;
77
+ }
78
+
79
+
80
+
81
+ /*
82
+ ** When creating file handles, always creates a `closed' file handle
83
+ ** before opening the actual file; so, if there is a memory error, the
84
+ ** file is not left opened.
85
+ */
86
+ static FILE **newfile (lua_State *L) {
87
+ FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
88
+ *pf = NULL; /* file handle is currently `closed' */
89
+ luaL_getmetatable(L, LUA_FILEHANDLE);
90
+ lua_setmetatable(L, -2);
91
+ return pf;
92
+ }
93
+
94
+
95
+ /*
96
+ ** function to (not) close the standard files stdin, stdout, and stderr
97
+ */
98
+ static int io_noclose (lua_State *L) {
99
+ lua_pushnil(L);
100
+ lua_pushliteral(L, "cannot close standard file");
101
+ return 2;
102
+ }
103
+
104
+
105
+ /*
106
+ ** function to close 'popen' files
107
+ */
108
+ static int io_pclose (lua_State *L) {
109
+ FILE **p = tofilep(L);
110
+ int ok = lua_pclose(L, *p);
111
+ *p = NULL;
112
+ return pushresult(L, ok, NULL);
113
+ }
114
+
115
+
116
+ /*
117
+ ** function to close regular files
118
+ */
119
+ static int io_fclose (lua_State *L) {
120
+ FILE **p = tofilep(L);
121
+ int ok = (fclose(*p) == 0);
122
+ *p = NULL;
123
+ return pushresult(L, ok, NULL);
124
+ }
125
+
126
+
127
+ static int aux_close (lua_State *L) {
128
+ lua_getfenv(L, 1);
129
+ lua_getfield(L, -1, "__close");
130
+ return (lua_tocfunction(L, -1))(L);
131
+ }
132
+
133
+
134
+ static int io_close (lua_State *L) {
135
+ if (lua_isnone(L, 1))
136
+ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
137
+ tofile(L); /* make sure argument is a file */
138
+ return aux_close(L);
139
+ }
140
+
141
+
142
+ static int io_gc (lua_State *L) {
143
+ FILE *f = *tofilep(L);
144
+ /* ignore closed files */
145
+ if (f != NULL)
146
+ aux_close(L);
147
+ return 0;
148
+ }
149
+
150
+
151
+ static int io_tostring (lua_State *L) {
152
+ FILE *f = *tofilep(L);
153
+ if (f == NULL)
154
+ lua_pushliteral(L, "file (closed)");
155
+ else
156
+ lua_pushfstring(L, "file (%p)", f);
157
+ return 1;
158
+ }
159
+
160
+
161
+ static int io_open (lua_State *L) {
162
+ const char *filename = luaL_checkstring(L, 1);
163
+ const char *mode = luaL_optstring(L, 2, "r");
164
+ FILE **pf = newfile(L);
165
+ *pf = fopen(filename, mode);
166
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
167
+ }
168
+
169
+
170
+ /*
171
+ ** this function has a separated environment, which defines the
172
+ ** correct __close for 'popen' files
173
+ */
174
+ static int io_popen (lua_State *L) {
175
+ const char *filename = luaL_checkstring(L, 1);
176
+ const char *mode = luaL_optstring(L, 2, "r");
177
+ FILE **pf = newfile(L);
178
+ *pf = lua_popen(L, filename, mode);
179
+ return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
180
+ }
181
+
182
+
183
+ static int io_tmpfile (lua_State *L) {
184
+ FILE **pf = newfile(L);
185
+ *pf = tmpfile();
186
+ return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
187
+ }
188
+
189
+
190
+ static FILE *getiofile (lua_State *L, int findex) {
191
+ FILE *f;
192
+ lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
193
+ f = *(FILE **)lua_touserdata(L, -1);
194
+ if (f == NULL)
195
+ luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
196
+ return f;
197
+ }
198
+
199
+
200
+ static int g_iofile (lua_State *L, int f, const char *mode) {
201
+ if (!lua_isnoneornil(L, 1)) {
202
+ const char *filename = lua_tostring(L, 1);
203
+ if (filename) {
204
+ FILE **pf = newfile(L);
205
+ *pf = fopen(filename, mode);
206
+ if (*pf == NULL)
207
+ fileerror(L, 1, filename);
208
+ }
209
+ else {
210
+ tofile(L); /* check that it's a valid file handle */
211
+ lua_pushvalue(L, 1);
212
+ }
213
+ lua_rawseti(L, LUA_ENVIRONINDEX, f);
214
+ }
215
+ /* return current value */
216
+ lua_rawgeti(L, LUA_ENVIRONINDEX, f);
217
+ return 1;
218
+ }
219
+
220
+
221
+ static int io_input (lua_State *L) {
222
+ return g_iofile(L, IO_INPUT, "r");
223
+ }
224
+
225
+
226
+ static int io_output (lua_State *L) {
227
+ return g_iofile(L, IO_OUTPUT, "w");
228
+ }
229
+
230
+
231
+ static int io_readline (lua_State *L);
232
+
233
+
234
+ static void aux_lines (lua_State *L, int idx, int toclose) {
235
+ lua_pushvalue(L, idx);
236
+ lua_pushboolean(L, toclose); /* close/not close file when finished */
237
+ lua_pushcclosure(L, io_readline, 2);
238
+ }
239
+
240
+
241
+ static int f_lines (lua_State *L) {
242
+ tofile(L); /* check that it's a valid file handle */
243
+ aux_lines(L, 1, 0);
244
+ return 1;
245
+ }
246
+
247
+
248
+ static int io_lines (lua_State *L) {
249
+ if (lua_isnoneornil(L, 1)) { /* no arguments? */
250
+ /* will iterate over default input */
251
+ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
252
+ return f_lines(L);
253
+ }
254
+ else {
255
+ const char *filename = luaL_checkstring(L, 1);
256
+ FILE **pf = newfile(L);
257
+ *pf = fopen(filename, "r");
258
+ if (*pf == NULL)
259
+ fileerror(L, 1, filename);
260
+ aux_lines(L, lua_gettop(L), 1);
261
+ return 1;
262
+ }
263
+ }
264
+
265
+
266
+ /*
267
+ ** {======================================================
268
+ ** READ
269
+ ** =======================================================
270
+ */
271
+
272
+
273
+ static int read_number (lua_State *L, FILE *f) {
274
+ lua_Number d;
275
+ if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
276
+ lua_pushnumber(L, d);
277
+ return 1;
278
+ }
279
+ else {
280
+ lua_pushnil(L); /* "result" to be removed */
281
+ return 0; /* read fails */
282
+ }
283
+ }
284
+
285
+
286
+ static int test_eof (lua_State *L, FILE *f) {
287
+ int c = getc(f);
288
+ ungetc(c, f);
289
+ lua_pushlstring(L, NULL, 0);
290
+ return (c != EOF);
291
+ }
292
+
293
+
294
+ static int read_line (lua_State *L, FILE *f) {
295
+ luaL_Buffer b;
296
+ luaL_buffinit(L, &b);
297
+ for (;;) {
298
+ size_t l;
299
+ char *p = luaL_prepbuffer(&b);
300
+ if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
301
+ luaL_pushresult(&b); /* close buffer */
302
+ return (lua_objlen(L, -1) > 0); /* check whether read something */
303
+ }
304
+ l = strlen(p);
305
+ if (l == 0 || p[l-1] != '\n')
306
+ luaL_addsize(&b, l);
307
+ else {
308
+ luaL_addsize(&b, l - 1); /* do not include `eol' */
309
+ luaL_pushresult(&b); /* close buffer */
310
+ return 1; /* read at least an `eol' */
311
+ }
312
+ }
313
+ }
314
+
315
+
316
+ static int read_chars (lua_State *L, FILE *f, size_t n) {
317
+ size_t rlen; /* how much to read */
318
+ size_t nr; /* number of chars actually read */
319
+ luaL_Buffer b;
320
+ luaL_buffinit(L, &b);
321
+ rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
322
+ do {
323
+ char *p = luaL_prepbuffer(&b);
324
+ if (rlen > n) rlen = n; /* cannot read more than asked */
325
+ nr = fread(p, sizeof(char), rlen, f);
326
+ luaL_addsize(&b, nr);
327
+ n -= nr; /* still have to read `n' chars */
328
+ } while (n > 0 && nr == rlen); /* until end of count or eof */
329
+ luaL_pushresult(&b); /* close buffer */
330
+ return (n == 0 || lua_objlen(L, -1) > 0);
331
+ }
332
+
333
+
334
+ static int g_read (lua_State *L, FILE *f, int first) {
335
+ int nargs = lua_gettop(L) - 1;
336
+ int success;
337
+ int n;
338
+ clearerr(f);
339
+ if (nargs == 0) { /* no arguments? */
340
+ success = read_line(L, f);
341
+ n = first+1; /* to return 1 result */
342
+ }
343
+ else { /* ensure stack space for all results and for auxlib's buffer */
344
+ luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
345
+ success = 1;
346
+ for (n = first; nargs-- && success; n++) {
347
+ if (lua_type(L, n) == LUA_TNUMBER) {
348
+ size_t l = (size_t)lua_tointeger(L, n);
349
+ success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
350
+ }
351
+ else {
352
+ const char *p = lua_tostring(L, n);
353
+ luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
354
+ switch (p[1]) {
355
+ case 'n': /* number */
356
+ success = read_number(L, f);
357
+ break;
358
+ case 'l': /* line */
359
+ success = read_line(L, f);
360
+ break;
361
+ case 'a': /* file */
362
+ read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
363
+ success = 1; /* always success */
364
+ break;
365
+ default:
366
+ return luaL_argerror(L, n, "invalid format");
367
+ }
368
+ }
369
+ }
370
+ }
371
+ if (ferror(f))
372
+ return pushresult(L, 0, NULL);
373
+ if (!success) {
374
+ lua_pop(L, 1); /* remove last result */
375
+ lua_pushnil(L); /* push nil instead */
376
+ }
377
+ return n - first;
378
+ }
379
+
380
+
381
+ static int io_read (lua_State *L) {
382
+ return g_read(L, getiofile(L, IO_INPUT), 1);
383
+ }
384
+
385
+
386
+ static int f_read (lua_State *L) {
387
+ return g_read(L, tofile(L), 2);
388
+ }
389
+
390
+
391
+ static int io_readline (lua_State *L) {
392
+ FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
393
+ int sucess;
394
+ if (f == NULL) /* file is already closed? */
395
+ luaL_error(L, "file is already closed");
396
+ sucess = read_line(L, f);
397
+ if (ferror(f))
398
+ return luaL_error(L, "%s", strerror(errno));
399
+ if (sucess) return 1;
400
+ else { /* EOF */
401
+ if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
402
+ lua_settop(L, 0);
403
+ lua_pushvalue(L, lua_upvalueindex(1));
404
+ aux_close(L); /* close it */
405
+ }
406
+ return 0;
407
+ }
408
+ }
409
+
410
+ /* }====================================================== */
411
+
412
+
413
+ static int g_write (lua_State *L, FILE *f, int arg) {
414
+ int nargs = lua_gettop(L) - 1;
415
+ int status = 1;
416
+ for (; nargs--; arg++) {
417
+ if (lua_type(L, arg) == LUA_TNUMBER) {
418
+ /* optimization: could be done exactly as for strings */
419
+ status = status &&
420
+ fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
421
+ }
422
+ else {
423
+ size_t l;
424
+ const char *s = luaL_checklstring(L, arg, &l);
425
+ status = status && (fwrite(s, sizeof(char), l, f) == l);
426
+ }
427
+ }
428
+ return pushresult(L, status, NULL);
429
+ }
430
+
431
+
432
+ static int io_write (lua_State *L) {
433
+ return g_write(L, getiofile(L, IO_OUTPUT), 1);
434
+ }
435
+
436
+
437
+ static int f_write (lua_State *L) {
438
+ return g_write(L, tofile(L), 2);
439
+ }
440
+
441
+
442
+ static int f_seek (lua_State *L) {
443
+ static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
444
+ static const char *const modenames[] = {"set", "cur", "end", NULL};
445
+ FILE *f = tofile(L);
446
+ int op = luaL_checkoption(L, 2, "cur", modenames);
447
+ long offset = luaL_optlong(L, 3, 0);
448
+ op = fseek(f, offset, mode[op]);
449
+ if (op)
450
+ return pushresult(L, 0, NULL); /* error */
451
+ else {
452
+ lua_pushinteger(L, ftell(f));
453
+ return 1;
454
+ }
455
+ }
456
+
457
+
458
+ static int f_setvbuf (lua_State *L) {
459
+ static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
460
+ static const char *const modenames[] = {"no", "full", "line", NULL};
461
+ FILE *f = tofile(L);
462
+ int op = luaL_checkoption(L, 2, NULL, modenames);
463
+ lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
464
+ int res = setvbuf(f, NULL, mode[op], sz);
465
+ return pushresult(L, res == 0, NULL);
466
+ }
467
+
468
+
469
+
470
+ static int io_flush (lua_State *L) {
471
+ return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
472
+ }
473
+
474
+
475
+ static int f_flush (lua_State *L) {
476
+ return pushresult(L, fflush(tofile(L)) == 0, NULL);
477
+ }
478
+
479
+
480
+ static const luaL_Reg iolib[] = {
481
+ {"close", io_close},
482
+ {"flush", io_flush},
483
+ {"input", io_input},
484
+ {"lines", io_lines},
485
+ {"open", io_open},
486
+ {"output", io_output},
487
+ {"popen", io_popen},
488
+ {"read", io_read},
489
+ {"tmpfile", io_tmpfile},
490
+ {"type", io_type},
491
+ {"write", io_write},
492
+ {NULL, NULL}
493
+ };
494
+
495
+
496
+ static const luaL_Reg flib[] = {
497
+ {"close", io_close},
498
+ {"flush", f_flush},
499
+ {"lines", f_lines},
500
+ {"read", f_read},
501
+ {"seek", f_seek},
502
+ {"setvbuf", f_setvbuf},
503
+ {"write", f_write},
504
+ {"__gc", io_gc},
505
+ {"__tostring", io_tostring},
506
+ {NULL, NULL}
507
+ };
508
+
509
+
510
+ static void createmeta (lua_State *L) {
511
+ luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
512
+ lua_pushvalue(L, -1); /* push metatable */
513
+ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
514
+ luaL_register(L, NULL, flib); /* file methods */
515
+ }
516
+
517
+
518
+ static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
519
+ *newfile(L) = f;
520
+ if (k > 0) {
521
+ lua_pushvalue(L, -1);
522
+ lua_rawseti(L, LUA_ENVIRONINDEX, k);
523
+ }
524
+ lua_pushvalue(L, -2); /* copy environment */
525
+ lua_setfenv(L, -2); /* set it */
526
+ lua_setfield(L, -3, fname);
527
+ }
528
+
529
+
530
+ static void newfenv (lua_State *L, lua_CFunction cls) {
531
+ lua_createtable(L, 0, 1);
532
+ lua_pushcfunction(L, cls);
533
+ lua_setfield(L, -2, "__close");
534
+ }
535
+
536
+
537
+ LUALIB_API int luaopen_io (lua_State *L) {
538
+ createmeta(L);
539
+ /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
540
+ newfenv(L, io_fclose);
541
+ lua_replace(L, LUA_ENVIRONINDEX);
542
+ /* open library */
543
+ luaL_register(L, LUA_IOLIBNAME, iolib);
544
+ /* create (and set) default files */
545
+ newfenv(L, io_noclose); /* close function for default files */
546
+ createstdfile(L, stdin, IO_INPUT, "stdin");
547
+ createstdfile(L, stdout, IO_OUTPUT, "stdout");
548
+ createstdfile(L, stderr, 0, "stderr");
549
+ lua_pop(L, 1); /* pop environment for default files */
550
+ lua_getfield(L, -1, "popen");
551
+ newfenv(L, io_pclose); /* create environment for 'popen' */
552
+ lua_setfenv(L, -2); /* set fenv for 'popen' */
553
+ lua_pop(L, 1); /* pop 'popen' */
554
+ return 1;
555
+ }
556
+