e14d135558b901e5d8182ba0bb644edc36bb1f8a
[citadel.git] / citadel / modules / extnotify / funambol65.c
1 /* 
2 * \file 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
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <sys/socket.h>
16 #include <time.h>
17 #include <libcitadel.h>
18 #include <errno.h>
19 #include <unistd.h>
20 #include <curl/curl.h>
21
22 #include "citadel.h"
23 #include "citadel_dirs.h"
24 #include "clientsocket.h"
25 #include "sysdep.h"
26 #include "config.h"
27 #include "sysdep_decls.h"
28 #include "msgbase.h"
29 #include "ctdl_module.h"
30
31 #include "extnotify.h"
32
33 /*
34 * \brief Sends a message to the Funambol server notifying 
35 * of new mail for a user
36 * Returns 0 if unsuccessful
37 */
38 int notify_http_server(char *remoteurl, 
39                        const char* template, long tlen, 
40                        char *user,
41                        char *msgid, 
42                        long MsgNum, 
43                        NotifyContext *Ctx) 
44 {
45         char curl_errbuf[CURL_ERROR_SIZE];
46         char *pchs, *pche;
47         char userpass[SIZ];
48         char msgnumstr[128];
49         char *buf = NULL;
50         CURL *curl;
51         CURLcode res;
52         struct curl_slist * headers=NULL;
53         char errmsg[1024] = "";
54         char *SOAPMessage = NULL;
55         char *contenttype = NULL;
56         StrBuf *ReplyBuf;
57
58         curl = curl_easy_init();
59         if (!curl) {
60                 CtdlLogPrintf(CTDL_ALERT, "Unable to initialize libcurl.\n");
61                 return 1;
62         }
63
64         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
65         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
66         ReplyBuf = NewStrBuf();
67         curl_easy_setopt(curl, CURLOPT_WRITEDATA, ReplyBuf);
68         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlFillStrBuf_callback);
69         curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errmsg);
70         curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
71         curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errbuf);
72
73         pchs = strchr(remoteurl, ':');
74         pche = strchr(remoteurl, '@');
75         if ((pche != NULL) && 
76             (pchs != NULL) && 
77             (pchs < pche) && ((pche - pchs) < SIZ)) {
78                 memcpy(userpass, pchs + 3, pche - pchs - 3);
79                 
80                 userpass[pche - pchs - 3] = '\0';
81                 curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
82                 curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
83
84         }
85 #ifdef CURLOPT_HTTP_CONTENT_DECODING
86         curl_easy_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 1);
87         curl_easy_setopt(curl, CURLOPT_ENCODING, "");
88 #endif
89         curl_easy_setopt(curl, CURLOPT_USERAGENT, CITADEL);
90         curl_easy_setopt(curl, CURLOPT_TIMEOUT, 180);           /* die after 180 seconds */
91         if (!IsEmptyStr(config.c_ip_addr)) {
92                 curl_easy_setopt(curl, CURLOPT_INTERFACE, config.c_ip_addr);
93         }
94
95         headers = curl_slist_append(headers,"Accept: application/soap+xml, application/mime, multipart/related, text/*");
96         headers = curl_slist_append(headers,"Pragma: no-cache");
97
98         if (tlen > 0) {
99                 /* Load the template message. Get mallocs done too */
100                 FILE *Ftemplate = NULL;
101                 const char *mimetype;
102
103                 Ftemplate = fopen(template, "r");
104                 if (Ftemplate == NULL) {
105                         char buf[SIZ];
106
107                         snprintf(buf, SIZ, 
108                                  "Cannot load template file %s [%s]won't send notification\r\n", 
109                                  file_funambol_msg, strerror(errno));
110                         CtdlLogPrintf(CTDL_ERR, buf);
111
112                         aide_message(buf, "External notifier unable to find message template!");
113                         goto free;
114                 }
115                 mimetype = GuessMimeByFilename(template, tlen);
116
117                 snprintf(msgnumstr, 128, "%ld", MsgNum);
118
119                 buf = malloc(SIZ);
120                 memset(buf, 0, SIZ);
121                 SOAPMessage = malloc(3072);
122                 memset(SOAPMessage, 0, 3072);
123         
124                 while(fgets(buf, SIZ, Ftemplate) != NULL) {
125                         strcat(SOAPMessage, buf);
126                 }
127                 fclose(Ftemplate);
128         
129                 if (strlen(SOAPMessage) < 0) {
130                         char buf[SIZ];
131
132                         snprintf(buf, SIZ, 
133                                  "Cannot load template file %s; won't send notification\r\n", 
134                                  file_funambol_msg);
135                         CtdlLogPrintf(CTDL_ERR, buf);
136
137                         aide_message(buf, "External notifier unable to load message template!");
138                         goto free;
139                 }
140                 // Do substitutions
141                 help_subst(SOAPMessage, "^notifyuser", user);
142                 help_subst(SOAPMessage, "^syncsource", config.c_funambol_source);
143                 help_subst(SOAPMessage, "^msgid", msgid);
144                 help_subst(SOAPMessage, "^msgnum", msgnumstr);
145
146                 curl_easy_setopt(curl, CURLOPT_URL, remoteurl);
147
148                 /* pass our list of custom made headers */
149
150                 contenttype=(char*) malloc(40+strlen(mimetype));
151                 sprintf(contenttype,"Content-Type: %s; charset=utf-8", mimetype);
152
153                 headers = curl_slist_append(headers, "SOAPAction: \"\"");
154                 headers = curl_slist_append(headers, contenttype);
155
156                 /* Now specify the POST binary data */
157
158                 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, SOAPMessage);
159                 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(SOAPMessage));
160                 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
161         }
162         else {
163                 help_subst(remoteurl, "^notifyuser", user);
164                 help_subst(remoteurl, "^syncsource", config.c_funambol_source);
165                 help_subst(remoteurl, "^msgid", msgid);
166                 help_subst(remoteurl, "^msgnum", msgnumstr);
167                 curl_easy_setopt(curl, CURLOPT_URL, remoteurl);
168                 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
169         }
170
171         res = curl_easy_perform(curl);
172         if (res) {
173                 StrBuf *ErrMsg;
174
175                 CtdlLogPrintf(CTDL_ALERT, "libcurl error %d: %s\n", res, errmsg);
176                 ErrMsg = NewStrBufPlain(HKEY("Error sending your Notification\n"));
177                 StrBufAppendPrintf(ErrMsg, "\nlibcurl error %d: %s\n", res, errmsg);
178                 StrBufAppendBufPlain(ErrMsg, curl_errbuf, -1, 0);
179                 StrBufAppendBufPlain(ErrMsg, HKEY("\nWas Trying to send: \n"), 0);
180                 StrBufAppendBufPlain(ErrMsg, remoteurl, -1, 0);
181                 if (tlen > 0) {
182                         StrBufAppendBufPlain(ErrMsg, HKEY("\nThe Post document was: \n"), 0);
183                         StrBufAppendBufPlain(ErrMsg, SOAPMessage, -1, 0);
184                         StrBufAppendBufPlain(ErrMsg, HKEY("\n\n"), 0);                  
185                 }
186                 if (StrLength(ReplyBuf) > 0) {                  
187                         StrBufAppendBufPlain(ErrMsg, HKEY("\n\nThe Serverreply was: \n\n"), 0);
188                         StrBufAppendBuf(ErrMsg, ReplyBuf, 0);
189                 }
190                 else 
191                         StrBufAppendBufPlain(ErrMsg, HKEY("\n\nThere was no Serverreply.\n\n"), 0);
192                 ExtNotify_PutErrorMessage(Ctx, ErrMsg);
193         }
194
195         CtdlLogPrintf(CTDL_DEBUG, "Funambol notified\n");
196 free:
197         curl_slist_free_all (headers);
198         curl_easy_cleanup(curl);
199         if (contenttype) free(contenttype);
200         if (SOAPMessage != NULL) free(SOAPMessage);
201         if (buf != NULL) free(buf);
202         FreeStrBuf (&ReplyBuf);
203         return 0;
204 }