2 * This module implements an external pager hook for when notifcation
3 * of a new email is wanted.
4 * Based on bits of serv_funambol
15 #include <sys/types.h>
17 #if TIME_WITH_SYS_TIME
18 # include <sys/time.h>
22 # include <sys/time.h>
31 #include <sys/socket.h>
34 #include "citserver.h"
44 #include "internet_addressing.h"
46 #include "clientsocket.h"
47 #include "serv_pager.h"
49 #include "ctdl_module.h"
51 #define PAGER_CONFIG_MESSAGE "__ Push email settings __"
52 #define PAGER_CONFIG_TEXT "textmessage"
55 * Create the notify message queue. We use the exact same room
57 void create_pager_queue(void) {
58 struct ctdlroom qrbuf;
60 create_room(FNBL_QUEUE_ROOM, 3, "", 0, 1, 0, VIEW_MAILBOX);
63 * Make sure it's set to be a "system room" so it doesn't show up
64 * in the <K>nown rooms list for Aides.
66 if (lgetroom(&qrbuf, FNBL_QUEUE_ROOM) == 0) {
67 qrbuf.QRflags2 |= QR2_SYSTEM;
71 void do_pager_queue(void) {
72 static int doing_queue = 0;
75 * This is a simple concurrency check to make sure only one queue run
76 * is done at a time. We could do this with a mutex, but since we
77 * don't really require extremely fine granularity here, we'll do it
78 * with a static variable instead.
80 if (doing_queue) return;
84 * Go ahead and run the queue
86 lprintf(CTDL_DEBUG, "serv_pager: processing notify queue\n");
88 if (getroom(&CC->room, FNBL_QUEUE_ROOM) != 0) {
89 lprintf(CTDL_ERR, "Cannot find room <%s>\n", FNBL_QUEUE_ROOM);
92 CtdlForEachMessage(MSGS_ALL, 0L, NULL,
93 SPOOLMIME, NULL, notify_pager, NULL);
95 lprintf(CTDL_DEBUG, "serv_pager: queue run completed\n");
100 * Call the external tool
102 void notify_pager(long msgnum, void *userdata) {
103 struct CtdlMessage *msg;
104 struct ctdlroom qrbuf;
106 /* W means 'wireless', which contains the unix name */
107 msg = CtdlFetchMessage(msgnum, 1);
108 if ( msg->cm_fields['W'] == NULL) {
111 /* Are we allowed to push? */
112 if (IsEmptyStr(config.c_pager_program)) {
114 } else if (IsEmptyStr(config.c_pager_program) && IsEmptyStr(config.c_funambol_host)) {
117 lprintf(CTDL_INFO, "Pager alerter enabled\n");
120 /* Get the configuration. We might be allowed system wide but the user
121 may have configured otherwise */
122 long configMsgNum = pager_getConfigMessage(msg->cm_fields['W']);
123 int allowed = pager_isPagerAllowedByPrefs(configMsgNum);
124 if (allowed != 0 && pager_doesUserWant(configMsgNum) == 0) {
126 } else if (allowed != 0) {
129 char *num = pager_getUserPhoneNumber(configMsgNum);
131 snprintf(command, sizeof command, "%s %s -u %s", config.c_pager_program, num, &msg->cm_fields['W']);
135 CtdlFreeMessage(msg);
137 todelete[0] = msgnum;
138 CtdlDeleteMessages(FNBL_QUEUE_ROOM, todelete, 1, "");
141 long pager_getConfigMessage(char *username) {
142 struct ctdlroom qrbuf; // scratch for room
143 struct ctdluser user; // ctdl user instance
144 char configRoomName[ROOMNAMELEN];
145 struct CtdlMessage *template;
146 struct CtdlMessage *msg;
147 struct cdbdata *cdbfr;
148 long *msglist = NULL;
150 long confMsgNum = -1;
152 getuser(&user, username);
154 MailboxName(configRoomName, sizeof configRoomName, &user, USERCONFIGROOM);
155 int prefroom = getroom(&qrbuf, configRoomName);
157 /* Do something really, really stoopid here. Raid the room on ourselves,
158 loop through the messages manually and find it. I don't want
159 to use a CtdlForEachMessage callback here, as we would be
161 cdbfr = cdb_fetch(CDB_MSGLISTS, &qrbuf.QRnumber, sizeof(long));
163 msglist = (long *) cdbfr->ptr;
164 cdbfr->ptr = NULL; /* CtdlForEachMessage() now owns this memory */
165 num_msgs = cdbfr->len / sizeof(long);
168 return -1; /* No messages at all? No further action. */
171 for (a = 0; a < num_msgs; ++a) {
172 msg = CtdlFetchMessage(msglist[a], 1);
174 if (msg->cm_fields['U'] != NULL && strncasecmp(msg->cm_fields['U'], PAGER_CONFIG_MESSAGE,
175 strlen(PAGER_CONFIG_MESSAGE)) == 0) {
176 confMsgNum = msglist[a];
178 CtdlFreeMessage(msg);
184 int pager_isPagerAllowedByPrefs(long configMsgNum) {
185 // Do a simple string search to see if 'textmessage' is selected as the
186 // type. This string would be at the very top of the message contents.
187 if (configMsgNum == -1) {
190 struct CtdlMessage *prefMsg;
191 prefMsg = CtdlFetchMessage(configMsgNum, 1);
192 char *msgContents = prefMsg->cm_fields['M'];
193 return strncasecmp(msgContents, PAGER_CONFIG_TEXT, strlen(PAGER_CONFIG_TEXT));
195 int pager_doesUserWant(long configMsgNum) {
196 if (configMsgNum == -1) {
199 struct CtdlMessage *prefMsg;
200 prefMsg = CtdlFetchMessage(configMsgNum, 1);
201 char *msgContents = prefMsg->cm_fields['M'];
202 return strncasecmp(msgContents, "none", 4);
204 /* warning: fetching twice gravely inefficient, will fix some time */
205 char *pager_getUserPhoneNumber(long configMsgNum) {
206 if (configMsgNum == -1) {
209 struct CtdlMessage *prefMsg;
210 prefMsg = CtdlFetchMessage(configMsgNum, 1);
211 char *msgContents = prefMsg->cm_fields['M'];
212 char *lines = strtok(msgContents, "textmessage\n");
215 CTDL_MODULE_INIT(pager)
217 create_pager_queue();
218 CtdlRegisterSessionHook(do_pager_queue, EVT_TIMER);
220 /* return our Subversion id for the Log */
221 return "$Id: serv_pager.c $";