Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
ecd91bd3295bbaf53acc3985707e44f0494a4b13
[xestiacalendar/.git] / source / objects / CalDAV / CalDAV.cpp
1 // CalDAV.cpp - CalDAV Connection Object.
2 //
3 // (c) 2016-2017 Xestia Software Development.
4 //
5 // This file is part of Xestia Calendar.
6 //
7 // Xestia Calendar is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by the
9 // Free Software Foundation, version 3 of the license.
10 //
11 // Xestia Calendar is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with Xestia Calendar. If not, see <http://www.gnu.org/licenses/>
19 #include "CalDAV.h"
21 using namespace std;
23 size_t CalDAVReceive(char *receivedBuffer, size_t size, size_t newMemoryBytes, string *stringPointer)
24 {
25         
26         stringPointer->append(receivedBuffer, newMemoryBytes);
27         
28         return size * newMemoryBytes;
29         
30 }
32 size_t CalDAVSend(char *sendBuffer, size_t size, size_t newMemoryBytes, void *dataStruct){
34         struct CalDAVSendData *uploadPtr = (struct CalDAVSendData *)dataStruct;
35         
36         if (uploadPtr->sizeleft){
38                 uploadPtr->sizeleft--;
39                 char charSend;
41                 charSend = (*uploadPtr->readptr)[uploadPtr->seek];
42                 
43                 *sendBuffer = charSend;
44                 
45                 uploadPtr->seek++;
47                 return 1;
49         }
51         return 0;
53 }
55 CalDAV::CalDAV(){
57         // Setup the objects within the CalDAV connection 
58         // object.
59         
60         connectionHandle = curl_easy_init();
61         
62 }
64 CalDAV::~CalDAV(){
65         
66         // Destory the objects within the CalDAV connection
67         // object.
68         
69         curl_easy_cleanup(connectionHandle);
70         connectionHandle = nullptr;
71         
72 }
74 void CalDAV::SetupConnectionData(CalDAVConnectionData *connData){
75         
76         // Check if ConnData is a nullptr, return if it is.
77         
78         if (connData == nullptr){
79                 return;
80         }
81         
82         // Set the connection settings to the values from ConnData.
84         connectionData = (*connData);
85         
86 }
88 CalDAVStatus CalDAV::GetConnectionData(){
89         
90         // Get the current connection settings for the CalDAV
91         // connection object and return a CalDAVStatus object.
92         
93         CalDAVStatus connectionStatus;
94         
95         connectionStatus.hostname = connectionData.hostname;
96         connectionStatus.port = connectionData.port;
97         connectionStatus.username = connectionData.username;
98         connectionStatus.prefix = connectionData.prefix;
99         connectionStatus.useSSL = connectionData.useSSL;
100         connectionStatus.timeout = connectionData.timeout;
101         
102         return connectionStatus;
103         
106 CalDAVServerResult CalDAV::Connect(){
108         CalDAVServerResult serverResult;
110         string serverAddress = "";
111         string serverUserPass = "";
113         // Setup the server address.
114         
115         serverAddress = BuildServerAddress(&connectionData, "/principals/");
117         // Setup the server password.
118         
119         serverUserPass += connectionData.username;
120         serverUserPass += ":";
121         serverUserPass += connectionData.password;
122         
123         curl_easy_setopt(connectionHandle, CURLOPT_URL, serverAddress.c_str());
124         curl_easy_setopt(connectionHandle, CURLOPT_USERPWD, serverUserPass.c_str());
125         curl_easy_setopt(connectionHandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
126         curl_easy_setopt(connectionHandle, CURLOPT_FAILONERROR, 1L);
127         curl_easy_setopt(connectionHandle, CURLOPT_TIMEOUT, connectionData.timeout);
128         curl_easy_setopt(connectionHandle, CURLOPT_WRITEFUNCTION, CalDAVReceive);
129         curl_easy_setopt(connectionHandle, CURLOPT_WRITEDATA, &serverData);
130         curl_easy_setopt(connectionHandle, CURLOPT_WRITEHEADER, &serverHeader);
131         
132         // Connect to the CalDAV server.
133         
134         serverResult.code = curl_easy_perform(connectionHandle);
136         // Process the result received from the server.
137         
138         if (serverResult.code != CURLE_OK){
139                 
140                 serverResult.result = CALDAVQUERYRESULT_SERVERERROR;
141                 
142         } else {
143                 
144                 serverResult.result = CALDAVQUERYRESULT_OK;
145                 
146         }
147         
148         // Get the HTTP code.
149         
150         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &serverResult.httpCode);
151         
152         return serverResult;
153         
156 CalDAVServerResult CalDAV::GetServerResult(){
157         
158         return connectionServerResult;
159         
162 CalDAVServerSupport CalDAV::GetServerSupport(){
164         CalDAVServerSupport serverStatus;
165         
166         // Setup the server connection.
167         
168         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "OPTIONS");
169         
170         CURLcode serverResult = curl_easy_perform(connectionHandle);
171         
172         // Set the results.
173         
174         if (serverResult == CURLE_OK){
175                 connectionServerResult.result = CALDAVQUERYRESULT_OK;
176         } else {
177                 connectionServerResult.result = CALDAVQUERYRESULT_SERVERERROR;          
178         }
179         connectionServerResult.code = serverResult;
180         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &connectionServerResult.httpCode);
181         
182         if (serverResult != CURLE_OK){
183                 return serverStatus;
184         }
185         
186         // Check that the server header has data in,
187         // otherwise return an "empty" CalDAVServerSupport.
188         
189         if (serverHeader.size() == 0){
190                 return serverStatus;
191         }
192         
193         // Process each line looking for the first DAV header 
194         // line.
195         
196         bool newlineMode = true;
197         
198         string davLine;
199         
200         for (int charSeek = 0; charSeek < serverHeader.size(); charSeek++){
201                 
202                 if (newlineMode == true){
203                         
204                         // Check if we have reached the end of the string.
205                         
206                         if (charSeek >= serverHeader.size()){
207                                 
208                                 break;
209                                 
210                         }
211                         
212                         // Check the first four letters to make sure
213                         // they are 'DAV:'.
214                         
215                         string davHeaderCheck = "";
216                         
217                         try {
218                                 davHeaderCheck = serverHeader.substr(charSeek, 4);
219                         }
220                         
221                         catch (out_of_range &oor){
222                                 break;
223                         }
224                         
225                         if (davHeaderCheck == "DAV:"){
226                                 
227                                 charSeek += 5;
228                                 
229                                 for (; charSeek < serverHeader.size(); charSeek++){
230                                         
231                                         if (serverHeader[charSeek] == '\n'){
232                                         
233                                                 break;
234                                                 
235                                         }
236                                         
237                                         davLine.push_back(serverHeader[charSeek]);
238                                         
239                                 }
240                                 
241                                 break;
242                                 
243                         }
244                         
245                         newlineMode = false;
246                         
247                 }
248                 
249                 if (serverHeader[charSeek] == '\n'){
250                         
251                         newlineMode = true;
252                         
253                 }
254                 
255         }
256         
257         // Process the DAV line.
258         
259         vector<string> davLineData;
260         string davSegmentString;
261         
262         for (int charSeek = 0; charSeek < davLine.size(); charSeek++){
263                 
264                 if (davLine[charSeek] == ' '){
265                         continue;
266                 }
267                 
268                 if (davLine[charSeek] == ','){
269                         
270                         davLineData.push_back(davSegmentString);
271                         davSegmentString.clear();
272                         continue;
273                         
274                 }
275                 
276                 davSegmentString += davLine[charSeek];
277                 
278         }
279         
280         // Process the DAV values and set each value
281         // to true as required.
282         
283         for (int davItemSeek = 0; 
284                 davItemSeek < davLineData.size();
285                 davItemSeek++){
286                         
287                 if (davLineData.at(davItemSeek) == "calendar-access"){
288                         
289                         serverStatus.basicSupport = true;
290                 
291                 }
292                         
293         }
294         
295         // Reset the connection status.
296         
297         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);
298         
299         return serverStatus;
300         
303 string CalDAV::GetUserPrincipal(){
304         
305         string currentUserPrincipal = "";
306         string userPrincipalRequest = "";
307         CalDAVSendData userPrincipalSendData;
308         
309         userPrincipalRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
310         "<d:propfind xmlns:d=\"DAV:\">\n"
311         " <d:prop>\n"
312         "  <d:current-user-principal />\n"
313         " </d:prop>\n"
314         "</d:propfind>";
315         
316         userPrincipalSendData.readptr = &userPrincipalRequest;
317         userPrincipalSendData.sizeleft = userPrincipalRequest.size();
318         
319         // Setup the header.
320         
321         struct curl_slist *userPrincipalRequestHeader = NULL;
322         
323         userPrincipalRequestHeader = curl_slist_append(userPrincipalRequestHeader, "Depth: 0");
324         userPrincipalRequestHeader = curl_slist_append(userPrincipalRequestHeader, "Prefer: return-minimal");
325         userPrincipalRequestHeader = curl_slist_append(userPrincipalRequestHeader, "Content-Type: application/xml; charset=utf-8");
326         
327         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, userPrincipalRequestHeader);
329         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "PROPFIND");
330         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
331         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &userPrincipalSendData);
332         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
333         
334         // Process the data.
335         
336         serverData.clear();
337         serverHeader.clear();
338         
339         CURLcode serverResult = curl_easy_perform(connectionHandle);
340         
341         // Set the results.
342         
343         if (serverResult == CURLE_OK){
344                 connectionServerResult.result = CALDAVQUERYRESULT_OK;
345         } else {
346                 connectionServerResult.result = CALDAVQUERYRESULT_SERVERERROR;          
347         }
348         connectionServerResult.code = serverResult;
349         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &connectionServerResult.httpCode);
350         
351         if (serverResult != CURLE_OK){
352                 
353                 return currentUserPrincipal;
354                 
355         }
356         
357         // Process the User Principal from the ServerData.
359         currentUserPrincipal = ProcessXMLUserPrincipal();
360         
361         // Reset the changed settings.
362         
363         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
364         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
365         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
367         return currentUserPrincipal;
371 string CalDAV::GetCalendarHome(string userPrincipalURI){
372         
373         string calendarHomeURI = "";
375         // Build the Calendar Home URL address.
376         
377         string calendarHomeURL = BuildServerAddress(&connectionData, userPrincipalURI);
378         
379         // Setup the header request.
380         
381         CalDAVSendData calendarHomeSendData;
382         
383         string calendarHomeRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
384         "<d:propfind xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">\n"
385         " <d:prop>\n"
386         "  <c:calendar-home-set />\n"
387         " </d:prop>\n"
388         "</d:propfind>";
389         
390         calendarHomeSendData.readptr = &calendarHomeRequest;
391         calendarHomeSendData.sizeleft = calendarHomeRequest.size();
392         
393         // Setup the header.
394         
395         struct curl_slist *calendarRequestHeader = NULL;
396         
397         calendarRequestHeader = curl_slist_append(calendarRequestHeader, "Depth: 0");
398         calendarRequestHeader = curl_slist_append(calendarRequestHeader, "Prefer: return-minimal");
399         calendarRequestHeader = curl_slist_append(calendarRequestHeader, "Content-Type: application/xml; charset=utf-8");
400         
401         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, calendarRequestHeader);
402         curl_easy_setopt(connectionHandle, CURLOPT_URL, calendarHomeURL.c_str());
403         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "PROPFIND");
404         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
405         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &calendarHomeSendData);
406         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
407         
408         // Process the data.
409         
410         serverData.clear();
411         serverHeader.clear();
412         
413         CURLcode serverResult = curl_easy_perform(connectionHandle);
414         
415         // Set the results.
416         
417         if (serverResult == CURLE_OK){
418                 connectionServerResult.result = CALDAVQUERYRESULT_OK;
419         } else {
420                 connectionServerResult.result = CALDAVQUERYRESULT_SERVERERROR;          
421         }
422         connectionServerResult.code = serverResult;
423         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &connectionServerResult.httpCode);
424         
425         if (serverResult != CURLE_OK){
426                 
427                 return calendarHomeURI;
428                 
429         }
430         
431         // Process the User Principal from the ServerData.
433         calendarHomeURI = ProcessXMLCalendarHome();
434         
435         // Reset the changed settings.
436         
437         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
438         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
439         
440         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
441         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
442         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
443         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, NULL);
444         
445         return calendarHomeURI;
446         
449 CalDAVCalendarList CalDAV::GetCalendars(){
450         
451         CalDAVCalendarList serverList;
452         CalDAVSendData calendarListSendData;
453         
454         // Build the server address.
455         
456         string userPrincipalURI = "";
457         userPrincipalURI = GetUserPrincipal();
458         
459         if (userPrincipalURI.size() == 0){
460                 
461                 return serverList;
462                 
463         }
464         
465         string calendarHomeURI = "";
466         calendarHomeURI = GetCalendarHome(userPrincipalURI);
467         
468         string calendarListURLAddress = BuildServerAddress(&connectionData, calendarHomeURI);
469         
470         string calendarListRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
471         "<d:propfind xmlns:d=\"DAV:\" xmlns:cs=\"http://calendarserver.org/ns/\""
472         " xmlns:c=\"urn:ietf:params:xml:ns:caldav\" xmlns:x0=\"http://apple.com/ns/ical/\">\n"
473         " <d:prop>\n"
474         "  <d:resourcetype />\n"
475         "  <d:displayname />\n"
476         "  <d:sync-token />\n"
477         "  <x0:calendar-color />\n"
478         "  <x0:calendar-order />\n"
479         "  <cs:getctag />\n"
480         "  <c:supported-calendar-component-set />\n"
481         "  <c:calendar-description />\n"
482         " </d:prop>\n"
483         "</d:propfind>";
484         
485         calendarListSendData.readptr = &calendarListRequest;
486         calendarListSendData.sizeleft = calendarListRequest.size();
487         
488         // Setup the header.
489         
490         struct curl_slist *calendarListRequestHeader = NULL;
491         
492         calendarListRequestHeader = curl_slist_append(calendarListRequestHeader, "Depth: 1");
493         calendarListRequestHeader = curl_slist_append(calendarListRequestHeader, "Prefer: return-minimal");
494         calendarListRequestHeader = curl_slist_append(calendarListRequestHeader, "Content-Type: application/xml; charset=utf-8");
495         
496         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, calendarListRequestHeader);
497         curl_easy_setopt(connectionHandle, CURLOPT_URL, calendarListURLAddress.c_str());
498         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "PROPFIND");
499         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
500         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &calendarListSendData);
501         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
502         
503         // Process the data.
504         
505         serverData.clear();
506         serverHeader.clear();
507         
508         CURLcode serverResult = curl_easy_perform(connectionHandle);
509         
510         //ServerList = ProcessXMLCalendarList();
511         
512         if (serverResult == CURLE_OK){
513                 connectionServerResult.result = CALDAVQUERYRESULT_OK;
514         } else {
515                 connectionServerResult.result = CALDAVQUERYRESULT_SERVERERROR;          
516         }
517         connectionServerResult.code = serverResult;
518         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &connectionServerResult.httpCode);
519         
520         if (serverResult != CURLE_OK){
521                 
522                 return serverList;
523                 
524         }
525         
526         // Process the received XML data into a list of calendars
527         // and locations.
528         
529         serverList = ProcessXMLCalendarList();
530         
531         // Restore the original settings.
532         
533         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
534         
535         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
536         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
537         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
538         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
539         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
540         
541         return serverList;
542         
545 CalDAVEntryList CalDAV::GetEntryList(string *calendarHREF){
546         
547         CalDAVEntryList entryList;
548         CalDAVSendData entryListSendData;
549         
550         if (calendarHREF->size() == 0){
551                 
552                 return entryList;
553                 
554         }
555         
556         string entryListURLAddress = BuildServerAddress(&connectionData, *calendarHREF);
557         
558         string entryListRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
559         
560         /*if (CalendarTag == nullptr){*/
561                 
562         entryListRequest += "<c:calendar-query xmlns:d=\"DAV:\" xmlns:cs=\"http://calendarserver.org/ns/\""
563         " xmlns:c=\"urn:ietf:params:xml:ns:caldav\" xmlns:x0=\"http://apple.com/ns/ical/\">\n"
564         " <d:prop>\n"
565         "  <d:getetag />\n"
566         "  <c:calendar-data />\n"
567         " </d:prop>\n"
568         " <c:filter>\n"
569         "  <c:comp-filter name=\"VCALENDAR\" />\n"
570         " </c:filter>\n"
571         "</c:calendar-query>";
572                 
573         /*} else {
575                 EntryListRequest += "<d:sync-collection xmlns:d=\"DAV:\" xmlns:cs=\"http://calendarserver.org/ns/\""
576                 " xmlns:c=\"urn:ietf:params:xml:ns:caldav\" xmlns:x0=\"http://apple.com/ns/ical/\">\n"          
577                 " <d:sync-token>";
578                 EntryListRequest += *CalendarTag;
579                 EntryListRequest += "</d:sync-token>\n"
580                 " <d:sync-level>1</d:sync-level>\n"
581                 " <d:prop>\n"
582                 "  <d:getetag />\n"
583                 "  <c:calendar-data />\n"
584                 " </d:prop>\n"
585                 "</d:sync-collection>";
586                 
587         }*/
588         
589         entryListSendData.readptr = &entryListRequest;
590         entryListSendData.sizeleft = entryListRequest.size();
591         
592         struct curl_slist *entryListRequestHeader = NULL;
593         
594         entryListRequestHeader = curl_slist_append(entryListRequestHeader, "Content-Type: application/xml; charset=utf-8");
595         
596         /*if (CalendarTag != nullptr){
597         
598                 EntryListRequestHeader = curl_slist_append(EntryListRequestHeader, "Content-Type: application/xml; charset=utf-8");
599                 EntryListRequestHeader = curl_slist_append(EntryListRequestHeader, "Content-Type: application/xml; charset=utf-8");
600                 
601         }*/
602         
603         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, entryListRequestHeader);
604         curl_easy_setopt(connectionHandle, CURLOPT_URL, entryListURLAddress.c_str());
605         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "REPORT");
606         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
607         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &entryListSendData);
608         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
609         
610         // Process the data.
611         
612         serverData.clear();
613         serverHeader.clear();
614         
615         CURLcode serverResult = curl_easy_perform(connectionHandle);
616         
617         //ServerList = ProcessXMLCalendarList();
618         
619         if (serverResult == CURLE_OK){
620                 connectionServerResult.result = CALDAVQUERYRESULT_OK;
621         } else {
622                 connectionServerResult.result = CALDAVQUERYRESULT_SERVERERROR;          
623         }
624         connectionServerResult.code = serverResult;
625         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &connectionServerResult.httpCode);
626         
627         if (serverResult != CURLE_OK){
628                 
629                 return entryList;
630                 
631         }
632         
633         // Process the received XML data into a list of calendars
634         // and locations.
635         
636         entryList = ProcessXMLEntryList();
637         
638         // Restore the original settings.
639         
640         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
641         
642         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
643         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
644         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
645         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
646         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
647         
648         return entryList;
649         
652 CalDAVEntryList CalDAV::GetEntryList(string *calendarHREF, string *calendarTag){
653         
654         CalDAVEntryList entryList;
655         CalDAVSendData entryListSendData;
656         
657         if (calendarHREF->size() == 0){
658                 
659                 return entryList;
660                 
661         }
662         
663         string entryListURLAddress = BuildServerAddress(&connectionData, *calendarHREF);
664         
665         // First query: Get the list of contacts that need to be updated.
666         
667         string entryListRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
669         entryListRequest += "<d:sync-collection xmlns:d=\"DAV:\" xmlns:cs=\"http://calendarserver.org/ns/\""
670         " xmlns:c=\"urn:ietf:params:xml:ns:caldav\" xmlns:x0=\"http://apple.com/ns/ical/\">\n"
671         " <d:sync-token>";
672         
673         if (calendarTag != nullptr){
674         
675                 entryListRequest += *calendarTag;
676                 
677         } else {
678         
679                 entryListRequest += "";
680                 
681         }
683         entryListRequest += "</d:sync-token>\n"
684         " <d:sync-level>1</d:sync-level>\n"
685         " <d:prop>\n"
686         "  <d:getetag />\n"
687         " </d:prop>\n"
688         "</d:sync-collection>";
689         
690         entryListSendData.readptr = &entryListRequest;
691         entryListSendData.sizeleft = entryListRequest.size();
692         
693         struct curl_slist *entryListRequestHeader = NULL;
694         
695         entryListRequestHeader = curl_slist_append(entryListRequestHeader, "Content-Type: application/xml; charset=utf-8");
696         
697         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, entryListRequestHeader);
698         curl_easy_setopt(connectionHandle, CURLOPT_URL, entryListURLAddress.c_str());
699         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "REPORT");
700         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
701         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &entryListSendData);
702         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
703         
704         // Process the data.
705         
706         serverData.clear();
707         serverHeader.clear();
708         
709         CURLcode serverResult = curl_easy_perform(connectionHandle);
710         
711         if (serverResult == CURLE_OK){
712                 connectionServerResult.result = CALDAVQUERYRESULT_OK;
713         } else {
714                 connectionServerResult.result = CALDAVQUERYRESULT_SERVERERROR;          
715         }
716         connectionServerResult.code = serverResult;
717         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &connectionServerResult.httpCode);
718         
719         if (serverResult != CURLE_OK){
720                 
721                 return entryList;
722                 
723         }
724         
725         entryList = ProcessXMLSyncTokenList();
726         
727         // Check the last entry matches the HREF and if it 
728         // does then delete it.
729         
730         if (entryList.href.size() > 0) {
731         
732                 if (entryList.href.rbegin()->second == *calendarHREF){
733                         
734                         entryList.href.erase((entryList.href.size() - 1));
735                         entryList.tag.erase((entryList.href.size() - 1));
736                         entryList.data.erase((entryList.href.size() - 1));
737                 
738                 }
739         
740         }
741         
742         // Build the list into a new list for getting the new 
743         // calendar data with.
744         
745         entryListRequest.clear();
746         
747         entryListRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
749         entryListRequest += "<c:calendar-multiget xmlns:d=\"DAV:\" "
750         " xmlns:c=\"urn:ietf:params:xml:ns:caldav\">\n"
751         " <d:prop>\n"
752         "  <d:getetag />\n"
753         "  <c:calendar-data />\n"
754         " </d:prop>\n";
755         
756         for (std::map<int,string>::iterator hrefIter = entryList.href.begin(); 
757                 hrefIter != entryList.href.end(); hrefIter++){
758                 
759                 string entryListHREFString = hrefIter->second;
760                         
761                 entryListRequest += " <d:href>";
762                 entryListRequest += entryListHREFString;
763                 entryListRequest += "</d:href>\n";
764                         
765         }
766         
767         entryListRequest += "</c:calendar-multiget>";
768         
769         CalDAVSendData updatedEntryListSendData;        
770         
771         updatedEntryListSendData.readptr = &entryListRequest;
772         updatedEntryListSendData.sizeleft = entryListRequest.size();
773         
774         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, entryListRequestHeader);
775         curl_easy_setopt(connectionHandle, CURLOPT_URL, entryListURLAddress.c_str());
776         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "REPORT");
777         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
778         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &updatedEntryListSendData);
779         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
780         
781         // Get the updated calendar data.
782         
783         serverData.clear();
784         serverHeader.clear();
785         entryList.href.clear();
786         entryList.tag.clear();
787         entryList.data.clear();
788         
789         serverResult = curl_easy_perform(connectionHandle);
791         // Check the last entry matches the HREF and if it 
792         // does then delete it.
793         
794         if (serverResult == CURLE_OK){
795                 connectionServerResult.result = CALDAVQUERYRESULT_OK;
796         } else {
797                 connectionServerResult.result = CALDAVQUERYRESULT_SERVERERROR;          
798         }
799         connectionServerResult.code = serverResult;
800         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &connectionServerResult.httpCode);
801         
802         if (serverResult != CURLE_OK){
803                 
804                 return entryList;
805                 
806         }
807         
808         entryList = ProcessXMLEntryList();
809         
810         // Second query: Get the list of contact data for the contacts that have
811         // beenchanged.
812         
813         // Restore the original settings.
814         
815         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
816         
817         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
818         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
819         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
820         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
821         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
822         
823         return entryList;
824         
827 CalDAVServerResult CalDAV::AddCalendar(string calendarName){
828         
829         CalDAVServerResult serverResult;
830         
831         AddCalendar(&calendarName, nullptr);
832         
833         return serverResult;
834         
837 CalDAVServerResult CalDAV::AddCalendar(string *calendarName, string *calendarShortName){
838         
839         CalDAVServerResult serverResult;
840         CalDAVSendData calendarAddSendData;
841         
842         // Build the server address.
843         
844         string userPrincipalURI = "";
845         userPrincipalURI = GetUserPrincipal();
846         
847         if (userPrincipalURI.size() == 0){
848                 
849                 return serverResult;
850                 
851         }
852         
853         string calendarHomeURI = "";
854         calendarHomeURI = GetCalendarHome(userPrincipalURI);
855         
856         // Generate the UUID.
857         
858         string UUIDValue = "";
859         
860         if (calendarShortName == nullptr){
861         
862                 UUIDValue = GenerateUUID();
863                 UUIDValue.erase(UUIDValue.end()-1);
865         } else {
866         
867                 UUIDValue = *calendarShortName;
868                 
869         }
870                 
871         string calendarHomeURL = calendarHomeURI;
872         calendarHomeURL.append(UUIDValue);
873         calendarHomeURL.append("/");
874         
875         // Build the calendar list address.
876         
877         string calendarListURLAddress = BuildServerAddress(&connectionData, calendarHomeURL);
878         
879         string calendarAddRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
880         "<c:mkcalendar xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">\n"
881         " <d:set>\n"
882         "  <d:prop>\n"
883         "   <d:displayname>";
884         calendarAddRequest += *calendarName;
885         calendarAddRequest += "</d:displayname>\n"
886         "   <c:supported-calendar-component-set>\n"
887         "    <c:comp name=\"VTODO\"/>\n"
888         "    <c:comp name=\"VEVENT\"/>\n"
889         "   </c:supported-calendar-component-set>\n"
890         "  </d:prop>\n"
891         " </d:set>\n"
892         "</c:mkcalendar>";
893         
894         calendarAddSendData.readptr = &calendarAddRequest;
895         calendarAddSendData.sizeleft = calendarAddRequest.size();
896         
897         // Setup the header.
898         
899         struct curl_slist *calendarRequestHeader = NULL;
900         
901         //curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, CalendarRequestHeader);
902         curl_easy_setopt(connectionHandle, CURLOPT_URL, calendarListURLAddress.c_str());
903         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "MKCALENDAR");
904         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
905         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &calendarAddSendData);
906         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
907         
908         // Process the data.
909         
910         serverData.clear();
911         serverHeader.clear();
912         
913         CURLcode serverConnectionResult = curl_easy_perform(connectionHandle);
914         
915         if (serverConnectionResult == CURLE_OK){
916                 serverResult.result = CALDAVQUERYRESULT_OK;
917         } else {
918                 serverResult.result = CALDAVQUERYRESULT_SERVERERROR;            
919         }
920         serverResult.code = serverConnectionResult;
921         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &serverResult.httpCode);
922         
923         // Restore the original settings.
924         
925         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
926         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
927         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
928         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
929         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
930         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
931         
932         return serverResult;
933         
936 CalDAVServerResult CalDAV::EditCalendarProcess(string *calendarHREF,
937                         string *calendarName,
938                         Colour *calendarColour,
939                         string *calendarDescription,
940                         int *calendarOrder){
942         CalDAVServerResult serverResult;
943         CalDAVSendData calendarEditSendData;
944         
945         // Build the server address.
946         
947         string userPrincipalURI = "";
948         userPrincipalURI = GetUserPrincipal();
949         
950         if (userPrincipalURI.size() == 0){
951                 
952                 return serverResult;
953                 
954         }
955         
956         string calendarHomeURI = "";
957         calendarHomeURI = GetCalendarHome(userPrincipalURI);
958         
959         // Generate the UUID.
960         
961         string UUIDValue = GenerateUUID();
962         UUIDValue.erase(UUIDValue.end()-1);
963         
964         string calendarHomeURL = calendarHomeURI;
965         calendarHomeURL.append(UUIDValue);
966         calendarHomeURL.append("/");
967         
968         // Build the calendar list address.
969         
970         string calendarEditURLAddress = BuildServerAddress(&connectionData, (*calendarHREF));
971         
972         string calendarEditRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
973         "<d:propertyupdate xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\"\n"
974         "       xmlns:x0=\"http://apple.com/ns/ical/\">\n"
975         " <d:set>\n"
976         "  <d:prop>\n";
977         
978         // Update the calendar name.
979         
980         if (calendarName != nullptr){
981         
982                 calendarEditRequest += "<d:displayname>";
983                 calendarEditRequest += (*calendarName);
984                 calendarEditRequest += "</d:displayname>\n";
985                 
986         }
987         
988         // Update the calendar colour.
989         
990         if (calendarColour != nullptr){
991                 
992                 calendarEditRequest += "<x0:calendar-color>";
993                 calendarEditRequest += (*calendarColour);
994                 calendarEditRequest += "</x0:calendar-color>\n";
995                 
996         }
997         
998         // Update the calendar description.
999         
1000         if (calendarDescription != nullptr){
1001                 
1002                 calendarEditRequest += "<c:calendar-description>";
1003                 calendarEditRequest += (*calendarDescription);
1004                 calendarEditRequest += "</c:calendar-description>\n";           
1005                 
1006         }
1007         
1008         // Update the calendar order.
1009         
1010         if (calendarOrder != nullptr){
1011                 
1012                 calendarEditRequest += "<x0:calendar-order>";
1013                 calendarEditRequest += to_string((*calendarOrder));
1014                 calendarEditRequest += "</x0:calendar-order>\n";
1015                 
1016         }
1017         
1018         calendarEditRequest += "  </d:prop>\n"
1019         " </d:set>\n"
1020         "</d:propertyupdate>";
1021         
1022         calendarEditSendData.readptr = &calendarEditRequest;
1023         calendarEditSendData.sizeleft = calendarEditRequest.size();
1024         
1025         // Setup the header.
1026         
1027         struct curl_slist *calendarRequestHeader = NULL;
1028         
1029         //curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, CalendarRequestHeader);
1030         curl_easy_setopt(connectionHandle, CURLOPT_URL, calendarEditURLAddress.c_str());
1031         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "PROPPATCH");
1032         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
1033         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &calendarEditSendData);
1034         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
1035         
1036         // Process the data.
1037         
1038         serverData.clear();
1039         serverHeader.clear();
1040         
1041         CURLcode serverConnectionResult = curl_easy_perform(connectionHandle);
1042         
1043         if (serverConnectionResult == CURLE_OK){
1044                 serverResult.result = CALDAVQUERYRESULT_OK;
1045         } else {
1046                 serverResult.result = CALDAVQUERYRESULT_SERVERERROR;            
1047         }
1048         serverResult.code = serverConnectionResult;
1049         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &serverResult.httpCode);
1050         
1051         // Restore the original settings.
1052         
1053         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
1054         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
1055         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1056         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
1057         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
1058         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
1059         
1060         return serverResult;
1064 CalDAVServerResult CalDAV::EditCalendar(string *calendarHREF,
1065                         string *calendarName,
1066                         Colour *calendarColour,
1067                         string *calendarDescription,
1068                         int *calendarOrder){
1069         
1070         CalDAVServerResult serverResult;
1071         
1072         serverResult = EditCalendarProcess(calendarHREF,
1073                 calendarName,
1074                 calendarColour,
1075                 calendarDescription,
1076                 calendarOrder);
1077                                 
1078         return serverResult;
1079         
1082 CalDAVServerResult CalDAV::EditCalendar(string *calendarHREF,
1083                         Colour *calendarColour){
1085         CalDAVServerResult serverResult;
1087         serverResult = EditCalendarProcess(calendarHREF,
1088                 nullptr,
1089                 calendarColour,
1090                 nullptr,
1091                 nullptr);
1092                                 
1093         return serverResult;    
1094         
1097 CalDAVServerResult CalDAV::EditCalendar(string *calendarHREF,
1098                         string *calendarName){
1099         
1100         CalDAVServerResult serverResult;
1101         
1102         serverResult = EditCalendarProcess(calendarHREF,
1103                 calendarName,
1104                 nullptr,
1105                 nullptr,
1106                 nullptr);       
1107         
1108         return serverResult;
1109         
1112 CalDAVServerResult CalDAV::EditCalendar(string *calendarHREF,
1113                         int *calendarOrder){
1114         
1115         CalDAVServerResult serverResult;
1116         
1117         serverResult = EditCalendarProcess(calendarHREF,
1118                 nullptr,
1119                 nullptr,
1120                 nullptr,
1121                 calendarOrder);
1122         
1123         return serverResult;
1124         
1127 CalDAVServerResult CalDAV::EditCalendarDescription(string *calendarHREF,
1128                         string *calendarDescription){
1129         
1130         CalDAVServerResult serverResult;
1131         
1132         serverResult = EditCalendarProcess(calendarHREF,
1133                 nullptr,
1134                 nullptr,
1135                 calendarDescription,
1136                 nullptr);
1137         
1138         return serverResult;
1139         
1142 CalDAVServerResult CalDAV::DeleteCalendar(string *calendarHREF){
1144         CalDAVServerResult serverResult;
1145         
1146         // Build the server address.
1147         
1148         string userPrincipalURI = "";
1149         userPrincipalURI = GetUserPrincipal();
1150         
1151         if (userPrincipalURI.size() == 0){
1152                 
1153                 return serverResult;
1154                 
1155         }
1156         
1157         string calendarHomeURI = "";
1158         calendarHomeURI = GetCalendarHome(userPrincipalURI);
1159         
1160         // Generate the UUID.
1161         
1162         string UUIDValue = GenerateUUID();
1163         UUIDValue.erase(UUIDValue.end()-1);
1164         
1165         string calendarHomeURL = calendarHomeURI;
1166         calendarHomeURL.append(UUIDValue);
1167         calendarHomeURL.append("/");
1168         
1169         // Build the calendar list address.
1170         
1171         struct curl_slist *deleteRequestHeader = NULL;
1172         
1173         deleteRequestHeader = curl_slist_append(deleteRequestHeader, "Depth: infinity");
1174         
1175         string calendarDeleteURLAddress = BuildServerAddress(&connectionData, (*calendarHREF));
1176         
1177         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, deleteRequestHeader);
1178         curl_easy_setopt(connectionHandle, CURLOPT_URL, calendarDeleteURLAddress.c_str());
1179         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
1180         
1181         // Delete the calendar.
1182         
1183         serverData.clear();
1184         serverHeader.clear();
1185         
1186         CURLcode serverConnectionResult = curl_easy_perform(connectionHandle);
1187         
1188         if (serverConnectionResult == CURLE_OK){
1189                 serverResult.result = CALDAVQUERYRESULT_OK;
1190         } else {
1191                 serverResult.result = CALDAVQUERYRESULT_SERVERERROR;            
1192         }
1193         serverResult.code = serverConnectionResult;
1194         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &serverResult.httpCode);
1195         
1196         // Restore the original settings.
1197         
1198         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
1199         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
1200         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1201         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
1202         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
1203         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
1204         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, NULL);
1205         
1206         return serverResult;
1207         
1210 CalDAVServerResult CalDAV::GetEntryETag(string *calendarEntryHREF, string *eTagValue){
1211         
1212         CalDAVServerResult serverResult;
1213         CalDAVSendData entryETagGetData;
1214         
1215         // Build the server address.
1216         
1217         string userPrincipalURI = "";
1218         userPrincipalURI = GetUserPrincipal();
1219         
1220         if (userPrincipalURI.size() == 0){
1221                 
1222                 return serverResult;
1223                 
1224         }
1225         
1226         string calendarHomeURI = "";
1227         calendarHomeURI = GetCalendarHome(userPrincipalURI);
1229         // Split the path and filename.
1230         
1231         string entryURIPath;
1232         string entryFilename;
1233         
1234         SplitPathFilename(calendarEntryHREF, &entryURIPath, &entryFilename);
1235         
1236         // Build the request for the server.
1238         string entryETagRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1239         "<c:calendar-multiget xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">\n"
1240         " <d:prop>\n"
1241         "  <d:getetag />\n"
1242         " </d:prop>\n"
1243         " <d:href>";
1244         entryETagRequest += (*calendarEntryHREF);
1245         entryETagRequest += "</d:href>\n"
1246         "</c:calendar-multiget>";
1247         
1248         entryETagGetData.readptr = &entryETagRequest;
1249         entryETagGetData.sizeleft = entryETagRequest.size();
1250         
1251         // Build the calendar list address.
1252         
1253         struct curl_slist *getETagRequestHeader = NULL;
1255         getETagRequestHeader = curl_slist_append(getETagRequestHeader, "Depth: 1");     
1256         getETagRequestHeader = curl_slist_append(getETagRequestHeader, "Prefer: return-minimal");
1257         getETagRequestHeader = curl_slist_append(getETagRequestHeader, "Content-Type: application/xml; charset=utf-8");
1258         
1259         string getETagURLAddress = BuildServerAddress(&connectionData, entryURIPath);
1260         
1261         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, getETagRequestHeader);
1262         curl_easy_setopt(connectionHandle, CURLOPT_URL, getETagURLAddress.c_str());
1263         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "REPORT");
1264         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
1265         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &entryETagGetData);
1266         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
1267         
1268         // Attempt to get the entity tag.
1269         
1270         serverData.clear();
1271         serverHeader.clear();
1272         
1273         CURLcode serverConnectionResult = curl_easy_perform(connectionHandle);
1274         
1275         if (serverConnectionResult == CURLE_OK){
1276                 serverResult.result = CALDAVQUERYRESULT_OK;
1277         } else {
1278                 serverResult.result = CALDAVQUERYRESULT_SERVERERROR;            
1279         }
1280         serverResult.code = serverConnectionResult;
1281         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &serverResult.httpCode);
1282         
1283         if (serverConnectionResult != CURLE_OK){
1284                 return serverResult;
1285         }
1286         
1287         // Get the entity tag from the result.
1288         
1289         *eTagValue = ProcessXMLEntryETag();
1290         
1291         // Restore the original settings.
1292         
1293         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
1294         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
1295         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1296         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
1297         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
1298         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
1299         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, NULL);
1300         
1301         return serverResult;
1302         
1305 CalDAVServerResult CalDAV::AddEntry(string *calendarEntryHREF, string *entryData){
1306         
1307         // Add an entry to the calendar collection.
1308         
1309         CalDAVServerResult serverResult;
1310         CalDAVSendData entryAddSendData;
1311         
1312         // Build the calendar list address.
1313         
1314         string entryAddURLAddress = BuildServerAddress(&connectionData, (*calendarEntryHREF));
1315         
1316         entryAddSendData.readptr = entryData;
1317         entryAddSendData.sizeleft = entryData->size();
1318         
1319         struct curl_slist *calendarRequestHeader = NULL;
1320         
1321         calendarRequestHeader = curl_slist_append(calendarRequestHeader, "Content-Type: text/calendar; charset=utf-8");
1322         
1323         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, calendarRequestHeader);
1324         curl_easy_setopt(connectionHandle, CURLOPT_URL, entryAddURLAddress.c_str());
1325         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "PUT");
1326         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
1327         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &entryAddSendData);
1328         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
1329         
1330         // Process the data.
1331         
1332         serverData.clear();
1333         serverHeader.clear();
1334         
1335         CURLcode serverConnectionResult = curl_easy_perform(connectionHandle);
1336         
1337         if (serverConnectionResult == CURLE_OK){
1338                 serverResult.result = CALDAVQUERYRESULT_OK;
1339         } else {
1340                 serverResult.result = CALDAVQUERYRESULT_SERVERERROR;            
1341         }
1342         serverResult.code = serverConnectionResult;
1343         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &serverResult.httpCode);
1344         
1345         // Restore the original settings.
1346         
1347         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
1348         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
1349         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1350         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
1351         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
1352         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
1353         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, NULL);
1354         
1355         return serverResult;
1356         
1359 CalDAVServerResult CalDAV::EditEntry(string *calendarEntryHREF, string *entryData, string *entryETag){
1360         
1361         // Edit an entry in the calendar collection.
1363         // Add an entry to the calendar collection.
1364         
1365         CalDAVServerResult serverResult;
1366         CalDAVSendData entryAddSendData;
1367         
1368         // Build the calendar list address.
1369         
1370         string entryAddURLAddress = BuildServerAddress(&connectionData, (*calendarEntryHREF));
1371         
1372         entryAddSendData.readptr = entryData;
1373         entryAddSendData.sizeleft = entryData->size();
1374         
1375         string ifMatchHeader = "If-Match: \"";
1376         ifMatchHeader.append(*entryETag);
1377         ifMatchHeader.append("\"");
1378         
1379         struct curl_slist *calendarRequestHeader = NULL;
1380         
1381         calendarRequestHeader = curl_slist_append(calendarRequestHeader, "Content-Type: text/calendar; charset=utf-8");
1382         calendarRequestHeader = curl_slist_append(calendarRequestHeader, ifMatchHeader.c_str());        
1383         
1384         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, calendarRequestHeader);
1385         curl_easy_setopt(connectionHandle, CURLOPT_URL, entryAddURLAddress.c_str());
1386         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "PUT");
1387         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 1L);
1388         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, &entryAddSendData);
1389         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
1390         
1391         // Process the data.
1392         
1393         serverData.clear();
1394         serverHeader.clear();
1395         
1396         CURLcode serverConnectionResult = curl_easy_perform(connectionHandle);
1397         
1398         if (serverConnectionResult == CURLE_OK){
1399                 serverResult.result = CALDAVQUERYRESULT_OK;
1400         } else {
1401                 serverResult.result = CALDAVQUERYRESULT_SERVERERROR;            
1402         }
1403         serverResult.code = serverConnectionResult;
1404         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &serverResult.httpCode);
1405         
1406         // Restore the original settings.
1407         
1408         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
1409         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
1410         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1411         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
1412         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
1413         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
1414         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, NULL);
1415         
1416         return serverResult;
1417         
1420 CalDAVServerResult CalDAV::DeleteEntry(string *calendarEntryHREF){
1421         
1422         // Delete an entry in the calendar collection.
1423         
1424         CalDAVServerResult serverResult;
1425         
1426         // Build the calendar list address.
1427         
1428         string entryDeleteURLAddress = BuildServerAddress(&connectionData, (*calendarEntryHREF));
1429         
1430         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, NULL);
1431         curl_easy_setopt(connectionHandle, CURLOPT_URL, entryDeleteURLAddress.c_str());
1432         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
1433         
1434         // Delete the calendar.
1435         
1436         serverData.clear();
1437         serverHeader.clear();
1438         
1439         CURLcode serverConnectionResult = curl_easy_perform(connectionHandle);
1440         
1441         if (serverConnectionResult == CURLE_OK){
1442                 serverResult.result = CALDAVQUERYRESULT_OK;
1443         } else {
1444                 serverResult.result = CALDAVQUERYRESULT_SERVERERROR;            
1445         }
1446         serverResult.code = serverConnectionResult;
1447         curl_easy_getinfo(connectionHandle, CURLINFO_RESPONSE_CODE, &serverResult.httpCode);
1448         
1449         // Restore the original settings.
1450         
1451         string originalServerAddress = BuildServerAddress(&connectionData, "/principals/");
1452         curl_easy_setopt(connectionHandle, CURLOPT_URL, originalServerAddress.c_str());
1453         curl_easy_setopt(connectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1454         curl_easy_setopt(connectionHandle, CURLOPT_UPLOAD, 0L);
1455         curl_easy_setopt(connectionHandle, CURLOPT_READDATA, NULL);
1456         curl_easy_setopt(connectionHandle, CURLOPT_READFUNCTION, NULL);
1457         curl_easy_setopt(connectionHandle, CURLOPT_HTTPHEADER, NULL);
1458         
1459         return serverResult;
1460         
1463 bool CalDAVObjectValidSettings(CalDAVConnectionData *connData){
1465         // Check if the passed CalDAV Connection Data is has
1466         // an address set. Return false if nullptr is used.
1468         if (connData == nullptr){
1469         
1470                 return false;
1471         
1472         }
1473         
1474         // Check the server hostname. Return false
1475         // if no value has been set.
1476         
1477         if (connData->hostname.size() == 0){
1478         
1479                 return false;
1480         
1481         }
1482         
1483         // Check the server port. Return false if
1484         // no value has been set or the port number
1485         // is less than 1 or higher than 65535.
1486         
1487         if (connData->port < 1 || connData->port > 65535){
1488         
1489                 return false;
1490         
1491         }
1492         
1493         // Check the server username. Return false
1494         // if no value has been set.
1495         
1496         if (connData->username.size() == 0){
1497                 
1498                 return false;
1499                 
1500         }       
1501         
1502         // Check the server password. Return false
1503         // if no value has been set.
1504         
1505         if (connData->password.size() == 0){
1506                 
1507                 return false;
1508                 
1509         }
1511         // Cannot check UseSSL: It is either true
1512         // or false.
1513         
1514         // Cannot check Prefix: The prefix may need
1515         // to be worked out first.
1517         // No errors were found whilst checking so
1518         // return true.
1519         
1520         return true;
1524 string BuildServerAddress(CalDAVConnectionData *connData, string uriAddress){
1525         
1526         string serverAddress;
1527         
1528         // Setup the server address.
1529         
1530         if (connData->useSSL == true){
1531                 serverAddress += "https://";
1532         } else {
1533                 serverAddress += "http://";
1534         }
1535         
1536         serverAddress += connData->hostname;
1537         
1538         // Check if server port is 80, otherwise
1539         // specifiy the port number in the address.
1540         
1541         if (connData->port != 80){
1542                 serverAddress += ":";
1543                 serverAddress += to_string(connData->port);
1544         }
1545         
1546         serverAddress += uriAddress;
1547         
1548         return serverAddress;
1549         
Xestia Software Development
Yn Maystri
© 2006 - 2019 Xestia Software Development
Software

Xestia Address Book
Xestia Calendar
Development

Xestia Gelforn
Everything else

About
News
Privacy Policy