X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fextnotify%2Fextnotify_main.c;h=3029322950dc79f66fdd7a2909d8911cf31c8c44;hb=c855d497545dad80942a194624c111a54cd1fdc7;hp=3e80ef4d775e628f5c977928d8b4652c79ceaf7e;hpb=3d0059e4b0486a07f88e59d9d7c42b1471650cfa;p=citadel.git diff --git a/citadel/modules/extnotify/extnotify_main.c b/citadel/modules/extnotify/extnotify_main.c index 3e80ef4d7..302932295 100644 --- a/citadel/modules/extnotify/extnotify_main.c +++ b/citadel/modules/extnotify/extnotify_main.c @@ -8,23 +8,24 @@ * Based on bits of serv_funambol * Contact: / * - * 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 #include @@ -63,11 +64,11 @@ #include "internet_addressing.h" #include "domain.h" #include "clientsocket.h" +#include "event_client.h" #include "extnotify.h" - #include "ctdl_module.h" - +struct CitContext extnotify_queue_CC; void ExtNotify_PutErrorMessage(NotifyContext *Ctx, StrBuf *ErrMsg) { @@ -83,9 +84,6 @@ void ExtNotify_PutErrorMessage(NotifyContext *Ctx, StrBuf *ErrMsg) HFreeStrBuf); } - - - StrBuf* GetNHBuf(int i, int allocit, StrBuf **NotifyHostList) { if ((NotifyHostList[i] == NULL) && (allocit != 0)) @@ -94,7 +92,7 @@ StrBuf* GetNHBuf(int i, int allocit, StrBuf **NotifyHostList) } -StrBuf** GetNotifyHosts(void) +int GetNotifyHosts(NotifyContext *Ctx) { char NotifyHostsBuf[SIZ]; StrBuf *Host; @@ -103,120 +101,153 @@ StrBuf** GetNotifyHosts(void) 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; - NotifyHostList = malloc(sizeof(StrBuf*) * 2 * (num_notify + 1)); - memset(NotifyHostList, 0, sizeof(StrBuf*) * 2 * (num_notify + 1)); + Ctx->NotifyHostList = malloc(sizeof(StrBuf*) * 2 * (Ctx->nNotifyHosts + 1)); + memset(Ctx->NotifyHostList, 0, sizeof(StrBuf*) * 2 * (Ctx->nNotifyHosts + 1)); NotifyBuf = NewStrBufPlain(NotifyHostsBuf, -1); /* get all configured notifiers's */ - for (notify=0; notifynNotifyHosts; notify++) { - Host = GetNHBuf(notify * 2, 1, NotifyHostList); + Host = GetNHBuf(notify * 2, 1, Ctx->NotifyHostList); StrBufExtract_NextToken(Host, NotifyBuf, &NextHost, '|'); pchs = ChrPtr(Host); pche = strchr(pchs, ':'); if (pche == NULL) { - CtdlLogPrintf(CTDL_ERR, - __FILE__": filename 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; } -/* Create the notify message queue. We use the exact same room - * as the Funambol module. - * - * Run at server startup, creates FNBL_QUEUE_ROOM if it doesn't exist - * and sets as system room. - */ -void create_extnotify_queue(void) { - struct ctdlroom qrbuf; - - CtdlCreateRoom(FNBL_QUEUE_ROOM, 3, "", 0, 1, 0, VIEW_MAILBOX); - - /* - * Make sure it's set to be a "system room" so it doesn't show up - * in the nown rooms list for Aides. - */ - if (CtdlGetRoomLock(&qrbuf, FNBL_QUEUE_ROOM) == 0) { - qrbuf.QRflags2 |= QR2_SYSTEM; - CtdlPutRoomLock(&qrbuf); - } -} -/*! - * \brief Run through the pager room queue + +/*! \brief Get configuration message for pager/funambol system from the + * users "My Citadel Config" room */ -void do_extnotify_queue(void) +eNotifyType extNotify_getConfigMessage(char *username, char **PagerNumber, char **FreeMe) { + struct ctdlroom qrbuf; // scratch for room + struct ctdluser user; // ctdl user instance + char configRoomName[ROOMNAMELEN]; + struct CtdlMessage *msg = NULL; + struct cdbdata *cdbfr; + long *msglist = NULL; + int num_msgs = 0; + int a; + char *configMsg; + char *pch; - NotifyContext Ctx; - static int doing_queue = 0; - int i = 0; + // Get the user + CtdlGetUser(&user, username); - /* - * 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 (doing_queue) return; - doing_queue = 1; + CtdlMailboxName(configRoomName, sizeof configRoomName, &user, USERCONFIGROOM); + // Fill qrbuf + CtdlGetRoom(&qrbuf, configRoomName); + /* Do something really, really stoopid here. Raid the room on ourselves, + * loop through the messages manually and find it. I don't want + * to use a CtdlForEachMessage callback here, as we would be + * already in one */ + cdbfr = cdb_fetch(CDB_MSGLISTS, &qrbuf.QRnumber, sizeof(long)); + if (cdbfr != NULL) { + msglist = (long *) cdbfr->ptr; + cdbfr->ptr = NULL; /* CtdlForEachMessage() now owns this memory */ + num_msgs = cdbfr->len / sizeof(long); + cdb_free(cdbfr); + } else { + 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)) { + break; + } + CtdlFreeMessage(msg); + msg = NULL; + } + } + + free(msglist); + if (msg == NULL) + return eNone; - /* - * Go ahead and run the queue - */ - CtdlLogPrintf(CTDL_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(); - return; + // 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); + + /* here we would find the pager number... */ + pch = strchr(configMsg, '\n'); + if (pch != NULL) + { + *pch = '\0'; + pch ++; } - CtdlForEachMessage(MSGS_ALL, 0L, NULL, - SPOOLMIME, NULL, process_notify, &Ctx); - while ((Ctx.NotifyHostList != NULL) && (Ctx.NotifyHostList[i] != NULL)) - FreeStrBuf(&Ctx.NotifyHostList[i]); + /* Check to see if: + * 1. The user has configured paging / They have and disabled it + * AND 2. There is an external pager program + * 3. A Funambol server has been entered + * + */ + if (!strncasecmp(configMsg, "none", 4)) + { + free(configMsg); + return eNone; + } - if (Ctx.NotifyErrors != NULL) + if (!strncasecmp(configMsg, HKEY(PAGER_CONFIG_HTTP))) + { + free(configMsg); + return eHttpMessages; + } + if (!strncasecmp(configMsg, HKEY(FUNAMBOL_CONFIG_TEXT))) + { + free(configMsg); + return eFunambol; + } + else if (!strncasecmp(configMsg, HKEY(PAGER_CONFIG_SYSTEM))) { - long len; - const char *Key; - HashPos *It; - void *vErr; - StrBuf *ErrMsg; - - It = GetNewHashPos(Ctx.NotifyErrors, 0); - while (GetNextHashPos(Ctx.NotifyErrors, It, &len, &Key, &vErr) && - (vErr != NULL)) { - ErrMsg = (StrBuf*) vErr; - quickie_message("Citadel", NULL, NULL, AIDEROOM, ChrPtr(ErrMsg), FMT_FIXED, - "Failed to notify external service about inbound mail"); + // whats the pager number? + if (!pch || (*pch == '\0')) + { + free(configMsg); + + return eNone; } - - DeleteHashPos(&It); - DeleteHash(&Ctx.NotifyErrors); + while (isspace(*pch)) + pch ++; + *PagerNumber = pch; + while (isdigit(*pch) || (*pch == '+')) + pch++; + *pch = '\0'; + *FreeMe = configMsg; + return eTextMessage; } - CtdlLogPrintf(CTDL_DEBUG, "serv_extnotify: queue run completed\n"); - doing_queue = 0; + free(configMsg); + return eNone; } + /* * Process messages in the external notification queue */ @@ -225,182 +256,186 @@ void process_notify(long NotifyMsgnum, void *usrdata) NotifyContext *Ctx; long msgnum = 0; long todelete[1]; - int fnblAllowed; - int extPagerAllowedHttp; - int extPagerAllowedSystem; char *pch; - long configMsgNum; - char configMsg[SIZ]; struct CtdlMessage *msg; + eNotifyType Type; + char remoteurl[SIZ]; + char *FreeMe = NULL; + char *PagerNo; + CitContext *SubC; Ctx = (NotifyContext*) usrdata; msg = CtdlFetchMessage(NotifyMsgnum, 1); - if ( msg->cm_fields['W'] == NULL) { - goto nuke; - } - - configMsgNum = extNotify_getConfigMessage(msg->cm_fields['W']); - - extNotify_getPrefs(configMsgNum, &configMsg[0]); + if ( msg->cm_fields['2'] != NULL) + { + Type = extNotify_getConfigMessage(msg->cm_fields['2'], &PagerNo, &FreeMe); - /* Check to see if: - * 1. The user has configured paging / They have and disabled it - * AND 2. There is an external pager program - * 3. A Funambol server has been entered - * - */ - if ((configMsgNum == -1) || - ((strncasecmp(configMsg, "none", 4) == 0) && - IsEmptyStr(config.c_pager_program) && - IsEmptyStr(config.c_funambol_host))) { - CtdlLogPrintf(CTDL_DEBUG, "No external notifiers configured on system/user"); - goto nuke; - } + pch = strstr(msg->cm_fields['M'], "msgid|"); + if (pch != NULL) + msgnum = atol(pch + sizeof("msgid")); - // Can Funambol take the message? - pch = strchr(configMsg, '\n'); - if (*pch == '\n') - *pch = '\0'; - fnblAllowed = strncasecmp(configMsg, HKEY(FUNAMBOL_CONFIG_TEXT)); - extPagerAllowedHttp = strncasecmp(configMsg, HKEY(PAGER_CONFIG_HTTP)); - extPagerAllowedSystem = strncasecmp(configMsg, HKEY(PAGER_CONFIG_SYSTEM)); - pch = strstr(msg->cm_fields['M'], "msgid|"); - if (pch != NULL) - msgnum = atol(pch + sizeof("msgid")); - if (fnblAllowed == 0) { - char remoteurl[SIZ]; - snprintf(remoteurl, SIZ, "http://%s@%s:%d/%s", - config.c_funambol_auth, - config.c_funambol_host, - config.c_funambol_port, - FUNAMBOL_WS); - notify_http_server(remoteurl, - file_funambol_msg, - strlen(file_funambol_msg),/*GNA*/ - msg->cm_fields['W'], - msg->cm_fields['I'], - msgnum, - Ctx); - } else if (extPagerAllowedHttp == 0) { - int i = 0; - StrBuf *URL; - char URLBuf[SIZ]; - StrBuf *File; - StrBuf *FileBuf = NewStrBuf(); - - while(1) + switch (Type) { - - URL = GetNHBuf(i*2, 0, Ctx->NotifyHostList); - if (URL==NULL) break; - File = GetNHBuf(i*2 + 1, 0, Ctx->NotifyHostList); - if (File==NULL) break; - - if (StrLength(File)>0) - StrBufPrintf(FileBuf, "%s/%s", - ctdl_shared_dir, - ChrPtr(File)); - else - FlushStrBuf(FileBuf); - memcpy(URLBuf, ChrPtr(URL), StrLength(URL) + 1); - - notify_http_server(URLBuf, - ChrPtr(FileBuf), - StrLength(FileBuf), - msg->cm_fields['W'], + case eFunambol: + snprintf(remoteurl, SIZ, "http://%s@%s:%d/%s", + config.c_funambol_auth, + config.c_funambol_host, + config.c_funambol_port, + FUNAMBOL_WS); + + notify_http_server(remoteurl, + file_funambol_msg, + strlen(file_funambol_msg),/*GNA*/ + msg->cm_fields['2'], msg->cm_fields['I'], msgnum, - Ctx); - i++; + NULL); + break; + case eHttpMessages: + { + int i = 0; + StrBuf *URL; + char URLBuf[SIZ]; + StrBuf *File; + StrBuf *FileBuf = NewStrBuf(); + + 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); + if (File==NULL) break; + + if (StrLength(File)>0) + StrBufPrintf(FileBuf, "%s/%s", + ctdl_shared_dir, + ChrPtr(File)); + else + FlushStrBuf(FileBuf); + memcpy(URLBuf, ChrPtr(URL), StrLength(URL) + 1); + + notify_http_server(URLBuf, + ChrPtr(FileBuf), + StrLength(FileBuf), + msg->cm_fields['2'], + msg->cm_fields['I'], + msgnum, + NULL); + } + FreeStrBuf(&FileBuf); + } + break; + case eTextMessage: + { + int commandSiz; + char *command; + + commandSiz = sizeof(config.c_pager_program) + strlen(PagerNo) + strlen(msg->cm_fields['2']) + 5; + command = malloc(commandSiz); + snprintf(command, commandSiz, "%s %s -u %s", config.c_pager_program, PagerNo, msg->cm_fields['2']); + system(command); + free(command); + } + break; + case eNone: + break; } - FreeStrBuf(&FileBuf); - } - else if (extPagerAllowedSystem == 0) { - char *number; - int commandSiz; - char *command; - - number = strtok(configMsg, "textmessage\n"); - commandSiz = sizeof(config.c_pager_program) + strlen(number) + strlen(msg->cm_fields['W']) + 5; - command = malloc(commandSiz); - snprintf(command, commandSiz, "%s %s -u %s", config.c_pager_program, number, msg->cm_fields['W']); - system(command); - free(command); } -nuke: + if (FreeMe != NULL) + free(FreeMe); CtdlFreeMessage(msg); - memset(configMsg, 0, sizeof(configMsg)); todelete[0] = NotifyMsgnum; CtdlDeleteMessages(FNBL_QUEUE_ROOM, todelete, 1, ""); } -/*! \brief Checks to see what notification option the user has set - * +/*! + * \brief Run through the pager room queue + * Checks to see what notification option the user has set */ -void extNotify_getPrefs(long configMsgNum, char *configMsg) +void do_extnotify_queue(void) { - struct CtdlMessage *prefMsg; - // 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. - if (configMsgNum == -1) { - CtdlLogPrintf(CTDL_ERR, "extNotify_isAllowedByPrefs was passed a non-existant config message id\n"); + NotifyContext Ctx; + static int doing_queue = 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) && + IsEmptyStr(config.c_funambol_host)) + { + syslog(LOG_ERR, "No external notifiers configured on system/user\n"); + return; + } + + if (doing_queue) return; + doing_queue = 1; + + become_session(&extnotify_queue_CC); + + pthread_setspecific(MyConKey, (void *)&extnotify_queue_CC); + + /* + * Go ahead and run the queue + */ + syslog(LOG_DEBUG, "serv_extnotify: processing notify queue\n"); + + memset(&Ctx, 0, sizeof(NotifyContext)); + 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; } - prefMsg = CtdlFetchMessage(configMsgNum, 1); - strncpy(configMsg, prefMsg->cm_fields['M'], strlen(prefMsg->cm_fields['M'])); - CtdlFreeMessage(prefMsg); + CtdlForEachMessage(MSGS_ALL, 0L, NULL, + SPOOLMIME, NULL, process_notify, &Ctx); + 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); + } } -/*! \brief Get configuration message for pager/funambol system from the - * users "My Citadel Config" room + + +/* Create the notify message queue. We use the exact same room + * as the Funambol module. + * + * Run at server startup, creates FNBL_QUEUE_ROOM if it doesn't exist + * and sets as system room. */ -long extNotify_getConfigMessage(char *username) { - struct ctdlroom qrbuf; // scratch for room - struct ctdluser user; // ctdl user instance - char configRoomName[ROOMNAMELEN]; - struct CtdlMessage *msg; - struct cdbdata *cdbfr; - long *msglist = NULL; - int num_msgs = 0; - long confMsgNum = -1; - int a; +void create_extnotify_queue(void) { + struct ctdlroom qrbuf; + + CtdlCreateRoom(FNBL_QUEUE_ROOM, 3, "", 0, 1, 0, VIEW_MAILBOX); - // Get the user - CtdlGetUser(&user, username); + CtdlFillSystemContext(&extnotify_queue_CC, "Extnotify"); - CtdlMailboxName(configRoomName, sizeof configRoomName, &user, USERCONFIGROOM); - // Fill qrbuf - CtdlGetRoom(&qrbuf, configRoomName); - /* Do something really, really stoopid here. Raid the room on ourselves, - * loop through the messages manually and find it. I don't want - * to use a CtdlForEachMessage callback here, as we would be - * already in one */ - cdbfr = cdb_fetch(CDB_MSGLISTS, &qrbuf.QRnumber, sizeof(long)); - if (cdbfr != NULL) { - msglist = (long *) cdbfr->ptr; - 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"); - return -1; /* 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)) { - confMsgNum = msglist[a]; - } - CtdlFreeMessage(msg); - } + /* + * Make sure it's set to be a "system room" so it doesn't show up + * in the nown rooms list for Aides. + */ + if (CtdlGetRoomLock(&qrbuf, FNBL_QUEUE_ROOM) == 0) { + qrbuf.QRflags2 |= QR2_SYSTEM; + CtdlPutRoomLock(&qrbuf); } - return confMsgNum; - } + CTDL_MODULE_INIT(extnotify) { if (!threading) @@ -408,6 +443,6 @@ CTDL_MODULE_INIT(extnotify) create_extnotify_queue(); CtdlRegisterSessionHook(do_extnotify_queue, EVT_TIMER); } - /* return our Subversion id for the Log */ + /* return our module name for the log */ return "extnotify"; }