imapfilter/pcre.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;
}