remember the lengths of config strings.
[citadel.git] / citadel / modules / instmsg / serv_instmsg.c
index fd0fa8e33a07231d0308fcfaa1b9db00f2713a52..17ed7cc629830d372d2ffdc6230ede42ab34490a 100644 (file)
@@ -1,24 +1,15 @@
 /*
- * $Id$
- *
  * This module handles instant messaging between users.
  * 
- * Copyright (c) 1987-2010 by the citadel.org team
+ * Copyright (c) 1987-2012 by the citadel.org team
  *
- * 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 version 3.
  *
  * 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
- *
  */
 #include "sysdep.h"
 #include <stdlib.h>
 #include "config.h"
 #include "msgbase.h"
 #include "user_ops.h"
-
-#ifndef HAVE_SNPRINTF
-#include "snprintf.h"
-#endif
-
 #include "ctdl_module.h"
 
 struct imlog {
@@ -473,16 +459,17 @@ void flush_individual_conversation(struct imlog *im) {
        msg->cm_anon_type = MES_NORMAL;
        msg->cm_format_type = FMT_RFC822;
        if (!IsEmptyStr(im->usernames[0])) {
-               msg->cm_fields['A'] = strdup(im->usernames[0]);
+               CM_SetField(msg, eAuthor, im->usernames[0], strlen(im->usernames[0]));
        } else {
-               msg->cm_fields['A'] = strdup("Citadel");
+               CM_SetField(msg, eAuthor, HKEY("Citadel"));
        }
        if (!IsEmptyStr(im->usernames[1])) {
-               msg->cm_fields['R'] = strdup(im->usernames[1]);
+               CM_SetField(msg, eRecipient, im->usernames[1], strlen(im->usernames[1]));
        }
-       msg->cm_fields['O'] = strdup(PAGELOGROOM);
-       msg->cm_fields['N'] = strdup(NODENAME);
-       msg->cm_fields['M'] = SmashStrBuf(&im->conversation);   /* we own this memory now */
+
+       CM_SetField(msg, eOriginalRoom, HKEY(PAGELOGROOM));
+       CM_SetField(msg, eNodeName, CFG_KEY(c_nodename));
+       CM_SetAsFieldSB(msg, eMesageText, &im->conversation);   /* we own this memory now */
 
        /* Start with usernums[1] because it's guaranteed to be higher than usernums[0],
         * so if there's only one party, usernums[0] will be zero but usernums[1] won't.
@@ -496,7 +483,7 @@ void flush_individual_conversation(struct imlog *im) {
        snprintf(roomname, sizeof roomname, "%010ld.%s", im->usernums[1], PAGELOGROOM);
        CtdlCreateRoom(roomname, 5, "", 0, 1, 1, VIEW_BBS);
        msgnum = CtdlSubmitMsg(msg, NULL, roomname, 0);
-       CtdlFreeMessage(msg);
+       CM_Free(msg);
 
        /* If there is a valid user number in usernums[0], save a copy for them too. */
        if (im->usernums[0] > 0) {
@@ -523,12 +510,38 @@ void flush_conversations_to_disk(time_t if_older_than) {
        struct imlog *flush_these = NULL;
        struct imlog *dont_flush_these = NULL;
        struct imlog *imptr = NULL;
+       struct CitContext *nptr;
+       int nContexts, i;
+
+       nptr = CtdlGetContextArray(&nContexts) ;        /* Make a copy of the current wholist */
 
        begin_critical_section(S_IM_LOGS);
        while (imlist)
        {
                imptr = imlist;
                imlist = imlist->next;
+
+               /* For a two party conversation, if one party has logged out, force flush. */
+               if (nptr) {
+                       int user0_is_still_online = 0;
+                       int user1_is_still_online = 0;
+                       for (i=0; i<nContexts; i++)  {
+                               if (nptr[i].user.usernum == imptr->usernums[0]) ++user0_is_still_online;
+                               if (nptr[i].user.usernum == imptr->usernums[1]) ++user1_is_still_online;
+                       }
+                       if (imptr->usernums[0] != imptr->usernums[1]) {         /* two party conversation */
+                               if ((!user0_is_still_online) || (!user1_is_still_online)) {
+                                       imptr->lastmsg = 0L;    /* force flush */
+                               }
+                       }
+                       else {          /* one party conversation (yes, people do IM themselves) */
+                               if (!user0_is_still_online) {
+                                       imptr->lastmsg = 0L;    /* force flush */
+                               }
+                       }
+               }
+
+               /* Now test this conversation to see if it qualifies for flushing. */
                if ((time(NULL) - imptr->lastmsg) > if_older_than)
                {
                        /* This conversation qualifies.  Move it to the list of ones to flush. */
@@ -543,6 +556,7 @@ void flush_conversations_to_disk(time_t if_older_than) {
        }
        imlist = dont_flush_these;
        end_critical_section(S_IM_LOGS);
+       free(nptr);
 
        /* We are now outside of the critical section, and we are the only thread holding a
         * pointer to a linked list of conversations to be flushed to disk.
@@ -574,13 +588,13 @@ CTDL_MODULE_INIT(instmsg)
                CtdlRegisterProtoHook(cmd_sexp, "SEXP", "Send an instant message");
                CtdlRegisterProtoHook(cmd_dexp, "DEXP", "Disable instant messages");
                CtdlRegisterProtoHook(cmd_reqt, "REQT", "Request client termination");
-               CtdlRegisterSessionHook(cmd_gexp_async, EVT_ASYNC);
-               CtdlRegisterSessionHook(delete_instant_messages, EVT_STOP);
+               CtdlRegisterSessionHook(cmd_gexp_async, EVT_ASYNC, PRIO_ASYNC + 1);
+               CtdlRegisterSessionHook(delete_instant_messages, EVT_STOP, PRIO_STOP + 1);
                CtdlRegisterXmsgHook(send_instant_message, XMSG_PRI_LOCAL);
-               CtdlRegisterSessionHook(instmsg_timer, EVT_TIMER);
-               CtdlRegisterSessionHook(instmsg_shutdown, EVT_SHUTDOWN);
+               CtdlRegisterSessionHook(instmsg_timer, EVT_TIMER, PRIO_CLEANUP + 400);
+               CtdlRegisterSessionHook(instmsg_shutdown, EVT_SHUTDOWN, PRIO_SHUTDOWN + 10);
        }
        
-       /* return our Subversion id for the Log */
-       return "$Id$";
+       /* return our module name for the log */
+       return "instmsg";
 }