* Based on bits of serv_funambol
* Contact: <matt@mcbridematt.dhs.org> / <matt@comalies>
*
- * Copyright (c) 2008-2009
+ * Copyright (c) 2008-2011
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
+ * This program is open source software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
#include "clientsocket.h"
#include "event_client.h"
#include "extnotify.h"
-
#include "ctdl_module.h"
struct CitContext extnotify_queue_CC;
Ctx->NotifyErrors = NewHash(1, Flathash);
nNext = GetCount(Ctx->NotifyErrors) + 1;
- Put(Ctx->NotifyErrors,
- (char*)&nNext,
- sizeof(int),
- ErrMsg,
+ Put(Ctx->NotifyErrors,
+ (char*)&nNext,
+ sizeof(int),
+ ErrMsg,
HFreeStrBuf);
}
}
-StrBuf** GetNotifyHosts(void)
+int GetNotifyHosts(NotifyContext *Ctx)
{
char NotifyHostsBuf[SIZ];
StrBuf *Host;
int notify;
const char *pchs, *pche;
const char *NextHost = NULL;
- StrBuf **NotifyHostList;
- int num_notify;
/* See if we have any Notification Hosts configured */
- num_notify = get_hosts(NotifyHostsBuf, "notify");
- if (num_notify < 1)
- return(NULL);
+ Ctx->nNotifyHosts = get_hosts(NotifyHostsBuf, "notify");
+ if (Ctx->nNotifyHosts < 1)
+ return 0;
+
+ Ctx->NotifyHostList = malloc(sizeof(StrBuf*) *
+ 2 *
+ (Ctx->nNotifyHosts + 1));
+ memset(Ctx->NotifyHostList, 0,
+ sizeof(StrBuf*) * 2 * (Ctx->nNotifyHosts + 1));
- NotifyHostList = malloc(sizeof(StrBuf*) * 2 * (num_notify + 1));
- memset(NotifyHostList, 0, sizeof(StrBuf*) * 2 * (num_notify + 1));
-
NotifyBuf = NewStrBufPlain(NotifyHostsBuf, -1);
/* get all configured notifiers's */
- for (notify=0; notify<num_notify; notify++) {
-
- Host = GetNHBuf(notify * 2, 1, NotifyHostList);
+ for (notify=0; notify<Ctx->nNotifyHosts; notify++) {
+
+ Host = GetNHBuf(notify * 2, 1, Ctx->NotifyHostList);
StrBufExtract_NextToken(Host, NotifyBuf, &NextHost, '|');
pchs = ChrPtr(Host);
pche = strchr(pchs, ':');
if (pche == NULL) {
- CtdlLogPrintf(CTDL_ERR,
- "extnotify: filename of notification template not found in %s.\n",
- pchs);
+ syslog(LOG_ERR,
+ "extnotify: filename of notification "
+ "template not found in %s.\n",
+ pchs);
continue;
}
- File = GetNHBuf(notify * 2 + 1, 1, NotifyHostList);
+ File = GetNHBuf(notify * 2 + 1, 1, Ctx->NotifyHostList);
StrBufPlain(File, pchs, pche - pchs);
StrBufCutLeft(Host, pche - pchs + 1);
}
- return NotifyHostList;
+ FreeStrBuf(&NotifyBuf);
+ return Ctx->nNotifyHosts;
}
+
/*! \brief Get configuration message for pager/funambol system from the
* users "My Citadel Config" room
*/
-eNotifyType extNotify_getConfigMessage(char *username, char **PagerNumber, char **FreeMe)
+eNotifyType extNotify_getConfigMessage(char *username,
+ char **PagerNumber,
+ char **FreeMe)
{
struct ctdlroom qrbuf; // scratch for room
struct ctdluser user; // ctdl user instance
int num_msgs = 0;
int a;
char *configMsg;
+ long clen;
char *pch;
// Get the user
CtdlGetUser(&user, username);
-
- CtdlMailboxName(configRoomName, sizeof configRoomName, &user, USERCONFIGROOM);
+
+ CtdlMailboxName(configRoomName,
+ sizeof(configRoomName),
+ &user,
+ USERCONFIGROOM);
// Fill qrbuf
CtdlGetRoom(&qrbuf, configRoomName);
/* Do something really, really stoopid here. Raid the room on ourselves,
cdbfr = cdb_fetch(CDB_MSGLISTS, &qrbuf.QRnumber, sizeof(long));
if (cdbfr != NULL) {
msglist = (long *) cdbfr->ptr;
- cdbfr->ptr = NULL; /* CtdlForEachMessage() now owns this memory */
+ cdbfr->ptr = NULL;
+ /* CtdlForEachMessage() now owns this memory */
num_msgs = cdbfr->len / sizeof(long);
cdb_free(cdbfr);
} else {
- CtdlLogPrintf(CTDL_DEBUG, "extNotify_getConfigMessage: No config messages found\n");
+ syslog(LOG_DEBUG,
+ "extNotify_getConfigMessage: "
+ "No config messages found\n");
return eNone; /* No messages at all? No further action. */
}
for (a = 0; a < num_msgs; ++a) {
msg = CtdlFetchMessage(msglist[a], 1);
if (msg != NULL) {
- if ((msg->cm_fields['U'] != NULL) &&
- (strncasecmp(msg->cm_fields['U'], PAGER_CONFIG_MESSAGE,
- strlen(PAGER_CONFIG_MESSAGE)) == 0)) {
+ if (!CM_IsEmpty(msg, eMsgSubject) &&
+ (strncasecmp(msg->cm_fields[eMsgSubject],
+ PAGER_CONFIG_MESSAGE,
+ strlen(PAGER_CONFIG_MESSAGE)) == 0))
+ {
break;
}
- CtdlFreeMessage(msg);
+ CM_Free(msg);
msg = NULL;
}
}
-
+
+ free(msglist);
if (msg == NULL)
return eNone;
// Do a simple string search to see if 'funambol' is selected as the
// type. This string would be at the very top of the message contents.
- configMsg = msg->cm_fields['M'];
- msg->cm_fields['M'] = NULL;
- CtdlFreeMessage(msg);
+ CM_GetAsField(msg, eMesageText, &configMsg, &clen);
+ CM_Free(msg);
/* here we would find the pager number... */
pch = strchr(configMsg, '\n');
if (!pch || (*pch == '\0'))
{
free(configMsg);
-
+
return eNone;
}
- while (isspace(*pch))
+ while (isspace(*pch))
pch ++;
*PagerNumber = pch;
while (isdigit(*pch) || (*pch == '+'))
/*
* Process messages in the external notification queue
*/
-void process_notify(long NotifyMsgnum, void *usrdata)
+void process_notify(long NotifyMsgnum, void *usrdata)
{
NotifyContext *Ctx;
long msgnum = 0;
char remoteurl[SIZ];
char *FreeMe = NULL;
char *PagerNo;
- CitContext *SubC;
Ctx = (NotifyContext*) usrdata;
msg = CtdlFetchMessage(NotifyMsgnum, 1);
- if ( msg->cm_fields['W'] != NULL)
+ if (!CM_IsEmpty(msg, eExtnotify))
{
- Type = extNotify_getConfigMessage(msg->cm_fields['W'], &PagerNo, &FreeMe);
-
- pch = strstr(msg->cm_fields['M'], "msgid|");
- if (pch != NULL)
+ Type = extNotify_getConfigMessage(
+ msg->cm_fields[eExtnotify],
+ &PagerNo,
+ &FreeMe);
+
+ pch = strstr(msg->cm_fields[eMesageText], "msgid|");
+ if (pch != NULL)
msgnum = atol(pch + sizeof("msgid"));
switch (Type)
config.c_funambol_port,
FUNAMBOL_WS);
- SubC = CloneContext (CC);
- SubC->session_specific_data = NULL;// (char*) DupNotifyContext(Ctx);
-
- notify_http_server(remoteurl,
+ notify_http_server(remoteurl,
file_funambol_msg,
strlen(file_funambol_msg),/*GNA*/
- msg->cm_fields['W'],
- msg->cm_fields['I'],
- msgnum,
+ msg->cm_fields[eExtnotify],
+ msg->cm_fields[emessageId],
+ msgnum,
NULL);
break;
case eHttpMessages:
char URLBuf[SIZ];
StrBuf *File;
StrBuf *FileBuf = NewStrBuf();
-
- while(1)
+
+ for (i = 0; i < Ctx->nNotifyHosts; i++)
{
URL = GetNHBuf(i*2, 0, Ctx->NotifyHostList);
if (URL==NULL) break;
- File = GetNHBuf(i*2 + 1, 0, Ctx->NotifyHostList);
+ File = GetNHBuf(i*2 + 1, 0,
+ Ctx->NotifyHostList);
if (File==NULL) break;
if (StrLength(File)>0)
- StrBufPrintf(FileBuf, "%s/%s",
- ctdl_shared_dir,
+ StrBufPrintf(FileBuf, "%s/%s",
+ ctdl_shared_dir,
ChrPtr(File));
else
FlushStrBuf(FileBuf);
memcpy(URLBuf, ChrPtr(URL), StrLength(URL) + 1);
- SubC = CloneContext (CC);
- SubC->session_specific_data = NULL;// (char*) DupNotifyContext(Ctx);
- notify_http_server(URLBuf,
+ notify_http_server(URLBuf,
ChrPtr(FileBuf),
StrLength(FileBuf),
- msg->cm_fields['W'],
- msg->cm_fields['I'],
- msgnum,
+ msg->cm_fields[eExtnotify],
+ msg->cm_fields[emessageId],
+ msgnum,
NULL);
- i++;
}
FreeStrBuf(&FileBuf);
- }
+ }
break;
case eTextMessage:
{
int commandSiz;
char *command;
- commandSiz = sizeof(config.c_pager_program) + strlen(PagerNo) + strlen(msg->cm_fields['W']) + 5;
+ commandSiz = sizeof(config.c_pager_program) +
+ strlen(PagerNo) +
+ msg->cm_lengths[eExtnotify] + 5;
+
command = malloc(commandSiz);
- snprintf(command, commandSiz, "%s %s -u %s", config.c_pager_program, PagerNo, msg->cm_fields['W']);
+
+ snprintf(command,
+ commandSiz,
+ "%s %s -u %s",
+ config.c_pager_program,
+ PagerNo,
+ msg->cm_fields[eExtnotify]);
+
system(command);
free(command);
}
}
if (FreeMe != NULL)
free(FreeMe);
- CtdlFreeMessage(msg);
+ CM_Free(msg);
todelete[0] = NotifyMsgnum;
CtdlDeleteMessages(FNBL_QUEUE_ROOM, todelete, 1, "");
}
-
-
-
-
-
/*!
* \brief Run through the pager room queue
+ * Checks to see what notification option the user has set
*/
-void do_extnotify_queue(void)
+void do_extnotify_queue(void)
{
- CitContext *CCC = CC;
-
NotifyContext Ctx;
static int doing_queue = 0;
- //int i = 0;
-
+ int i = 0;
+
/*
* This is a simple concurrency check to make sure only one queue run
* is done at a time. We could do this with a mutex, but since we
* don't really require extremely fine granularity here, we'll do it
* with a static variable instead.
*/
-
- if (IsEmptyStr(config.c_pager_program) &&
+ if (IsEmptyStr(config.c_pager_program) &&
IsEmptyStr(config.c_funambol_host))
{
- CtdlLogPrintf(CTDL_DEBUG, "No external notifiers configured on system/user");
+ syslog(LOG_ERR,
+ "No external notifiers configured on system/user\n");
return;
}
- if (doing_queue) return;
+ if (doing_queue)
+ return;
+
doing_queue = 1;
- citthread_setspecific(MyConKey, (void *)&extnotify_queue_CC);
+ become_session(&extnotify_queue_CC);
+
+ pthread_setspecific(MyConKey, (void *)&extnotify_queue_CC);
/*
* Go ahead and run the queue
*/
- CtdlLogPrintf(CTDL_DEBUG, "serv_extnotify: processing notify queue\n");
+ syslog(LOG_DEBUG, "serv_extnotify: processing notify queue\n");
memset(&Ctx, 0, sizeof(NotifyContext));
- Ctx.NotifyHostList = GetNotifyHosts();
- if (CtdlGetRoom(&CC->room, FNBL_QUEUE_ROOM) != 0) {
- CtdlLogPrintf(CTDL_ERR, "Cannot find room <%s>\n", FNBL_QUEUE_ROOM);
- CtdlClearSystemContext();
+ if ((GetNotifyHosts(&Ctx) > 0) &&
+ (CtdlGetRoom(&CC->room, FNBL_QUEUE_ROOM) != 0))
+ {
+ syslog(LOG_ERR, "Cannot find room <%s>\n", FNBL_QUEUE_ROOM);
+ if (Ctx.nNotifyHosts > 0)
+ {
+ for (i = 0; i < Ctx.nNotifyHosts * 2; i++)
+ FreeStrBuf(&Ctx.NotifyHostList[i]);
+ free(Ctx.NotifyHostList);
+ }
return;
}
CtdlForEachMessage(MSGS_ALL, 0L, NULL,
SPOOLMIME, NULL, process_notify, &Ctx);
- CtdlLogPrintf(CTDL_DEBUG, "serv_extnotify: queue run completed\n");
+ syslog(LOG_DEBUG, "serv_extnotify: queue run completed\n");
doing_queue = 0;
+ if (Ctx.nNotifyHosts > 0)
+ {
+ for (i = 0; i < Ctx.nNotifyHosts * 2; i++)
+ FreeStrBuf(&Ctx.NotifyHostList[i]);
+ free(Ctx.NotifyHostList);
+ }
}
*/
void create_extnotify_queue(void) {
struct ctdlroom qrbuf;
-
- CtdlCreateRoom(FNBL_QUEUE_ROOM, 3, "", 0, 1, 0, VIEW_MAILBOX);
- CtdlFillSystemContext(&extnotify_queue_CC, "Extnotify");
-
+ CtdlCreateRoom(FNBL_QUEUE_ROOM, 3, "", 0, 1, 0, VIEW_QUEUE);
+
+ CtdlFillSystemContext(&extnotify_queue_CC, "Extnotify");
+
/*
* Make sure it's set to be a "system room" so it doesn't show up
* in the <K>nown rooms list for Aides.
}
}
+int extnotify_after_mbox_save(struct CtdlMessage *msg,
+ recptypes *recps)
+
+{
+ /* If this is private, local mail, make a copy in the
+ * recipient's mailbox and bump the reference count.
+ */
+ if (!IsEmptyStr(config.c_funambol_host) || !IsEmptyStr(config.c_pager_program))
+ {
+ /* Generate a instruction message for the Funambol notification
+ * server, in the same style as the SMTP queue
+ */
+ StrBuf *instr;
+ struct CtdlMessage *imsg;
+
+ instr = NewStrBufPlain(NULL, 1024);
+ StrBufPrintf(instr,
+ "Content-type: "SPOOLMIME"\n"
+ "\n"
+ "msgid|%s\n"
+ "submitted|%ld\n"
+ "bounceto|%s\n",
+ msg->cm_fields[eVltMsgNum],
+ (long)time(NULL), //todo: time() is expensive!
+ recps->bounce_to
+ );
+
+ imsg = malloc(sizeof(struct CtdlMessage));
+ memset(imsg, 0, sizeof(struct CtdlMessage));
+ imsg->cm_magic = CTDLMESSAGE_MAGIC;
+ imsg->cm_anon_type = MES_NORMAL;
+ imsg->cm_format_type = FMT_RFC822;
+ CM_SetField(imsg, eMsgSubject, HKEY("QMSG"));
+ CM_SetField(imsg, eAuthor, HKEY("Citadel"));
+ CM_SetField(imsg, eJournal, HKEY("do not journal"));
+ CM_SetAsFieldSB(imsg, eMesageText, &instr);
+ CM_SetField(imsg, eExtnotify, recps->recp_local, strlen(recps->recp_local));
+ CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM, 0);
+ CM_Free(imsg);
+ }
+ return 0;
+}
+
CTDL_MODULE_INIT(extnotify)
{
if (!threading)
{
create_extnotify_queue();
- CtdlRegisterSessionHook(do_extnotify_queue, EVT_TIMER);
+ CtdlRegisterMessageHook(extnotify_after_mbox_save, EVT_AFTERUSRMBOXSAVE);
+
+ CtdlRegisterSessionHook(do_extnotify_queue, EVT_TIMER, PRIO_SEND + 10);
}
- /* return our Subversion id for the Log */
- return "extnotify";
+ /* return our module name for the log */
+ return "extnotify";
}