diff options
Diffstat (limited to 'filter.c')
-rw-r--r-- | filter.c | 255 |
1 files changed, 0 insertions, 255 deletions
diff --git a/filter.c b/filter.c index fba26aa..2b6c838 100644 --- a/filter.c +++ b/filter.c | |||
@@ -8,12 +8,6 @@ | |||
8 | 8 | ||
9 | #include "cgit.h" | 9 | #include "cgit.h" |
10 | #include "html.h" | 10 | #include "html.h" |
11 | #ifndef NO_LUA | ||
12 | #include <dlfcn.h> | ||
13 | #include <lua.h> | ||
14 | #include <lualib.h> | ||
15 | #include <lauxlib.h> | ||
16 | #endif | ||
17 | 11 | ||
18 | static inline void reap_filter(struct cgit_filter *filter) | 12 | static inline void reap_filter(struct cgit_filter *filter) |
19 | { | 13 | { |
@@ -138,252 +132,6 @@ void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **ar | |||
138 | filter->base.argument_count = 0; | 132 | filter->base.argument_count = 0; |
139 | } | 133 | } |
140 | 134 | ||
141 | #ifdef NO_LUA | ||
142 | void cgit_init_filters(void) | ||
143 | { | ||
144 | } | ||
145 | #endif | ||
146 | |||
147 | #ifndef NO_LUA | ||
148 | static size_t (*libc_fwrite)(const void *buf, size_t size, size_t n, FILE *); | ||
149 | static ssize_t (*libc_write)(int fd, const void *buf, size_t size); | ||
150 | static ssize_t (*filter_write)(struct cgit_filter *base, const void *buf, size_t count) = NULL; | ||
151 | static struct cgit_filter *current_write_filter = NULL; | ||
152 | |||
153 | void cgit_init_filters(void) | ||
154 | { | ||
155 | /* | ||
156 | * we need to wrap both functions since the Lua filter may | ||
157 | * have code which calls write(2) directly, bypassing fwrite(3) | ||
158 | */ | ||
159 | libc_fwrite = dlsym(RTLD_NEXT, "fwrite"); | ||
160 | if (!libc_fwrite) | ||
161 | die("Could not locate libc's write function"); | ||
162 | libc_write = dlsym(RTLD_NEXT, "write"); | ||
163 | if (!libc_write) | ||
164 | die("Could not locate libc's write function"); | ||
165 | } | ||
166 | |||
167 | size_t fwrite(const void *buf, size_t size, size_t n, FILE *f) | ||
168 | { | ||
169 | if (f != stdout || !filter_write) | ||
170 | return libc_fwrite(buf, size, n, f); | ||
171 | return filter_write(current_write_filter, buf, size * n); | ||
172 | } | ||
173 | |||
174 | ssize_t write(int fd, const void *buf, size_t count) | ||
175 | { | ||
176 | if (fd != STDOUT_FILENO || !filter_write) | ||
177 | return libc_write(fd, buf, count); | ||
178 | return filter_write(current_write_filter, buf, count); | ||
179 | } | ||
180 | |||
181 | static inline void hook_write(struct cgit_filter *filter, ssize_t (*new_write)(struct cgit_filter *base, const void *buf, size_t count)) | ||
182 | { | ||
183 | /* We want to avoid buggy nested patterns. */ | ||
184 | assert(filter_write == NULL); | ||
185 | assert(current_write_filter == NULL); | ||
186 | current_write_filter = filter; | ||
187 | filter_write = new_write; | ||
188 | } | ||
189 | |||
190 | static inline void unhook_write(void) | ||
191 | { | ||
192 | assert(filter_write != NULL); | ||
193 | assert(current_write_filter != NULL); | ||
194 | filter_write = NULL; | ||
195 | current_write_filter = NULL; | ||
196 | } | ||
197 | |||
198 | struct lua_filter { | ||
199 | struct cgit_filter base; | ||
200 | char *script_file; | ||
201 | lua_State *lua_state; | ||
202 | }; | ||
203 | |||
204 | static void error_lua_filter(struct lua_filter *filter) | ||
205 | { | ||
206 | die("Lua error in %s: %s", filter->script_file, lua_tostring(filter->lua_state, -1)); | ||
207 | lua_pop(filter->lua_state, 1); | ||
208 | } | ||
209 | |||
210 | static ssize_t write_lua_filter(struct cgit_filter *base, const void *buf, size_t count) | ||
211 | { | ||
212 | struct lua_filter *filter = (struct lua_filter *)base; | ||
213 | |||
214 | lua_getglobal(filter->lua_state, "filter_write"); | ||
215 | lua_pushlstring(filter->lua_state, buf, count); | ||
216 | if (lua_pcall(filter->lua_state, 1, 0, 0)) { | ||
217 | error_lua_filter(filter); | ||
218 | errno = EIO; | ||
219 | return -1; | ||
220 | } | ||
221 | return count; | ||
222 | } | ||
223 | |||
224 | static inline int hook_lua_filter(lua_State *lua_state, void (*fn)(const char *txt)) | ||
225 | { | ||
226 | const char *str; | ||
227 | ssize_t (*save_filter_write)(struct cgit_filter *base, const void *buf, size_t count); | ||
228 | struct cgit_filter *save_filter; | ||
229 | |||
230 | str = lua_tostring(lua_state, 1); | ||
231 | if (!str) | ||
232 | return 0; | ||
233 | |||
234 | save_filter_write = filter_write; | ||
235 | save_filter = current_write_filter; | ||
236 | unhook_write(); | ||
237 | fn(str); | ||
238 | hook_write(save_filter, save_filter_write); | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int html_lua_filter(lua_State *lua_state) | ||
244 | { | ||
245 | return hook_lua_filter(lua_state, html); | ||
246 | } | ||
247 | |||
248 | static int html_txt_lua_filter(lua_State *lua_state) | ||
249 | { | ||
250 | return hook_lua_filter(lua_state, html_txt); | ||
251 | } | ||
252 | |||
253 | static int html_attr_lua_filter(lua_State *lua_state) | ||
254 | { | ||
255 | return hook_lua_filter(lua_state, html_attr); | ||
256 | } | ||
257 | |||
258 | static int html_url_path_lua_filter(lua_State *lua_state) | ||
259 | { | ||
260 | return hook_lua_filter(lua_state, html_url_path); | ||
261 | } | ||
262 | |||
263 | static int html_url_arg_lua_filter(lua_State *lua_state) | ||
264 | { | ||
265 | return hook_lua_filter(lua_state, html_url_arg); | ||
266 | } | ||
267 | |||
268 | static int html_include_lua_filter(lua_State *lua_state) | ||
269 | { | ||
270 | return hook_lua_filter(lua_state, (void (*)(const char *))html_include); | ||
271 | } | ||
272 | |||
273 | static void cleanup_lua_filter(struct cgit_filter *base) | ||
274 | { | ||
275 | struct lua_filter *filter = (struct lua_filter *)base; | ||
276 | |||
277 | if (!filter->lua_state) | ||
278 | return; | ||
279 | |||
280 | lua_close(filter->lua_state); | ||
281 | filter->lua_state = NULL; | ||
282 | if (filter->script_file) { | ||
283 | free(filter->script_file); | ||
284 | filter->script_file = NULL; | ||
285 | } | ||
286 | } | ||
287 | |||
288 | static int init_lua_filter(struct lua_filter *filter) | ||
289 | { | ||
290 | if (filter->lua_state) | ||
291 | return 0; | ||
292 | |||
293 | if (!(filter->lua_state = luaL_newstate())) | ||
294 | return 1; | ||
295 | |||
296 | luaL_openlibs(filter->lua_state); | ||
297 | |||
298 | lua_pushcfunction(filter->lua_state, html_lua_filter); | ||
299 | lua_setglobal(filter->lua_state, "html"); | ||
300 | lua_pushcfunction(filter->lua_state, html_txt_lua_filter); | ||
301 | lua_setglobal(filter->lua_state, "html_txt"); | ||
302 | lua_pushcfunction(filter->lua_state, html_attr_lua_filter); | ||
303 | lua_setglobal(filter->lua_state, "html_attr"); | ||
304 | lua_pushcfunction(filter->lua_state, html_url_path_lua_filter); | ||
305 | lua_setglobal(filter->lua_state, "html_url_path"); | ||
306 | lua_pushcfunction(filter->lua_state, html_url_arg_lua_filter); | ||
307 | lua_setglobal(filter->lua_state, "html_url_arg"); | ||
308 | lua_pushcfunction(filter->lua_state, html_include_lua_filter); | ||
309 | lua_setglobal(filter->lua_state, "html_include"); | ||
310 | |||
311 | if (luaL_dofile(filter->lua_state, filter->script_file)) { | ||
312 | error_lua_filter(filter); | ||
313 | lua_close(filter->lua_state); | ||
314 | filter->lua_state = NULL; | ||
315 | return 1; | ||
316 | } | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static int open_lua_filter(struct cgit_filter *base, va_list ap) | ||
321 | { | ||
322 | struct lua_filter *filter = (struct lua_filter *)base; | ||
323 | int i; | ||
324 | |||
325 | if (fflush(stdout)) | ||
326 | return 1; | ||
327 | |||
328 | if (init_lua_filter(filter)) | ||
329 | return 1; | ||
330 | |||
331 | hook_write(base, write_lua_filter); | ||
332 | |||
333 | lua_getglobal(filter->lua_state, "filter_open"); | ||
334 | for (i = 0; i < filter->base.argument_count; ++i) | ||
335 | lua_pushstring(filter->lua_state, va_arg(ap, char *)); | ||
336 | if (lua_pcall(filter->lua_state, filter->base.argument_count, 0, 0)) { | ||
337 | error_lua_filter(filter); | ||
338 | return 1; | ||
339 | } | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int close_lua_filter(struct cgit_filter *base) | ||
344 | { | ||
345 | struct lua_filter *filter = (struct lua_filter *)base; | ||
346 | int ret = 0; | ||
347 | |||
348 | lua_getglobal(filter->lua_state, "filter_close"); | ||
349 | if (lua_pcall(filter->lua_state, 0, 1, 0)) { | ||
350 | error_lua_filter(filter); | ||
351 | ret = -1; | ||
352 | } else { | ||
353 | ret = lua_tonumber(filter->lua_state, -1); | ||
354 | lua_pop(filter->lua_state, 1); | ||
355 | } | ||
356 | |||
357 | unhook_write(); | ||
358 | return ret; | ||
359 | } | ||
360 | |||
361 | static void fprintf_lua_filter(struct cgit_filter *base, FILE *f, const char *prefix) | ||
362 | { | ||
363 | struct lua_filter *filter = (struct lua_filter *)base; | ||
364 | fprintf(f, "%slua:%s\n", prefix, filter->script_file); | ||
365 | } | ||
366 | |||
367 | |||
368 | static struct cgit_filter *new_lua_filter(const char *cmd, int argument_count) | ||
369 | { | ||
370 | struct lua_filter *filter; | ||
371 | |||
372 | filter = xmalloc(sizeof(*filter)); | ||
373 | memset(filter, 0, sizeof(*filter)); | ||
374 | filter->base.open = open_lua_filter; | ||
375 | filter->base.close = close_lua_filter; | ||
376 | filter->base.fprintf = fprintf_lua_filter; | ||
377 | filter->base.cleanup = cleanup_lua_filter; | ||
378 | filter->base.argument_count = argument_count; | ||
379 | filter->script_file = xstrdup(cmd); | ||
380 | |||
381 | return &filter->base; | ||
382 | } | ||
383 | |||
384 | #endif | ||
385 | |||
386 | |||
387 | int cgit_open_filter(struct cgit_filter *filter, ...) | 135 | int cgit_open_filter(struct cgit_filter *filter, ...) |
388 | { | 136 | { |
389 | int result; | 137 | int result; |
@@ -415,9 +163,6 @@ static const struct { | |||
415 | struct cgit_filter *(*ctor)(const char *cmd, int argument_count); | 163 | struct cgit_filter *(*ctor)(const char *cmd, int argument_count); |
416 | } filter_specs[] = { | 164 | } filter_specs[] = { |
417 | { "exec", new_exec_filter }, | 165 | { "exec", new_exec_filter }, |
418 | #ifndef NO_LUA | ||
419 | { "lua", new_lua_filter }, | ||
420 | #endif | ||
421 | }; | 166 | }; |
422 | 167 | ||
423 | struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype) | 168 | struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype) |