3 * @author Mathew McBride
5 * This module facilitates notifications to a Funambol server
8 * Based on bits of the previous serv_funambol
9 * Contact: <matt@mcbridematt.dhs.org> / <matt@comalies>
11 #include "extnotify.h"
16 #include <sys/socket.h>
18 #include <libcitadel.h>
21 #include <curl/curl.h>
24 #include "citadel_dirs.h"
25 #include "clientsocket.h"
28 #include "sysdep_decls.h"
30 #include "ctdl_module.h"
33 * \brief Sends a message to the Funambol server notifying
34 * of new mail for a user
35 * Returns 0 if unsuccessful
37 int notify_http_server(char *remoteurl,
38 const char* template, long tlen,
43 char curl_errbuf[CURL_ERROR_SIZE];
50 struct curl_slist * headers=NULL;
51 char errmsg[1024] = "";
52 char *SOAPMessage = NULL;
53 char *contenttype = NULL;
56 curl = curl_easy_init();
58 CtdlLogPrintf(CTDL_ALERT, "Unable to initialize libcurl.\n");
62 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
63 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
64 ReplyBuf = NewStrBuf();
65 curl_easy_setopt(curl, CURLOPT_WRITEDATA, ReplyBuf);
66 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlFillStrBuf_callback);
67 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errmsg);
68 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
69 curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errbuf);
71 pchs = strchr(remoteurl, ':');
72 pche = strchr(remoteurl, '@');
75 (pchs < pche) && ((pche - pchs) < SIZ)) {
76 memcpy(userpass, pchs + 3, pche - pchs - 3);
78 userpass[pche - pchs - 3] = '\0';
79 curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_BASIC);
80 curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
83 #ifdef CURLOPT_HTTP_CONTENT_DECODING
84 curl_easy_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 1);
85 curl_easy_setopt(curl, CURLOPT_ENCODING, "");
87 curl_easy_setopt(curl, CURLOPT_USERAGENT, CITADEL);
88 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 180); /* die after 180 seconds */
89 if (!IsEmptyStr(config.c_ip_addr)) {
90 curl_easy_setopt(curl, CURLOPT_INTERFACE, config.c_ip_addr);
93 headers = curl_slist_append(headers,"Accept: application/soap+xml, application/mime, multipart/related, text/*");
94 headers = curl_slist_append(headers,"Pragma: no-cache");
97 /* Load the template message. Get mallocs done too */
98 FILE *Ftemplate = NULL;
101 Ftemplate = fopen(template, "r");
102 if (Ftemplate == NULL) {
106 "Cannot load template file %s [%s]won't send notification\r\n",
107 file_funambol_msg, strerror(errno));
108 CtdlLogPrintf(CTDL_ERR, buf);
110 aide_message(buf, "External notifier unable to find message template!");
113 mimetype = GuessMimeByFilename(template, tlen);
115 snprintf(msgnumstr, 128, "%ld", MsgNum);
119 SOAPMessage = malloc(3072);
120 memset(SOAPMessage, 0, 3072);
122 while(fgets(buf, SIZ, Ftemplate) != NULL) {
123 strcat(SOAPMessage, buf);
127 if (strlen(SOAPMessage) < 0) {
131 "Cannot load template file %s; won't send notification\r\n",
133 CtdlLogPrintf(CTDL_ERR, buf);
135 aide_message(buf, "External notifier unable to load message template!");
139 help_subst(SOAPMessage, "^notifyuser", user);
140 help_subst(SOAPMessage, "^syncsource", config.c_funambol_source);
141 help_subst(SOAPMessage, "^msgid", msgid);
142 help_subst(SOAPMessage, "^msgnum", msgnumstr);
144 curl_easy_setopt(curl, CURLOPT_URL, remoteurl);
146 /* pass our list of custom made headers */
148 contenttype=(char*) malloc(40+strlen(mimetype));
149 sprintf(contenttype,"Content-Type: %s; charset=utf-8", mimetype);
151 headers = curl_slist_append(headers, "SOAPAction: \"\"");
152 headers = curl_slist_append(headers, contenttype);
154 /* Now specify the POST binary data */
156 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, SOAPMessage);
157 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(SOAPMessage));
158 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
161 help_subst(remoteurl, "^notifyuser", user);
162 help_subst(remoteurl, "^syncsource", config.c_funambol_source);
163 help_subst(remoteurl, "^msgid", msgid);
164 help_subst(remoteurl, "^msgnum", msgnumstr);
165 curl_easy_setopt(curl, CURLOPT_URL, remoteurl);
166 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
169 res = curl_easy_perform(curl);
173 CtdlLogPrintf(CTDL_ALERT, "libcurl error %d: %s\n", res, errmsg);
174 ErrMsg = NewStrBufPlain(HKEY("Error sending your Notification\n"));
175 StrBufAppendPrintf(ErrMsg, "\nlibcurl error %d: %s\n", res, errmsg);
176 StrBufAppendBufPlain(ErrMsg, curl_errbuf, -1, 0);
177 StrBufAppendBufPlain(ErrMsg, HKEY("\nWas Trying to send: \n"), 0);
178 StrBufAppendBufPlain(ErrMsg, remoteurl, -1, 0);
180 StrBufAppendBufPlain(ErrMsg, HKEY("\nThe Post document was: \n"), 0);
181 StrBufAppendBufPlain(ErrMsg, SOAPMessage, -1, 0);
182 StrBufAppendBufPlain(ErrMsg, HKEY("\n\n"), 0);
184 if (StrLength(ReplyBuf) > 0) {
185 StrBufAppendBufPlain(ErrMsg, HKEY("\n\nThe Serverreply was: \n\n"), 0);
186 StrBufAppendBuf(ErrMsg, ReplyBuf, 0);
189 StrBufAppendBufPlain(ErrMsg, HKEY("\n\nThere was no Serverreply.\n\n"), 0);
190 /* TODO: this will change the floor we're in :(
191 quickie_message("Citadel", NULL, NULL, AIDEROOM, ChrPtr(ErrMsg), FMT_FIXED,
192 "Failed to notify external service about inbound mail");
197 CtdlLogPrintf(CTDL_DEBUG, "Funambol notified\n");
199 curl_slist_free_all (headers);
200 curl_easy_cleanup(curl);
201 if (contenttype) free(contenttype);
202 if (SOAPMessage != NULL) free(SOAPMessage);
203 if (buf != NULL) free(buf);
204 FreeStrBuf (&ReplyBuf);