Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 38 additions & 5 deletions src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ static int ifcore_rename(lua_State *lua);
static int ifcore_subscribe(lua_State *lua);
static int ifcore_unsubscribe(lua_State *lua);
static int ifcore_idle(lua_State *lua);
static int ifcore_notify(lua_State *lua);


/* Lua imapfilter core library functions. */
Expand Down Expand Up @@ -77,6 +78,7 @@ static const luaL_Reg ifcorelib[] = {
{ "store", ifcore_store },
{ "copy", ifcore_copy },
{ "idle", ifcore_idle },
{ "notify", ifcore_notify },
{ NULL, NULL }
};

Expand Down Expand Up @@ -992,11 +994,42 @@ ifcore_idle(lua_State *lua)
luaL_error(lua, "wrong number of arguments");
luaL_checktype(lua, 1, LUA_TLIGHTUSERDATA);

if (get_option_boolean("reenter"))
r = request_idle((session *)(lua_topointer(lua, 1)),
&event);
else
r = request_idle((session *)(lua_topointer(lua, 1)), &event);
r = request_idle((session *)(lua_topointer(lua, 1)), &event);

lua_pop(lua, 1);

if (r < 0)
return 0;

lua_pushboolean(lua, (r == STATUS_OK));

if (!event)
return 1;

lua_pushstring(lua, event);

xfree(event);

return 2;
}


/*
* Core function to go to idle state.
*/
static int
ifcore_notify(lua_State *lua)
{
int r;
char *event;

event = NULL;

if (lua_gettop(lua) != 1)
luaL_error(lua, "wrong number of arguments");
luaL_checktype(lua, 1, LUA_TLIGHTUSERDATA);

r = request_notify((session *)(lua_topointer(lua, 1)), &event);

lua_pop(lua, 1);

Expand Down
3 changes: 3 additions & 0 deletions src/imapfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#define CAPABILITY_XOAUTH2 0x10
#define CAPABILITY_ENABLE 0x20
#define CAPABILITY_UTF8 0x40
#define CAPABILITY_NOTIFY 0x80

/* Status responses and response codes. */
#define STATUS_BYE -2
Expand Down Expand Up @@ -184,6 +185,7 @@ int request_rename(session *ssn, const char *oldmbox, const char *newmbox);
int request_subscribe(session *ssn, const char *mbox);
int request_unsubscribe(session *ssn, const char *mbox);
int request_idle(session *ssn, char **event);
int request_notify(session *ssn, char **event);

/* response.c */
int response_generic(session *ssn, int tag);
Expand All @@ -207,6 +209,7 @@ int response_fetchsize(session *ssn, int tag, char **size);
int response_fetchstructure(session *ssn, int tag, char **structure);
int response_fetchbody(session *ssn, int tag, char **body, size_t *len);
int response_idle(session *ssn, int tag, char **event);
int response_notify(session *ssn, char **event);

/* signal.c */
void catch_signals(void);
Expand Down
18 changes: 18 additions & 0 deletions src/mailbox.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,24 @@ function Mailbox.enter_idle(self)
end


function Mailbox.await_notification(self)
if self._cached_select(self) ~= true then return false end

self._check_connection(self)
local r, event = ifcore.notify(self._account._account.session)
self._check_result(self, 'notify', r)
if r == false then return false end

if options.close == true then self._cached_close(self) end

if type(event) == 'string' then
return true, string.upper(event)
else
return true
end
end


Mailbox.open = _cached_select
Mailbox.close = _cached_close

Expand Down
34 changes: 34 additions & 0 deletions src/request.c
Original file line number Diff line number Diff line change
Expand Up @@ -776,3 +776,37 @@ request_idle(session *ssn, char **event)

return r;
}


int
request_notify(session *ssn, char **event)
{
int t, r, ri;

debug("request_notify: capa:%x, status:%d\n\n",
ssn->capabilities & CAPABILITY_NOTIFY,
ssn->notify_active
);

if (!(ssn->capabilities & CAPABILITY_NOTIFY))
return STATUS_BAD;

if (!ssn->notify_active) {
TRY(t = send_request(ssn, "NOTIFY SET (Subscribed (MessageNew MessageExpunge))"));
TRY(r = response_generic(ssn, t));
if (r != STATUS_OK) {
return r;
}
ssn->notify_active = 1;
}

do {
ri = 0;

TRY(ri = response_notify(ssn, event));
if (ri == STATUS_TIMEOUT)
request_noop(ssn);
} while (ri == STATUS_TIMEOUT);

return r;
}
52 changes: 52 additions & 0 deletions src/response.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ response_capability(session *ssn, int tag)
ssn->capabilities |= CAPABILITY_ENABLE;
if (xstrcasestr(s, "UTF8=ACCEPT"))
ssn->capabilities |= CAPABILITY_UTF8;
if (xstrcasestr(s, "NOTIFY"))
ssn->capabilities |= CAPABILITY_NOTIFY;

xfree(s);
}
Expand Down Expand Up @@ -892,3 +894,53 @@ response_idle(session *ssn, int tag, char **event)

return STATUS_UNTAGGED;
}


/*
* Process the data that server sent due to IMAP NOTIFY client request.
*/
int
response_notify(session *ssn, char **event)
{
regexp *re;
ssize_t n;
int eintr = 0;

re = &responses[RESPONSE_UNTAGGED];

for (;;) {
buffer_reset(&ibuf);

do {
buffer_check(&ibuf, ibuf.len + INPUT_BUF);
n = receive_response(ssn, ibuf.data + ibuf.len,
get_option_number("keepalive") * 60, 0, &eintr);
if (n < 0) {
if (eintr)
return STATUS_INTERRUPT;
else
return STATUS_ERROR;
}
if (n == 0)
return STATUS_TIMEOUT;
ibuf.len += n;

if (check_bye(ibuf.data))
return handle_bye(ssn);

} while (regexec(re->preg, ibuf.data, re->nmatch, re->pmatch, 0));

verbose("S (%d): %s", ssn->socket, ibuf.data);

if (get_option_boolean("wakeonany"))
break;
if (!strncasecmp(ibuf.data + re->pmatch[1].rm_so,
"STATUS", strlen("STATUS")))
break;
}

*event = xstrndup(ibuf.data + re->pmatch[1].rm_so,
re->pmatch[1].rm_eo - re->pmatch[1].rm_so);

return STATUS_UNTAGGED;
}
1 change: 1 addition & 0 deletions src/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ session_init(session *ssn)
ssn->ns.prefix = NULL;
ssn->ns.delim = '\0';
ssn->utf8 = 0;
ssn->notify_active = 0;
}


Expand Down
1 change: 1 addition & 0 deletions src/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ typedef struct session {
char delim; /* Namespace delimiter. */
} ns;
int utf8; /* UTF8 enabled. */
int notify_active; /* NOTIFY is active */
} session;


Expand Down