6049b179d2fbd8877286a476551a4a209eb094da
[citadel.git] / citadel / modules / extnotify / funambol65.c
1 /* 
2  * funambol65.c
3  * Author: Mathew McBride
4  * 
5  * This module facilitates notifications to a Funambol server
6  * for push email
7  *
8  * Based on bits of the previous serv_funambol
9  * Contact: <matt@mcbridematt.dhs.org> / <matt@comalies>
10  *
11  * Copyright (c) 2008-2010
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <sys/socket.h>
32 #include <time.h>
33 #include <libcitadel.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <curl/curl.h>
37
38 #include "citadel.h"
39 #include "citadel_dirs.h"
40 #include "clientsocket.h"
41 #include "sysdep.h"
42 #include "config.h"
43 #include "sysdep_decls.h"
44 #include "msgbase.h"
45 #include "ctdl_module.h"
46
47 #include "event_client.h"
48 #include "extnotify.h"
49
50 eNextState EvaluateResult(AsyncIO *IO);
51
52 /*
53 * \brief Sends a message to the Funambol server notifying 
54 * of new mail for a user
55 * Returns 0 if unsuccessful
56 */
57 int notify_http_server(char *remoteurl, 
58                        const char* template, long tlen, 
59                        char *user,
60                        char *msgid, 
61                        long MsgNum, 
62                        NotifyContext *Ctx) 
63 {
64         CURLcode sta;
65         char msgnumstr[128];
66         char *buf = NULL;
67         char *SOAPMessage = NULL;
68         char *contenttype = NULL;
69         StrBuf *ReplyBuf;
70         CURL *chnd;
71         AsyncIO *IO;
72
73         IO = (AsyncIO*) malloc(sizeof(AsyncIO));
74         memset(IO, 0, sizeof(AsyncIO));
75         IO->CitContext = CC;
76
77         snprintf(msgnumstr, 128, "%ld", MsgNum);
78
79         if (tlen > 0) {
80                 /* Load the template message. Get mallocs done too */
81                 FILE *Ftemplate = NULL;
82                 const char *mimetype;
83
84                 Ftemplate = fopen(template, "r");
85                 if (Ftemplate == NULL) {
86                         char buf[SIZ];
87
88                         snprintf(buf, SIZ, 
89                                  "Cannot load template file %s [%s]won't send notification\r\n", 
90                                  file_funambol_msg, strerror(errno));
91                         CtdlLogPrintf(CTDL_ERR, buf);
92
93                         CtdlAideMessage(buf, "External notifier unable to find message template!");
94                         goto abort;
95                 }
96                 mimetype = GuessMimeByFilename(template, tlen);
97
98                 buf = malloc(SIZ);
99                 memset(buf, 0, SIZ);
100                 SOAPMessage = malloc(3072);
101                 memset(SOAPMessage, 0, 3072);
102         
103                 while(fgets(buf, SIZ, Ftemplate) != NULL) {
104                         strcat(SOAPMessage, buf);
105                 }
106                 fclose(Ftemplate);
107         
108                 if (strlen(SOAPMessage) < 0) {
109                         char buf[SIZ];
110
111                         snprintf(buf, SIZ, 
112                                  "Cannot load template file %s; won't send notification\r\n", 
113                                  file_funambol_msg);
114                         CtdlLogPrintf(CTDL_ERR, buf);
115
116                         CtdlAideMessage(buf, "External notifier unable to load message template!");
117                         goto abort;
118                 }
119                 // Do substitutions
120                 help_subst(SOAPMessage, "^notifyuser", user);
121                 help_subst(SOAPMessage, "^syncsource", config.c_funambol_source);
122                 help_subst(SOAPMessage, "^msgid", msgid);
123                 help_subst(SOAPMessage, "^msgnum", msgnumstr);
124
125                 /* pass our list of custom made headers */
126
127                 contenttype=(char*) malloc(40+strlen(mimetype));
128                 sprintf(contenttype,"Content-Type: %s; charset=utf-8", mimetype);
129
130                 IO->HttpReq.headers = curl_slist_append(IO->HttpReq.headers, "SOAPAction: \"\"");
131                 IO->HttpReq.headers = curl_slist_append(IO->HttpReq.headers, contenttype);
132                 IO->HttpReq.headers = curl_slist_append(IO->HttpReq.headers, "Accept: application/soap+xml, application/mime, multipart/related, text/*");
133                 IO->HttpReq.headers = curl_slist_append(IO->HttpReq.headers, "Pragma: no-cache");
134
135                 /* Now specify the POST binary data */
136                 IO->HttpReq.PlainPostData = SOAPMessage;
137                 IO->HttpReq.PlainPostDataLen = strlen(SOAPMessage);
138         }
139         else {
140                 help_subst(remoteurl, "^notifyuser", user);
141                 help_subst(remoteurl, "^syncsource", config.c_funambol_source);
142                 help_subst(remoteurl, "^msgid", msgid);
143                 help_subst(remoteurl, "^msgnum", msgnumstr);
144                 IO->HttpReq.headers = curl_slist_append(IO->HttpReq.headers, "Accept: application/soap+xml, application/mime, multipart/related, text/*");
145                 IO->HttpReq.headers = curl_slist_append(IO->HttpReq.headers, "Pragma: no-cache");
146         }
147
148         ParseURL(&IO->ConnectMe, NewStrBufPlain (remoteurl, -1), 80);
149         CurlPrepareURL(IO->ConnectMe);
150         if (! evcurl_init(IO, 
151 //                        Ctx, 
152                           NULL,
153                           "Citadel ExtNotify",
154                           EvaluateResult))
155         {
156                 CtdlLogPrintf(CTDL_ALERT, "Unable to initialize libcurl.\n");
157                 goto abort;
158         }
159         chnd = IO->HttpReq.chnd;
160         OPT(SSL_VERIFYPEER, 0);
161         OPT(SSL_VERIFYHOST, 0);
162 /*
163         ReplyBuf = NewStrBuf();
164         curl_easy_setopt(curl, CURLOPT_WRITEDATA, ReplyBuf);
165         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlFillStrBuf_callback);
166 */
167         if (
168                 (!IsEmptyStr(config.c_ip_addr))
169                 && (strcmp(config.c_ip_addr, "*"))
170                 && (strcmp(config.c_ip_addr, "::"))
171                 && (strcmp(config.c_ip_addr, "0.0.0.0"))
172         ) {
173                 OPT(INTERFACE, config.c_ip_addr);
174         }
175
176         evcurl_handle_start(IO);
177
178         return 0;
179 abort:
180 ///     curl_slist_free_all (headers);
181 ///     curl_easy_cleanup(curl);
182         if (contenttype) free(contenttype);
183         if (SOAPMessage != NULL) free(SOAPMessage);
184         if (buf != NULL) free(buf);
185         FreeStrBuf (&ReplyBuf);
186         return 1;
187 }
188
189
190 eNextState EvaluateResult(AsyncIO *IO)
191 {
192
193         if (IO->HttpReq.httpcode != 200) {
194                 StrBuf *ErrMsg;
195
196                 CtdlLogPrintf(CTDL_ALERT, "libcurl error %ld: %s\n", 
197                               IO->HttpReq.httpcode, 
198                               IO->HttpReq.errdesc);
199                 ErrMsg = NewStrBufPlain(HKEY("Error sending your Notification\n"));
200                 StrBufAppendPrintf(ErrMsg, "\nlibcurl error %ld: \n\t\t%s\n", 
201                                    IO->HttpReq.httpcode, 
202                                    IO->HttpReq.errdesc);
203                 StrBufAppendBufPlain(ErrMsg, HKEY("\nWas Trying to send: \n"), 0);
204                 StrBufAppendBufPlain(ErrMsg, IO->ConnectMe->PlainUrl, -1, 0);
205                 if (IO->HttpReq.PlainPostDataLen > 0) {
206                         StrBufAppendBufPlain(ErrMsg, HKEY("\nThe Post document was: \n"), 0);
207                         StrBufAppendBufPlain(ErrMsg, 
208                                              IO->HttpReq.PlainPostData, 
209                                              IO->HttpReq.PlainPostDataLen, 0);
210                         StrBufAppendBufPlain(ErrMsg, HKEY("\n\n"), 0);                  
211                 }
212                 if (StrLength(IO->HttpReq.ReplyData) > 0) {                     
213                         StrBufAppendBufPlain(ErrMsg, HKEY("\n\nThe Serverreply was: \n\n"), 0);
214                         StrBufAppendBuf(ErrMsg, IO->HttpReq.ReplyData, 0);
215                 }
216                 else 
217                         StrBufAppendBufPlain(ErrMsg, HKEY("\n\nThere was no Serverreply.\n\n"), 0);
218                 ///ExtNotify_PutErrorMessage(Ctx, ErrMsg);
219                 CtdlAideMessage(ChrPtr(ErrMsg), "External notifier unable to load message template!");
220         }
221
222         CtdlLogPrintf(CTDL_DEBUG, "Funambol notified\n");
223 /*
224         while ((Ctx.NotifyHostList != NULL) && (Ctx.NotifyHostList[i] != NULL))
225                 FreeStrBuf(&Ctx.NotifyHostList[i]);
226
227         if (Ctx.NotifyErrors != NULL)
228         {
229                 long len;
230                 const char *Key;
231                 HashPos *It;
232                 void *vErr;
233                 StrBuf *ErrMsg;
234
235                 It = GetNewHashPos(Ctx.NotifyErrors, 0);
236                 while (GetNextHashPos(Ctx.NotifyErrors, It, &len, &Key, &vErr) && 
237                        (vErr != NULL)) {
238                         ErrMsg = (StrBuf*) vErr;
239                         quickie_message("Citadel", NULL, NULL, AIDEROOM, ChrPtr(ErrMsg), FMT_FIXED, 
240                                         "Failed to notify external service about inbound mail");
241                 }
242
243                 DeleteHashPos(&It);
244                 DeleteHash(&Ctx.NotifyErrors);
245         }
246 */
247
248 ////    curl_slist_free_all (headers);
249 ///     curl_easy_cleanup(curl);
250         ///if (contenttype) free(contenttype);
251         ///if (SOAPMessage != NULL) free(SOAPMessage);
252         ///if (buf != NULL) free(buf);
253         ///FreeStrBuf (&ReplyBuf);
254         return 0;
255 }