1 /* Copyright (c) 2018 Dovecot authors, see the included COPYING file */
2
3 #include "lib.h"
4 #include "str.h"
5 #include "istream.h"
6 #include "array.h"
7 #include "var-expand.h"
8 #include "dlua-script.h"
9 #include "dlua-script-private.h"
10 #include "mail-storage.h"
11 #include "mailbox-attribute.h"
12 #include "mail-storage-lua.h"
13 #include "mail-storage-lua-private.h"
14 #include "mail-user.h"
15
16 #define LUA_STORAGE_MAIL "struct mail"
17
dlua_push_mail(lua_State * L,struct mail * mail)18 void dlua_push_mail(lua_State *L, struct mail *mail)
19 {
20 luaL_checkstack(L, 20, "out of memory");
21 /* create a table for holding few things */
22 lua_createtable(L, 0, 20);
23 luaL_setmetatable(L, LUA_STORAGE_MAIL);
24
25 lua_pushlightuserdata(L, mail);
26 lua_setfield(L, -2, "item");
27
28 #undef LUA_TABLE_SET_NUMBER
29 #define LUA_TABLE_SET_NUMBER(field) \
30 lua_pushnumber(L, mail->field); \
31 lua_setfield(L, -2, #field);
32 #undef LUA_TABLE_SET_BOOL
33 #define LUA_TABLE_SET_BOOL(field) \
34 lua_pushboolean(L, mail->field); \
35 lua_setfield(L, -2, #field);
36
37 LUA_TABLE_SET_NUMBER(seq);
38 LUA_TABLE_SET_NUMBER(uid);
39 LUA_TABLE_SET_BOOL(expunged);
40
41 dlua_push_mailbox(L, mail->box);
42 lua_setfield(L, -2, "mailbox");
43
44 }
45
46 static struct mail *
lua_check_storage_mail(lua_State * L,int arg)47 lua_check_storage_mail(lua_State *L, int arg)
48 {
49 if (!lua_istable(L, arg)) {
50 (void)luaL_error(L, "Bad argument #%d, expected %s got %s",
51 arg, LUA_STORAGE_MAIL,
52 lua_typename(L, lua_type(L, arg)));
53 }
54 lua_pushliteral(L, "item");
55 lua_rawget(L, arg);
56 void *bp = (void*)lua_touserdata(L, -1);
57 lua_pop(L, 1);
58 return (struct mail*)bp;
59 }
60
lua_storage_mail_tostring(lua_State * L)61 static int lua_storage_mail_tostring(lua_State *L)
62 {
63 DLUA_REQUIRE_ARGS(L, 1);
64 struct mail *mail = lua_check_storage_mail(L, 1);
65
66 const char *str =
67 t_strdup_printf("<%s:UID %u>", mailbox_get_vname(mail->box),
68 mail->uid);
69 lua_pushstring(L, str);
70 return 1;
71 }
72
lua_storage_mail_eq(lua_State * L)73 static int lua_storage_mail_eq(lua_State *L)
74 {
75 DLUA_REQUIRE_ARGS(L, 2);
76 struct mail *mail = lua_check_storage_mail(L, 1);
77 struct mail *mail2 = lua_check_storage_mail(L, 2);
78
79 if (!DLUA_MAILBOX_EQUALS(mail->box, mail2->box))
80 lua_pushboolean(L, FALSE);
81 else
82 lua_pushboolean(L, mail->uid != mail2->uid);
83 return 1;
84 }
85
lua_storage_mail_lt(lua_State * L)86 static int lua_storage_mail_lt(lua_State *L)
87 {
88 DLUA_REQUIRE_ARGS(L, 2);
89 struct mail *mail = lua_check_storage_mail(L, 1);
90 struct mail *mail2 = lua_check_storage_mail(L, 2);
91
92 if (!DLUA_MAILBOX_EQUALS(mail->box, mail2->box))
93 return luaL_error(L,
94 "For lt, Mail can only be compared within same mailbox");
95 else
96 lua_pushboolean(L, mail->uid < mail2->uid);
97 return 1;
98 }
99
lua_storage_mail_le(lua_State * L)100 static int lua_storage_mail_le(lua_State *L)
101 {
102 DLUA_REQUIRE_ARGS(L, 2);
103 struct mail *mail = lua_check_storage_mail(L, 1);
104 struct mail *mail2 = lua_check_storage_mail(L, 2);
105
106 if (!DLUA_MAILBOX_EQUALS(mail->box, mail2->box))
107 return luaL_error(L,
108 "For le, mails can only be within same mailbox");
109 else
110 lua_pushboolean(L, mail->uid <= mail2->uid);
111
112 return 1;
113 }
114
lua_storage_mail_gc(lua_State * L)115 static int lua_storage_mail_gc(lua_State *L)
116 {
117 (void)lua_check_storage_mail(L, 1);
118
119 /* reset value to NULL */
120 lua_pushliteral(L, "item");
121 lua_pushnil(L);
122 lua_rawset(L, 1);
123
124 return 0;
125 }
126
127 static luaL_Reg lua_storage_mail_methods[] = {
128 { "__tostring", lua_storage_mail_tostring },
129 { "__eq", lua_storage_mail_eq },
130 { "__lt", lua_storage_mail_lt },
131 { "__le", lua_storage_mail_le },
132 { "__gc", lua_storage_mail_gc },
133 { NULL, NULL }
134 };
135
lua_storage_mail_register(struct dlua_script * script)136 void lua_storage_mail_register(struct dlua_script *script)
137 {
138 luaL_newmetatable(script->L, LUA_STORAGE_MAIL);
139 lua_pushvalue(script->L, -1);
140 lua_setfield(script->L, -2, "__index");
141 luaL_setfuncs(script->L, lua_storage_mail_methods, 0);
142 lua_pop(script->L, 1);
143 }
144