From mboxrd@z Thu Jan 1 00:00:00 1970 From: john at keeping.me.uk (John Keeping) Date: Mon, 13 Jan 2014 08:55:31 +0000 Subject: [PATCH 06/12] filter: add preliminary lua support In-Reply-To: <1389586279-23724-7-git-send-email-Jason@zx2c4.com> References: <1389586279-23724-1-git-send-email-Jason@zx2c4.com> <1389586279-23724-7-git-send-email-Jason@zx2c4.com> Message-ID: <20140113085531.GY7608@serenity.lan> On Mon, Jan 13, 2014 at 05:11:13AM +0100, Jason A. Donenfeld wrote: [snip] > +static int html_lua_filter(lua_State *lua_state) > +{ > + size_t len; > + const char *str; > + > + str = lua_tostring(lua_state, 1); > + if (!str) > + return 0; > + len = strlen(str); > + libc_write(STDOUT_FILENO, str, len); > + return 0; > +} > + > +static void cleanup_lua_filter(struct cgit_filter *base) > +{ > + struct lua_filter *filter = (struct lua_filter *) base; > + > + if (!filter->lua_state) > + return; > + > + lua_close(filter->lua_state); > + filter->lua_state = NULL; > + if (filter->script_file) { > + free(filter->script_file); > + filter->script_file = NULL; > + } > +} > + > +static int init_lua_filter(struct lua_filter *filter) > +{ > + if (filter->lua_state) > + return 0; > + > + if (!(filter->lua_state = luaL_newstate())) > + return 1; > + > + luaL_openlibs(filter->lua_state); > + > + lua_pushcfunction(filter->lua_state, html_lua_filter); > + lua_setglobal(filter->lua_state, "html"); It would be good to provide some of the other html_* functions here, particularly html_txt so that filters don't need to re-invent the wheel for escaping output. That's probably slightly harder than the plain HTML, but I suspect we just need to wrap the call to the underlying function in an unhook_write/hook_write pair. > + > + if (luaL_dofile(filter->lua_state, filter->script_file)) { > + lua_close(filter->lua_state); > + filter->lua_state = NULL; > + return 1; > + } > + return 0; > +} > + > +static int open_lua_filter(struct cgit_filter *base, va_list ap) > +{ > + struct lua_filter *filter = (struct lua_filter *) base; > + int i; > + > + if (init_lua_filter(filter)) > + return 1; > + > + hook_write(base, write_lua_filter); > + > + lua_getglobal(filter->lua_state, "filter_open"); > + for (i = 0; i < filter->base.argument_count; ++i) > + lua_pushstring(filter->lua_state, va_arg(ap, char *)); > + if (lua_pcall(filter->lua_state, filter->base.argument_count, 0, 0)) > + return 1; > + return 0; > +} > + > +static int close_lua_filter(struct cgit_filter *base) > +{ > + struct lua_filter *filter = (struct lua_filter *) base; > + int ret = 0; > + > + lua_getglobal(filter->lua_state, "filter_close"); > + if (lua_pcall(filter->lua_state, 0, 0, 0)) > + ret = 1; > + unhook_write(); > + return ret; > +} > + > +static void fprintf_lua_filter(struct cgit_filter *base, FILE *f, const char *prefix) > +{ > + struct lua_filter *filter = (struct lua_filter *) base; > + fprintf(f, "%slua:%s\n", prefix, filter->script_file); > +} > + > + > +static struct cgit_filter *new_lua_filter(const char *cmd, int argument_count) > +{ > + struct lua_filter *filter; > + > + filter = xmalloc(sizeof(*filter)); > + memset(filter, 0, sizeof(*filter)); > + filter->base.open = open_lua_filter; > + filter->base.close = close_lua_filter; > + filter->base.fprintf = fprintf_lua_filter; > + filter->base.cleanup = cleanup_lua_filter; > + filter->base.argument_count = argument_count; > + filter->script_file = xstrdup(cmd); > + > + return &filter->base; > } > > +#endif