Back to index

citadel  8.12
funambol65.c
Go to the documentation of this file.
00001 /*
00002  * funambol65.c
00003  * Author: Mathew McBride
00004  *
00005  * This module facilitates notifications to a Funambol server
00006  * for push email
00007  *
00008  * Based on bits of the previous serv_funambol
00009  * Contact: <matt@mcbridematt.dhs.org> / <matt@comalies>
00010  *
00011  * Copyright (c) 2008-2010
00012  *
00013  * This program is open source software; you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License version 3.
00015  * 
00016  * 
00017  *
00018  * This program is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * 
00024  * 
00025  * 
00026  */
00027 
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <sys/socket.h>
00032 #include <time.h>
00033 #include <libcitadel.h>
00034 #include <errno.h>
00035 #include <unistd.h>
00036 #include <curl/curl.h>
00037 
00038 #include "citadel.h"
00039 #include "citadel_dirs.h"
00040 #include "clientsocket.h"
00041 #include "sysdep.h"
00042 #include "config.h"
00043 #include "sysdep_decls.h"
00044 #include "msgbase.h"
00045 #include "ctdl_module.h"
00046 
00047 #include "event_client.h"
00048 #include "extnotify.h"
00049 
00050 eNextState EvaluateResult(AsyncIO *IO);
00051 eNextState ExtNotifyTerminate(AsyncIO *IO);
00052 eNextState ExtNotifyTerminateDB(AsyncIO *IO);
00053 eNextState ExtNotifyShutdownAbort(AsyncIO *IO);
00054 
00055 /*
00056 * \brief Sends a message to the Funambol server notifying
00057 * of new mail for a user
00058 * Returns 0 if unsuccessful
00059 */
00060 int notify_http_server(char *remoteurl,
00061                      const char* template, long tlen,
00062                      char *user,
00063                      char *msgid,
00064                      long MsgNum,
00065                      NotifyContext *Ctx)
00066 {
00067        CURLcode sta;
00068        char msgnumstr[128];
00069        char *buf = NULL;
00070        char *SOAPMessage = NULL;
00071        char *contenttype = NULL;
00072        StrBuf *ReplyBuf;
00073        StrBuf *Buf;
00074        CURL *chnd;
00075        AsyncIO *IO;
00076 
00077        IO = (AsyncIO*) malloc(sizeof(AsyncIO));
00078        memset(IO, 0, sizeof(AsyncIO));
00079 
00080        if (! InitcURLIOStruct(IO,
00081                             NULL, /* we don't have personal data anymore. */
00082                             "Citadel ExtNotify",
00083                             EvaluateResult,
00084                             ExtNotifyTerminate,
00085                             ExtNotifyTerminateDB,
00086                             ExtNotifyShutdownAbort))
00087        {
00088               syslog(LOG_ALERT, "Unable to initialize libcurl.\n");
00089               goto abort;
00090        }
00091 
00092        snprintf(msgnumstr, 128, "%ld", MsgNum);
00093 
00094        if (tlen > 0) {
00095               /* Load the template message. Get mallocs done too */
00096               int fd;
00097               struct stat statbuf;
00098               const char *mimetype;
00099               const char *Err = NULL;
00100 
00101               fd = open(template, O_RDONLY);
00102               if ((fd < 0) ||
00103                   (fstat(fd, &statbuf) == -1))
00104               {
00105                      char buf[SIZ];
00106 
00107                      snprintf(buf, SIZ,
00108                              "Cannot load template file %s [%s] "
00109                              "won't send notification\r\n",
00110                              file_funambol_msg,
00111                              strerror(errno));
00112                      syslog(LOG_ERR, "%s", buf);
00113                      // TODO: once an hour!
00114                      CtdlAideMessage(
00115                             buf,
00116                             "External notifier: "
00117                             "unable to find/stat message template!");
00118                      goto abort;
00119               }
00120 
00121               Buf = NewStrBufPlain(NULL, statbuf.st_size + 1);
00122               if (StrBufReadBLOB(Buf, &fd, 1, statbuf.st_size, &Err) < 0) {
00123                      char buf[SIZ];
00124 
00125                      close(fd);
00126 
00127                      snprintf(buf, SIZ,
00128                              "Cannot load template file %s [%s] "
00129                              "won't send notification\r\n",
00130                              file_funambol_msg,
00131                              Err);
00132                      syslog(LOG_ERR, "%s", buf);
00133                      // TODO: once an hour!
00134                      CtdlAideMessage(
00135                             buf,
00136                             "External notifier: "
00137                             "unable to load message template!");
00138                      goto abort;
00139               }
00140               close(fd);
00141 
00142               mimetype = GuessMimeByFilename(template, tlen);
00143 
00144               SOAPMessage = SmashStrBuf(&Buf);
00145 
00146               // Do substitutions
00147               help_subst(SOAPMessage, "^notifyuser", user);
00148               help_subst(SOAPMessage, "^syncsource",
00149                         config.c_funambol_source);
00150               help_subst(SOAPMessage, "^msgid", msgid);
00151               help_subst(SOAPMessage, "^msgnum", msgnumstr);
00152 
00153               /* pass our list of custom made headers */
00154 
00155               contenttype=(char*) malloc(40+strlen(mimetype));
00156               sprintf(contenttype,
00157                      "Content-Type: %s; charset=utf-8",
00158                      mimetype);
00159 
00160               IO->HttpReq.headers = curl_slist_append(
00161                      IO->HttpReq.headers,
00162                      "SOAPAction: \"\"");
00163 
00164               IO->HttpReq.headers = curl_slist_append(
00165                      IO->HttpReq.headers,
00166                      contenttype);
00167               free(contenttype);
00168               contenttype = NULL;
00169               IO->HttpReq.headers = curl_slist_append(
00170                      IO->HttpReq.headers,
00171                      "Accept: application/soap+xml, "
00172                      "application/mime, multipart/related, text/*");
00173 
00174               IO->HttpReq.headers = curl_slist_append(
00175                      IO->HttpReq.headers,
00176                      "Pragma: no-cache");
00177 
00178               /* Now specify the POST binary data */
00179               IO->HttpReq.PlainPostData = SOAPMessage;
00180               IO->HttpReq.PlainPostDataLen = strlen(SOAPMessage);
00181        }
00182        else {
00183               help_subst(remoteurl, "^notifyuser", user);
00184               help_subst(remoteurl, "^syncsource", config.c_funambol_source);
00185               help_subst(remoteurl, "^msgid", msgid);
00186               help_subst(remoteurl, "^msgnum", msgnumstr);
00187 
00188               IO->HttpReq.headers = curl_slist_append(
00189                      IO->HttpReq.headers,
00190                      "Accept: application/soap+xml, "
00191                      "application/mime, multipart/related, text/*");
00192 
00193               IO->HttpReq.headers = curl_slist_append(
00194                      IO->HttpReq.headers,
00195                      "Pragma: no-cache");
00196        }
00197 
00198        Buf = NewStrBufPlain (remoteurl, -1);
00199        ParseURL(&IO->ConnectMe, Buf, 80);
00200        FreeStrBuf(&Buf); /* TODO: this is uncool... */
00201        CurlPrepareURL(IO->ConnectMe);
00202 
00203        chnd = IO->HttpReq.chnd;
00204        OPT(SSL_VERIFYPEER, 0);
00205        OPT(SSL_VERIFYHOST, 0);
00206 
00207        QueueCurlContext(IO);
00208 
00209        return 0;
00210 abort:
00211 
00212        if (contenttype) free(contenttype);
00213        if (SOAPMessage != NULL) free(SOAPMessage);
00214        if (buf != NULL) free(buf);
00215        FreeStrBuf (&ReplyBuf);
00216        return 1;
00217 }
00218 
00219 
00220 eNextState EvaluateResult(AsyncIO *IO)
00221 {
00222 
00223        if (IO->HttpReq.httpcode != 200) {
00224               StrBuf *ErrMsg;
00225 
00226               syslog(LOG_ALERT, "libcurl error %ld: %s\n",
00227                            IO->HttpReq.httpcode,
00228                            IO->HttpReq.errdesc);
00229 
00230               ErrMsg = NewStrBufPlain(
00231                      HKEY("Error sending your Notification\n"));
00232               StrBufAppendPrintf(ErrMsg, "\nlibcurl error %ld: \n\t\t%s\n",
00233                                IO->HttpReq.httpcode,
00234                                IO->HttpReq.errdesc);
00235 
00236               StrBufAppendBufPlain(ErrMsg,
00237                                  HKEY("\nWas Trying to send: \n"),
00238                                  0);
00239 
00240               StrBufAppendBufPlain(ErrMsg, IO->ConnectMe->PlainUrl, -1, 0);
00241               if (IO->HttpReq.PlainPostDataLen > 0) {
00242                      StrBufAppendBufPlain(
00243                             ErrMsg,
00244                             HKEY("\nThe Post document was: \n"),
00245                             0);
00246                      StrBufAppendBufPlain(ErrMsg,
00247                                         IO->HttpReq.PlainPostData,
00248                                         IO->HttpReq.PlainPostDataLen, 0);
00249                      StrBufAppendBufPlain(ErrMsg, HKEY("\n\n"), 0);
00250               }
00251               if (StrLength(IO->HttpReq.ReplyData) > 0) {
00252                      StrBufAppendBufPlain(
00253                             ErrMsg,
00254                             HKEY("\n\nThe Serverreply was: \n\n"),
00255                             0);
00256                      StrBufAppendBuf(ErrMsg, IO->HttpReq.ReplyData, 0);
00257               }
00258               else
00259                      StrBufAppendBufPlain(
00260                             ErrMsg,
00261                             HKEY("\n\nThere was no Serverreply.\n\n"),
00262                             0);
00264               CtdlAideMessage(ChrPtr(ErrMsg),
00265                             "External notifier: "
00266                             "unable to contact notification host!");
00267        }
00268 
00269        syslog(LOG_DEBUG, "Funambol notified\n");
00270 /*
00271        while ((Ctx.NotifyHostList != NULL) && (Ctx.NotifyHostList[i] != NULL))
00272               FreeStrBuf(&Ctx.NotifyHostList[i]);
00273 
00274        if (Ctx.NotifyErrors != NULL)
00275        {
00276               long len;
00277               const char *Key;
00278               HashPos *It;
00279               void *vErr;
00280               StrBuf *ErrMsg;
00281 
00282               It = GetNewHashPos(Ctx.NotifyErrors, 0);
00283               while (GetNextHashPos(Ctx.NotifyErrors,
00284               It, &len, &Key, &vErr) &&
00285                      (vErr != NULL)) {
00286                      ErrMsg = (StrBuf*) vErr;
00287                      quickie_message("Citadel", NULL, NULL,
00288                      AIDEROOM, ChrPtr(ErrMsg), FMT_FIXED,
00289                      "Failed to notify external service about inbound mail");
00290               }
00291 
00292               DeleteHashPos(&It);
00293               DeleteHash(&Ctx.NotifyErrors);
00294        }
00295 */
00296 
00303        return 0;
00304 }
00305 
00306 eNextState ExtNotifyTerminateDB(AsyncIO *IO)
00307 {
00308        free(IO);
00309        return eAbort;
00310 }
00311 eNextState ExtNotifyTerminate(AsyncIO *IO)
00312 {
00313        free(IO);
00314        return eAbort;
00315 }
00316 eNextState ExtNotifyShutdownAbort(AsyncIO *IO)
00317 {
00318        free(IO);
00319        return eAbort;
00320 }