Back to index

citadel  8.12
serv_notes.c
Go to the documentation of this file.
00001 /*
00002  * Handles functions related to yellow sticky notes.
00003  *
00004  * Copyright (c) 2007-2012 by the citadel.org team
00005  *
00006  *  This program is open source software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License version 3.
00008  *  
00009  *  
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  
00017  *  
00018  *  
00019  */
00020 
00021 #include "sysdep.h"
00022 #include <stdlib.h>
00023 #include <unistd.h>
00024 #include <stdio.h>
00025 #include <fcntl.h>
00026 #include <signal.h>
00027 #include <pwd.h>
00028 #include <errno.h>
00029 #include <sys/types.h>
00030 
00031 #if TIME_WITH_SYS_TIME
00032 # include <sys/time.h>
00033 # include <time.h>
00034 #else
00035 # if HAVE_SYS_TIME_H
00036 #  include <sys/time.h>
00037 # else
00038 #  include <time.h>
00039 # endif
00040 #endif
00041 
00042 #include <sys/wait.h>
00043 #include <string.h>
00044 #include <limits.h>
00045 #include <libcitadel.h>
00046 #include "citadel.h"
00047 #include "server.h"
00048 #include "citserver.h"
00049 #include "support.h"
00050 #include "config.h"
00051 #include "user_ops.h"
00052 #include "database.h"
00053 #include "msgbase.h"
00054 
00055 #include "ctdl_module.h"
00056 
00057 
00058 /*
00059  * Callback function for serv_notes_beforesave() hunts for a vNote in the MIME structure
00060  */
00061 void notes_extract_vnote(char *name, char *filename, char *partnum, char *disp,
00062                  void *content, char *cbtype, char *cbcharset, size_t length,
00063                  char *encoding, char *cbid, void *cbuserdata)
00064 {
00065        struct vnote **v = (struct vnote **) cbuserdata;
00066 
00067        if (!strcasecmp(cbtype, "text/vnote")) {
00068 
00069               syslog(LOG_DEBUG, "Part %s contains a vNote!  Loading...\n", partnum);
00070               if (*v != NULL) {
00071                      vnote_free(*v);
00072               }
00073               *v = vnote_new_from_str(content);
00074        }
00075 }
00076 
00077 
00078 /*
00079  * Before-save hook searches for two different types of notes (legacy Kolab/Aethera notes
00080  * and modern vNote format notes) and does its best to learn the subject (summary)
00081  * and EUID (uid) of the note for Citadel's own nefarious purposes.
00082  */
00083 int serv_notes_beforesave(struct CtdlMessage *msg)
00084 {
00085        char *p;
00086        int a, i;
00087        char uuid[512];
00088        struct vnote *v = NULL;
00089 
00090        /* First determine if this room has the "notes" view set */
00091 
00092        if (CC->room.QRdefaultview != VIEW_NOTES) {
00093               return(0);                  /* not notes; do nothing */
00094        }
00095 
00096        /* It must be an RFC822 message! */
00097        if (msg->cm_format_type != 4) {
00098               return(0);    /* You tried to save a non-RFC822 message! */
00099        }
00100        
00101        /*
00102         * If we are in a "notes" view room, and the client has sent an RFC822
00103         * message containing an X-KOrg-Note-Id: field (Aethera does this, as
00104         * do some Kolab clients) then set both the Subject and the Exclusive ID
00105         * of the message to that.  It's going to be a UUID so we want to replace
00106         * any existing message containing that UUID.
00107         */
00108        strcpy(uuid, "");
00109        p = msg->cm_fields['M'];
00110        a = strlen(p);
00111        while (--a > 0) {
00112               if (!strncasecmp(p, "X-KOrg-Note-Id: ", 16)) {   /* Found it */
00113                      safestrncpy(uuid, p + 16, sizeof(uuid));
00114                      for (i = 0; uuid[i]; ++i) {
00115                             if ( (uuid[i] == '\r') || (uuid[i] == '\n') ) {
00116                                    uuid[i] = 0;
00117                                    break;
00118                             }
00119                      }
00120 
00121                      syslog(LOG_DEBUG, "UUID of note is: %s\n", uuid);
00122                      if (!IsEmptyStr(uuid)) {
00123 
00124                             if (msg->cm_fields['E'] != NULL) {
00125                                    free(msg->cm_fields['E']);
00126                             }
00127                             msg->cm_fields['E'] = strdup(uuid);
00128 
00129                             if (msg->cm_fields['U'] != NULL) {
00130                                    free(msg->cm_fields['U']);
00131                             }
00132                             msg->cm_fields['U'] = strdup(uuid);
00133                      }
00134               }
00135               p++;
00136        }
00137 
00138        /* Modern clients are using vNote format.  Check for one... */
00139 
00140        mime_parser(msg->cm_fields['M'],
00141               NULL,
00142               *notes_extract_vnote,
00143               NULL, NULL,
00144               &v,           /* user data ptr - put the vnote here */
00145               0
00146        );
00147 
00148        if (v == NULL) return(0);   /* no vNotes were found in this message */
00149 
00150        /* Set the message EUID to the vNote UID */
00151 
00152        if (v->uid) if (!IsEmptyStr(v->uid)) {
00153               syslog(LOG_DEBUG, "UID of vNote is: %s\n", v->uid);
00154               if (msg->cm_fields['E'] != NULL) {
00155                      free(msg->cm_fields['E']);
00156               }
00157               msg->cm_fields['E'] = strdup(v->uid);
00158        }
00159 
00160        /* Set the message Subject to the vNote Summary */
00161 
00162        if (v->summary) if (!IsEmptyStr(v->summary)) {
00163               if (msg->cm_fields['U'] != NULL) {
00164                      free(msg->cm_fields['U']);
00165               }
00166               msg->cm_fields['U'] = strdup(v->summary);
00167               if (strlen(msg->cm_fields['U']) > 72) {
00168                      strcpy(&msg->cm_fields['U'][68], "...");
00169               }
00170        }
00171 
00172        vnote_free(v);
00173        
00174        return(0);
00175 }
00176 
00177 
00178 CTDL_MODULE_INIT(notes)
00179 {
00180        if (!threading)
00181        {
00182               CtdlRegisterMessageHook(serv_notes_beforesave, EVT_BEFORESAVE);
00183        }
00184        
00185        /* return our module name for the log */
00186        return "notes";
00187 }