X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fextnotify%2Fextnotify_main.c;h=7bbad0503b9eee9830c092c7bba334085b451a6d;hb=320f2c1b46a08add1e866be64a101329932b98d6;hp=db1967eba78e5dd4651f3df46375c7a8ebed8ab5;hpb=f7b1efa87ade0ab3d80f39accf47f1de93c61b3e;p=citadel.git diff --git a/citadel/modules/extnotify/extnotify_main.c b/citadel/modules/extnotify/extnotify_main.c index db1967eba..7bbad0503 100644 --- a/citadel/modules/extnotify/extnotify_main.c +++ b/citadel/modules/extnotify/extnotify_main.c @@ -8,23 +8,20 @@ * Based on bits of serv_funambol * Contact: / * - * Copyright (c) 2008-2009 + * Copyright (c) 2008-2015 * - * 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. - * - * 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 + * 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. */ + #include "sysdep.h" #include #include @@ -65,10 +62,9 @@ #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) { @@ -77,10 +73,10 @@ void ExtNotify_PutErrorMessage(NotifyContext *Ctx, StrBuf *ErrMsg) 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); } @@ -92,7 +88,7 @@ StrBuf* GetNHBuf(int i, int allocit, StrBuf **NotifyHostList) } -StrBuf** GetNotifyHosts(void) +int GetNotifyHosts(NotifyContext *Ctx) { char NotifyHostsBuf[SIZ]; StrBuf *Host; @@ -101,43 +97,49 @@ 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; + + 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; notifynNotifyHosts; 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.", + 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 @@ -148,12 +150,16 @@ eNotifyType extNotify_getConfigMessage(char *username, char **PagerNumber, char 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, @@ -163,35 +169,40 @@ eNotifyType extNotify_getConfigMessage(char *username, char **PagerNumber, char 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"); return eNone; /* No messages at all? No further action. */ } for (a = 0; a < num_msgs; ++a) { - msg = CtdlFetchMessage(msglist[a], 1); + msg = CtdlFetchMessage(msglist[a], 1, 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'); @@ -229,10 +240,10 @@ eNotifyType extNotify_getConfigMessage(char *username, char **PagerNumber, char if (!pch || (*pch == '\0')) { free(configMsg); - + return eNone; } - while (isspace(*pch)) + while (isspace(*pch)) pch ++; *PagerNumber = pch; while (isdigit(*pch) || (*pch == '+')) @@ -250,7 +261,7 @@ eNotifyType extNotify_getConfigMessage(char *username, char **PagerNumber, char /* * 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; @@ -264,30 +275,34 @@ void process_notify(long NotifyMsgnum, void *usrdata) Ctx = (NotifyContext*) usrdata; - msg = CtdlFetchMessage(NotifyMsgnum, 1); - if ( msg->cm_fields['W'] != NULL) + msg = CtdlFetchMessage(NotifyMsgnum, 1, 1); + 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) { case eFunambol: snprintf(remoteurl, SIZ, "http://%s@%s:%d/%s", - config.c_funambol_auth, - config.c_funambol_host, - config.c_funambol_port, + CtdlGetConfigStr("c_funambol_auth"), + CtdlGetConfigStr("c_funambol_host"), + CtdlGetConfigInt("c_funambol_port"), FUNAMBOL_WS); - 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, - Ctx); + msg->cm_fields[eExtnotify], + msg->cm_fields[emessageId], + msgnum, + NULL); break; case eHttpMessages: { @@ -296,43 +311,53 @@ void process_notify(long NotifyMsgnum, void *usrdata) 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); - notify_http_server(URLBuf, + notify_http_server(URLBuf, ChrPtr(FileBuf), StrLength(FileBuf), - msg->cm_fields['W'], - msg->cm_fields['I'], - msgnum, - Ctx); - i++; + msg->cm_fields[eExtnotify], + msg->cm_fields[emessageId], + msgnum, + NULL); } 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(CtdlGetConfigStr("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", + CtdlGetConfigStr("c_pager_program"), + PagerNo, + msg->cm_fields[eExtnotify]); + system(command); free(command); } @@ -343,59 +368,72 @@ void process_notify(long NotifyMsgnum, void *usrdata) } 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) { - 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) && - IsEmptyStr(config.c_funambol_host)) + if (IsEmptyStr(CtdlGetConfigStr("c_pager_program")) && + IsEmptyStr(CtdlGetConfigStr("c_funambol_host"))) { - CtdlLogPrintf(CTDL_DEBUG, "No external notifiers configured on system/user"); + syslog(LOG_DEBUG, + "No external notifiers configured on system/user"); return; } - if (doing_queue) 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 */ - CtdlLogPrintf(CTDL_DEBUG, "serv_extnotify: processing notify queue\n"); - + syslog(LOG_DEBUG, "serv_extnotify: processing notify queue"); + 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>", 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"); doing_queue = 0; + if (Ctx.nNotifyHosts > 0) + { + for (i = 0; i < Ctx.nNotifyHosts * 2; i++) + FreeStrBuf(&Ctx.NotifyHostList[i]); + free(Ctx.NotifyHostList); + } } @@ -408,9 +446,11 @@ void do_extnotify_queue(void) */ void create_extnotify_queue(void) { struct ctdlroom qrbuf; - - CtdlCreateRoom(FNBL_QUEUE_ROOM, 3, "", 0, 1, 0, VIEW_MAILBOX); - + + 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 nown rooms list for Aides. @@ -421,13 +461,58 @@ void create_extnotify_queue(void) { } } +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(CtdlGetConfigStr("c_funambol_host")) || !IsEmptyStr(CtdlGetConfigStr("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"; }