Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
Updated/Added copyright header and licensing to all source files
[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){
1084         
1086         CalDAVServerResult ServerResult;
1088         ServerResult = EditCalendarProcess(CalendarHREF,
1089                 nullptr,
1090                 CalendarColour,
1091                 nullptr,
1092                 nullptr);
1093                                 
1094         return ServerResult;    
1095         
1098 CalDAVServerResult CalDAV::EditCalendar(string *CalendarHREF,
1099                         string *CalendarName){
1100         
1101         CalDAVServerResult ServerResult;
1102         
1103         ServerResult = EditCalendarProcess(CalendarHREF,
1104                 CalendarName,
1105                 nullptr,
1106                 nullptr,
1107                 nullptr);       
1108         
1109         return ServerResult;
1110         
1113 CalDAVServerResult CalDAV::EditCalendar(string *CalendarHREF,
1114                         int *CalendarOrder){
1115         
1116         CalDAVServerResult ServerResult;
1117         
1118         ServerResult = EditCalendarProcess(CalendarHREF,
1119                 nullptr,
1120                 nullptr,
1121                 nullptr,
1122                 CalendarOrder);
1123         
1124         return ServerResult;
1125         
1128 CalDAVServerResult CalDAV::EditCalendarDescription(string *CalendarHREF,
1129                         string *CalendarDescription){
1130         
1131         CalDAVServerResult ServerResult;
1132         
1133         ServerResult = EditCalendarProcess(CalendarHREF,
1134                 nullptr,
1135                 nullptr,
1136                 CalendarDescription,
1137                 nullptr);
1138         
1139         return ServerResult;
1140         
1143 CalDAVServerResult CalDAV::DeleteCalendar(string *CalendarHREF){
1145         CalDAVServerResult ServerResult;
1146         
1147         // Build the server address.
1148         
1149         string UserPrincipalURI = "";
1150         UserPrincipalURI = GetUserPrincipal();
1151         
1152         if (UserPrincipalURI.size() == 0){
1153                 
1154                 return ServerResult;
1155                 
1156         }
1157         
1158         string CalendarHomeURI = "";
1159         CalendarHomeURI = GetCalendarHome(UserPrincipalURI);
1160         
1161         // Generate the UUID.
1162         
1163         string UUIDValue = GenerateUUID();
1164         UUIDValue.erase(UUIDValue.end()-1);
1165         
1166         string CalendarHomeURL = CalendarHomeURI;
1167         CalendarHomeURL.append(UUIDValue);
1168         CalendarHomeURL.append("/");
1169         
1170         // Build the calendar list address.
1171         
1172         struct curl_slist *DeleteRequestHeader = NULL;
1173         
1174         DeleteRequestHeader = curl_slist_append(DeleteRequestHeader, "Depth: infinity");
1175         
1176         string CalendarDeleteURLAddress = BuildServerAddress(&ConnectionData, (*CalendarHREF));
1177         
1178         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, DeleteRequestHeader);
1179         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, CalendarDeleteURLAddress.c_str());
1180         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
1181         
1182         // Delete the calendar.
1183         
1184         ServerData.clear();
1185         ServerHeader.clear();
1186         
1187         CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
1188         
1189         if (ServerConnectionResult == CURLE_OK){
1190                 ServerResult.Result = CALDAVQUERYRESULT_OK;
1191         } else {
1192                 ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
1193         }
1194         ServerResult.Code = ServerConnectionResult;
1195         curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
1196         
1197         // Restore the original settings.
1198         
1199         string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
1200         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
1201         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1202         curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
1203         curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
1204         curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
1205         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
1206         
1207         return ServerResult;
1208         
1211 CalDAVServerResult CalDAV::GetEntryETag(string *CalendarEntryHREF, string *ETagValue){
1212         
1213         CalDAVServerResult ServerResult;
1214         CalDAVSendData EntryETagGetData;
1215         
1216         // Build the server address.
1217         
1218         string UserPrincipalURI = "";
1219         UserPrincipalURI = GetUserPrincipal();
1220         
1221         if (UserPrincipalURI.size() == 0){
1222                 
1223                 return ServerResult;
1224                 
1225         }
1226         
1227         string CalendarHomeURI = "";
1228         CalendarHomeURI = GetCalendarHome(UserPrincipalURI);
1230         // Split the path and filename.
1231         
1232         string EntryURIPath;
1233         string EntryFilename;
1234         
1235         SplitPathFilename(CalendarEntryHREF, &EntryURIPath, &EntryFilename);
1236         
1237         // Build the request for the server.
1239         string EntryETagRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1240         "<c:calendar-multiget xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">\n"
1241         " <d:prop>\n"
1242         "  <d:getetag />\n"
1243         " </d:prop>\n"
1244         " <d:href>";
1245         EntryETagRequest += (*CalendarEntryHREF);
1246         EntryETagRequest += "</d:href>\n"
1247         "</c:calendar-multiget>";
1248         
1249         EntryETagGetData.readptr = &EntryETagRequest;
1250         EntryETagGetData.sizeleft = EntryETagRequest.size();
1251         
1252         // Build the calendar list address.
1253         
1254         struct curl_slist *GetETagRequestHeader = NULL;
1256         GetETagRequestHeader = curl_slist_append(GetETagRequestHeader, "Depth: 1");     
1257         GetETagRequestHeader = curl_slist_append(GetETagRequestHeader, "Prefer: return-minimal");
1258         GetETagRequestHeader = curl_slist_append(GetETagRequestHeader, "Content-Type: application/xml; charset=utf-8");
1259         
1260         string GetETagURLAddress = BuildServerAddress(&ConnectionData, EntryURIPath);
1261         
1262         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, GetETagRequestHeader);
1263         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, GetETagURLAddress.c_str());
1264         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "REPORT");
1265         curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
1266         curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &EntryETagGetData);
1267         curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
1268         
1269         // Attempt to get the entity tag.
1270         
1271         ServerData.clear();
1272         ServerHeader.clear();
1273         
1274         CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
1275         
1276         if (ServerConnectionResult == CURLE_OK){
1277                 ServerResult.Result = CALDAVQUERYRESULT_OK;
1278         } else {
1279                 ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
1280         }
1281         ServerResult.Code = ServerConnectionResult;
1282         curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
1283         
1284         if (ServerConnectionResult != CURLE_OK){
1285                 return ServerResult;
1286         }
1287         
1288         // Get the entity tag from the result.
1289         
1290         *ETagValue = ProcessXMLEntryETag();
1291         
1292         // Restore the original settings.
1293         
1294         string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
1295         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
1296         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1297         curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
1298         curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
1299         curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
1300         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
1301         
1302         return ServerResult;
1303         
1306 CalDAVServerResult CalDAV::AddEntry(string *CalendarEntryHREF, string *EntryData){
1307         
1308         // Add an entry to the calendar collection.
1309         
1310         CalDAVServerResult ServerResult;
1311         CalDAVSendData EntryAddSendData;
1312         
1313         // Build the calendar list address.
1314         
1315         string EntryAddURLAddress = BuildServerAddress(&ConnectionData, (*CalendarEntryHREF));
1316         
1317         EntryAddSendData.readptr = EntryData;
1318         EntryAddSendData.sizeleft = EntryData->size();
1319         
1320         struct curl_slist *CalendarRequestHeader = NULL;
1321         
1322         CalendarRequestHeader = curl_slist_append(CalendarRequestHeader, "Content-Type: text/calendar; charset=utf-8");
1323         
1324         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, CalendarRequestHeader);
1325         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, EntryAddURLAddress.c_str());
1326         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "PUT");
1327         curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
1328         curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &EntryAddSendData);
1329         curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
1330         
1331         // Process the data.
1332         
1333         ServerData.clear();
1334         ServerHeader.clear();
1335         
1336         CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
1337         
1338         if (ServerConnectionResult == CURLE_OK){
1339                 ServerResult.Result = CALDAVQUERYRESULT_OK;
1340         } else {
1341                 ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
1342         }
1343         ServerResult.Code = ServerConnectionResult;
1344         curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
1345         
1346         // Restore the original settings.
1347         
1348         string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
1349         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
1350         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1351         curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
1352         curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
1353         curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
1354         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
1355         
1356         return ServerResult;
1357         
1360 CalDAVServerResult CalDAV::EditEntry(string *CalendarEntryHREF, string *EntryData, string *EntryETag){
1361         
1362         // Edit an entry in the calendar collection.
1364         // Add an entry to the calendar collection.
1365         
1366         CalDAVServerResult ServerResult;
1367         CalDAVSendData EntryAddSendData;
1368         
1369         // Build the calendar list address.
1370         
1371         string EntryAddURLAddress = BuildServerAddress(&ConnectionData, (*CalendarEntryHREF));
1372         
1373         EntryAddSendData.readptr = EntryData;
1374         EntryAddSendData.sizeleft = EntryData->size();
1375         
1376         string IfMatchHeader = "If-Match: \"";
1377         IfMatchHeader.append(*EntryETag);
1378         IfMatchHeader.append("\"");
1379         
1380         struct curl_slist *CalendarRequestHeader = NULL;
1381         
1382         CalendarRequestHeader = curl_slist_append(CalendarRequestHeader, "Content-Type: text/calendar; charset=utf-8");
1383         CalendarRequestHeader = curl_slist_append(CalendarRequestHeader, IfMatchHeader.c_str());        
1384         
1385         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, CalendarRequestHeader);
1386         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, EntryAddURLAddress.c_str());
1387         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "PUT");
1388         curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
1389         curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &EntryAddSendData);
1390         curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
1391         
1392         // Process the data.
1393         
1394         ServerData.clear();
1395         ServerHeader.clear();
1396         
1397         CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
1398         
1399         if (ServerConnectionResult == CURLE_OK){
1400                 ServerResult.Result = CALDAVQUERYRESULT_OK;
1401         } else {
1402                 ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
1403         }
1404         ServerResult.Code = ServerConnectionResult;
1405         curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
1406         
1407         // Restore the original settings.
1408         
1409         string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
1410         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
1411         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1412         curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
1413         curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
1414         curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
1415         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
1416         
1417         return ServerResult;
1418         
1421 CalDAVServerResult CalDAV::DeleteEntry(string *CalendarEntryHREF){
1422         
1423         // Delete an entry in the calendar collection.
1424         
1425         CalDAVServerResult ServerResult;
1426         
1427         // Build the calendar list address.
1428         
1429         string EntryDeleteURLAddress = BuildServerAddress(&ConnectionData, (*CalendarEntryHREF));
1430         
1431         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
1432         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, EntryDeleteURLAddress.c_str());
1433         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
1434         
1435         // Delete the calendar.
1436         
1437         ServerData.clear();
1438         ServerHeader.clear();
1439         
1440         CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
1441         
1442         if (ServerConnectionResult == CURLE_OK){
1443                 ServerResult.Result = CALDAVQUERYRESULT_OK;
1444         } else {
1445                 ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
1446         }
1447         ServerResult.Code = ServerConnectionResult;
1448         curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
1449         
1450         // Restore the original settings.
1451         
1452         string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
1453         curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
1454         curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
1455         curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
1456         curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
1457         curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
1458         curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
1459         
1460         return ServerResult;
1461         
1464 bool CalDAVObjectValidSettings(CalDAVConnectionData *ConnData){
1466         // Check if the passed CalDAV Connection Data is has
1467         // an address set. Return false if nullptr is used.
1469         if (ConnData == nullptr){
1470         
1471                 return false;
1472         
1473         }
1474         
1475         // Check the server hostname. Return false
1476         // if no value has been set.
1477         
1478         if (ConnData->Hostname.size() == 0){
1479         
1480                 return false;
1481         
1482         }
1483         
1484         // Check the server port. Return false if
1485         // no value has been set or the port number
1486         // is less than 1 or higher than 65535.
1487         
1488         if (ConnData->Port < 1 || ConnData->Port > 65535){
1489         
1490                 return false;
1491         
1492         }
1493         
1494         // Check the server username. Return false
1495         // if no value has been set.
1496         
1497         if (ConnData->Username.size() == 0){
1498                 
1499                 return false;
1500                 
1501         }       
1502         
1503         // Check the server password. Return false
1504         // if no value has been set.
1505         
1506         if (ConnData->Password.size() == 0){
1507                 
1508                 return false;
1509                 
1510         }
1512         // Cannot check UseSSL: It is either true
1513         // or false.
1514         
1515         // Cannot check Prefix: The prefix may need
1516         // to be worked out first.
1518         // No errors were found whilst checking so
1519         // return true.
1520         
1521         return true;
1525 string BuildServerAddress(CalDAVConnectionData *ConnData, string URIAddress){
1526         
1527         string ServerAddress;
1528         
1529         // Setup the server address.
1530         
1531         if (ConnData->UseSSL == true){
1532                 ServerAddress += "https://";
1533         } else {
1534                 ServerAddress += "http://";
1535         }
1536         
1537         ServerAddress += ConnData->Hostname;
1538         
1539         // Check if server port is 80, otherwise
1540         // specifiy the port number in the address.
1541         
1542         if (ConnData->Port != 80){
1543                 ServerAddress += ":";
1544                 ServerAddress += to_string(ConnData->Port);
1545         }
1546         
1547         ServerAddress += URIAddress;
1548         
1549         return ServerAddress;
1550         
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