about summary refs log tree commit diff stats
path: root/filter.c
diff options
context:
space:
mode:
Diffstat (limited to 'filter.c')
-rw-r--r--filter.c255
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
18static inline void reap_filter(struct cgit_filter *filter) 12static 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
142void cgit_init_filters(void)
143{
144}
145#endif
146
147#ifndef NO_LUA
148static size_t (*libc_fwrite)(const void *buf, size_t size, size_t n, FILE *);
149static ssize_t (*libc_write)(int fd, const void *buf, size_t size);
150static ssize_t (*filter_write)(struct cgit_filter *base, const void *buf, size_t count) = NULL;
151static struct cgit_filter *current_write_filter = NULL;
152
153void 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
167size_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
174ssize_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
181static 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
190static 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
198struct lua_filter {
199 struct cgit_filter base;
200 char *script_file;
201 lua_State *lua_state;
202};
203
204static 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
210static 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
224static 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
243static int html_lua_filter(lua_State *lua_state)
244{
245 return hook_lua_filter(lua_state, html);
246}
247
248static int html_txt_lua_filter(lua_State *lua_state)
249{
250 return hook_lua_filter(lua_state, html_txt);
251}
252
253static int html_attr_lua_filter(lua_State *lua_state)
254{
255 return hook_lua_filter(lua_state, html_attr);
256}
257
258static int html_url_path_lua_filter(lua_State *lua_state)
259{
260 return hook_lua_filter(lua_state, html_url_path);
261}
262
263static int html_url_arg_lua_filter(lua_State *lua_state)
264{
265 return hook_lua_filter(lua_state, html_url_arg);
266}
267
268static int html_include_lua_filter(lua_State *lua_state)
269{
270 return hook_lua_filter(lua_state, (void (*)(const char *))html_include);
271}
272
273static 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
288static 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
320static 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
343static 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
361static 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
368static 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
387int cgit_open_filter(struct cgit_filter *filter, ...) 135int 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
423struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype) 168struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype)