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