mirror of
https://github.com/moparisthebest/imapfilter
synced 2024-08-13 16:53:51 -04:00
269 lines
5.7 KiB
C
269 lines
5.7 KiB
C
|
#include <stdio.h>
|
||
|
|
||
|
#include <lua.h>
|
||
|
#include <lauxlib.h>
|
||
|
#include <lualib.h>
|
||
|
|
||
|
#include <pcre.h>
|
||
|
|
||
|
#include "imapfilter.h"
|
||
|
|
||
|
|
||
|
static int ifre_flags(lua_State *lua);
|
||
|
static int ifre_compile(lua_State *lua);
|
||
|
static int ifre_exec(lua_State *lua);
|
||
|
static int ifre_free(lua_State *lua);
|
||
|
|
||
|
/* Lua imapfilter library of PCRE related functions. */
|
||
|
static const luaL_reg ifrelib[] = {
|
||
|
{ "flags", ifre_flags },
|
||
|
{ "compile", ifre_compile },
|
||
|
{ "exec", ifre_exec },
|
||
|
{ "free", ifre_free },
|
||
|
{ NULL, NULL }
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Return PCRE available compile and exec flags.
|
||
|
*/
|
||
|
static int
|
||
|
ifre_flags(lua_State *lua)
|
||
|
{
|
||
|
|
||
|
if (lua_gettop(lua) != 0)
|
||
|
luaL_error(lua, "wrong number of arguments");
|
||
|
|
||
|
lua_newtable(lua);
|
||
|
|
||
|
#ifdef PCRE_CASELESS
|
||
|
set_table_number("CASELESS", PCRE_CASELESS);
|
||
|
#endif
|
||
|
#ifdef PCRE_MULTILINE
|
||
|
set_table_number("MULTILINE", PCRE_MULTILINE);
|
||
|
#endif
|
||
|
#ifdef PCRE_DOTALL
|
||
|
set_table_number("DOTALL", PCRE_DOTALL);
|
||
|
#endif
|
||
|
#ifdef PCRE_EXTENDED
|
||
|
set_table_number("EXTENDED", PCRE_EXTENDED);
|
||
|
#endif
|
||
|
#ifdef PCRE_ANCHORED
|
||
|
set_table_number("ANCHORED", PCRE_ANCHORED);
|
||
|
#endif
|
||
|
#ifdef PCRE_DOLLAR_ENDONLY
|
||
|
set_table_number("DOLLAR_ENDONLY", PCRE_DOLLAR_ENDONLY);
|
||
|
#endif
|
||
|
#ifdef PCRE_EXTRA
|
||
|
set_table_number("EXTRA", PCRE_EXTRA);
|
||
|
#endif
|
||
|
#ifdef PCRE_NOTBOL
|
||
|
set_table_number("NOTBOL", PCRE_NOTBOL);
|
||
|
#endif
|
||
|
#ifdef PCRE_NOTEOL
|
||
|
set_table_number("NOTEOL", PCRE_NOTEOL);
|
||
|
#endif
|
||
|
#ifdef PCRE_UNGREEDY
|
||
|
set_table_number("UNGREEDY", PCRE_UNGREEDY);
|
||
|
#endif
|
||
|
#ifdef PCRE_NOTEMPTY
|
||
|
set_table_number("NOTEMPTY", PCRE_NOTEMPTY);
|
||
|
#endif
|
||
|
#ifdef PCRE_UTF8
|
||
|
set_table_number("UTF8", PCRE_UTF8);
|
||
|
#endif
|
||
|
#ifdef PCRE_NO_AUTO_CAPTURE
|
||
|
set_table_number("NO_AUTO_CAPTURE", PCRE_NO_AUTO_CAPTURE);
|
||
|
#endif
|
||
|
#ifdef PCRE_NO_UTF8_CHECK
|
||
|
set_table_number("NO_UTF8_CHECK", PCRE_NO_UTF8_CHECK);
|
||
|
#endif
|
||
|
#ifdef PCRE_FIRSTLINE
|
||
|
set_table_number("FIRSTLINE", PCRE_FIRSTLINE);
|
||
|
#endif
|
||
|
#ifdef PCRE_AUTO_CALLOUT
|
||
|
set_table_number("AUTO_CALLOUT", PCRE_AUTO_CALLOUT);
|
||
|
#endif
|
||
|
#ifdef PCRE_PARTIAL
|
||
|
set_table_number("PARTIAL", PCRE_PARTIAL);
|
||
|
#endif
|
||
|
#ifdef PCRE_DFA_SHORTEST
|
||
|
set_table_number("DFA_SHORTEST", PCRE_DFA_SHORTEST);
|
||
|
#endif
|
||
|
#ifdef PCRE_DFA_RESTART
|
||
|
set_table_number("DFA_RESTART", PCRE_DFA_RESTART);
|
||
|
#endif
|
||
|
#ifdef PCRE_FIRSTLINE
|
||
|
set_table_number("FIRSTLINE", PCRE_FIRSTLINE);
|
||
|
#endif
|
||
|
#ifdef PCRE_DUPNAMES
|
||
|
set_table_number("DUPNAMES", PCRE_DUPNAMES);
|
||
|
#endif
|
||
|
#ifdef PCRE_NEWLINE_CR
|
||
|
set_table_number("NEWLINE_CR)", PCRE_NEWLINE_CR);
|
||
|
#endif
|
||
|
#ifdef PCRE_NEWLINE_LF
|
||
|
set_table_number("NEWLINE_LF", PCRE_NEWLINE_LF);
|
||
|
#endif
|
||
|
#ifdef PCRE_NEWLINE_CRLF
|
||
|
set_table_number("NEWLINE_CRLF", PCRE_NEWLINE_CRLF);
|
||
|
#endif
|
||
|
#ifdef PCRE_NEWLINE_ANY
|
||
|
set_table_number("NEWLINE_ANY", PCRE_NEWLINE_ANY);
|
||
|
#endif
|
||
|
#ifdef PCRE_NEWLINE_ANYCRLF
|
||
|
set_table_number("NEWLINE_ANYCRLF", PCRE_NEWLINE_ANYCRLF);
|
||
|
#endif
|
||
|
#ifdef PCRE_BSR_ANYCRLF
|
||
|
set_table_number("PCRE_BSR_ANYCRLF", PCRE_BSR_ANYCRLF);
|
||
|
#endif
|
||
|
#ifdef PCRE_BSR_UNICODE
|
||
|
set_table_number("PCRE_BSR_UNICODE", PCRE_BSR_UNICODE);
|
||
|
#endif
|
||
|
#ifdef PCRE_JAVASCRIPT_COMPAT
|
||
|
set_table_number("PCRE_JAVASCRIPT_COMPAT", PCRE_JAVASCRIPT_COMPAT);
|
||
|
#endif
|
||
|
#ifdef PCRE_NO_START_OPTIMIZE
|
||
|
set_table_number("PCRE_NO_START_OPTIMIZE", PCRE_NO_START_OPTIMIZE);
|
||
|
#endif
|
||
|
#ifdef PCRE_NO_START_OPTIMISE
|
||
|
set_table_number("PCRE_NO_START_OPTIMISE", PCRE_NO_START_OPTIMISE);
|
||
|
#endif
|
||
|
#ifdef PCRE_PARTIAL_HARD
|
||
|
set_table_number("PCRE_PARTIAL_HARD", PCRE_PARTIAL_HARD);
|
||
|
#endif
|
||
|
#ifdef PCRE_NOTEMPTY_ATSTART
|
||
|
set_table_number("PCRE_NOTEMPTY_ATSTART", PCRE_NOTEMPTY_ATSTART);
|
||
|
#endif
|
||
|
#ifdef PCRE_UCP
|
||
|
set_table_number("PCRE_UCP", PCRE_UCP);
|
||
|
#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Lua implementation of the PCRE compile function.
|
||
|
*/
|
||
|
static int
|
||
|
ifre_compile(lua_State *lua)
|
||
|
{
|
||
|
pcre **re;
|
||
|
const char *error;
|
||
|
int erroffset;
|
||
|
|
||
|
if (lua_gettop(lua) != 2)
|
||
|
luaL_error(lua, "wrong number of arguments");
|
||
|
|
||
|
luaL_checktype(lua, 1, LUA_TSTRING);
|
||
|
luaL_checktype(lua, 2, LUA_TNUMBER);
|
||
|
|
||
|
re = (pcre **)(lua_newuserdata(lua, sizeof(pcre *)));
|
||
|
|
||
|
*re = pcre_compile(lua_tostring(lua, 1), lua_tonumber(lua, 2), &error,
|
||
|
&erroffset, NULL);
|
||
|
|
||
|
if (*re == NULL) {
|
||
|
fprintf(stderr, "RE failed at offset %d: %s\n", erroffset,
|
||
|
error);
|
||
|
lua_pop(lua, 1);
|
||
|
}
|
||
|
|
||
|
lua_remove(lua, 1);
|
||
|
lua_remove(lua, 1);
|
||
|
|
||
|
lua_pushboolean(lua, (*re != NULL));
|
||
|
lua_insert(lua, 1);
|
||
|
|
||
|
return (*re != NULL ? 2 : 1);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Lua implementation of the PCRE exec function.
|
||
|
*/
|
||
|
static int
|
||
|
ifre_exec(lua_State *lua)
|
||
|
{
|
||
|
int i, n;
|
||
|
pcre *re;
|
||
|
int ovecsize;
|
||
|
int *ovector;
|
||
|
|
||
|
if (lua_gettop(lua) != 3)
|
||
|
luaL_error(lua, "wrong number of arguments");
|
||
|
|
||
|
luaL_checktype(lua, 1, LUA_TUSERDATA);
|
||
|
luaL_checktype(lua, 2, LUA_TSTRING);
|
||
|
luaL_checktype(lua, 3, LUA_TNUMBER);
|
||
|
|
||
|
re = *(pcre **)(lua_touserdata(lua, 1));
|
||
|
|
||
|
pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &ovecsize);
|
||
|
|
||
|
ovector = (int *)xmalloc(sizeof(int) * (ovecsize + 1) * 3);
|
||
|
|
||
|
for (i = 0; i <= ovecsize; i++)
|
||
|
ovector[2 * i] = ovector[2 * i + 1] = -1;
|
||
|
|
||
|
n = pcre_exec(re, NULL, lua_tostring(lua, 2), lua_strlen(lua, 2), 0,
|
||
|
lua_tonumber(lua, 3), ovector, (ovecsize + 1) * 3);
|
||
|
|
||
|
if (n > 0)
|
||
|
for (i = 1; i < n; i++)
|
||
|
if (ovector[2 * i] != -1 && ovector[2 * i + 1] != -1)
|
||
|
lua_pushlstring(lua, lua_tostring(lua, 2) +
|
||
|
ovector[2 * i], ovector[2 * i + 1] -
|
||
|
ovector[2 * i]);
|
||
|
else
|
||
|
lua_pushnil(lua);
|
||
|
|
||
|
xfree(ovector);
|
||
|
|
||
|
lua_remove(lua, 1);
|
||
|
lua_remove(lua, 1);
|
||
|
lua_remove(lua, 1);
|
||
|
|
||
|
lua_pushboolean(lua, (n > 0));
|
||
|
lua_insert(lua, 1);
|
||
|
|
||
|
return (n > 0 ? n : 1);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Lua implementation of a PCRE free function.
|
||
|
*/
|
||
|
static int
|
||
|
ifre_free(lua_State *lua)
|
||
|
{
|
||
|
pcre *re;
|
||
|
|
||
|
if (lua_gettop(lua) != 1)
|
||
|
luaL_error(lua, "wrong number of arguments");
|
||
|
|
||
|
luaL_checktype(lua, 1, LUA_TUSERDATA);
|
||
|
|
||
|
re = *(pcre **)(lua_touserdata(lua, 1));
|
||
|
|
||
|
xfree(re);
|
||
|
|
||
|
lua_remove(lua, 1);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Open imapfilter library of PCRE related functions.
|
||
|
*/
|
||
|
LUALIB_API int
|
||
|
luaopen_ifre(lua_State *lua)
|
||
|
{
|
||
|
|
||
|
luaL_register(lua, "ifre", ifrelib);
|
||
|
|
||
|
return 1;
|
||
|
}
|