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
index 545c108..7f268b0 100644 (file)
@@ -1,14 +1,14 @@
 // CalDAV.cpp - CalDAV Connection Object.
 //
-// (c) 2016 Xestia Software Development.
+// (c) 2016-2017 Xestia Software Development.
 //
 // This file is part of Xestia Calendar.
 //
-// Xestia Address Book is free software: you can redistribute it and/or modify
+// Xestia Calendar is free software: you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by the
 // Free Software Foundation, version 3 of the license.
 //
-// Xestia Address Book is distributed in the hope that it will be useful,
+// Xestia Calendar is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 // GNU General Public License for more details.
 // with Xestia Calendar. If not, see <http://www.gnu.org/licenses/>
 
 #include "CalDAV.h"
-#include <iostream>
 
 using namespace std;
 
+size_t CalDAVReceive(char *ReceivedBuffer, size_t Size, size_t NewMemoryBytes, string *StringPointer)
+{
+       
+       StringPointer->append(ReceivedBuffer, NewMemoryBytes);
+       
+       return Size * NewMemoryBytes;
+       
+}
+
+size_t CalDAVSend(char *SendBuffer, size_t Size, size_t NewMemoryBytes, void *DataStruct){
+
+       struct CalDAVSendData *UploadPtr = (struct CalDAVSendData *)DataStruct;
+       
+       if (UploadPtr->sizeleft){
+
+               UploadPtr->sizeleft--;
+               char CharSend;
+
+               CharSend = (*UploadPtr->readptr)[UploadPtr->seek];
+               
+               *SendBuffer = CharSend;
+               
+               UploadPtr->seek++;
+
+               return 1;
+
+       }
+
+       return 0;
+
+}
+
 CalDAV::CalDAV(){
 
        // Setup the objects within the CalDAV connection 
@@ -66,6 +97,7 @@ CalDAVStatus CalDAV::GetConnectionData(){
        ConnectionStatus.Username = ConnectionData.Username;
        ConnectionStatus.Prefix = ConnectionData.Prefix;
        ConnectionStatus.UseSSL = ConnectionData.UseSSL;
+       ConnectionStatus.Timeout = ConnectionData.Timeout;
        
        return ConnectionStatus;
        
@@ -77,28 +109,10 @@ CalDAVServerResult CalDAV::Connect(){
 
        string ServerAddress = "";
        string ServerUserPass = "";
-       string ServerData = "";
-       string ServerHeader = "";
 
        // Setup the server address.
        
-       if (ConnectionData.UseSSL == true){
-               ServerAddress += "https://";
-       } else {
-               ServerAddress += "http://";
-       }
-       
-       ServerAddress += ConnectionData.Hostname;
-       
-       // Check if server port is 80, otherwise
-       // specifiy the port number in the address.
-       
-       if (ConnectionData.Port != 80){
-               ServerAddress += ":";
-               ServerAddress += to_string(ConnectionData.Port);
-       }
-       
-       ServerAddress += "/principals/";
+       ServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
 
        // Setup the server password.
        
@@ -110,7 +124,8 @@ CalDAVServerResult CalDAV::Connect(){
        curl_easy_setopt(ConnectionHandle, CURLOPT_USERPWD, ServerUserPass.c_str());
        curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
        curl_easy_setopt(ConnectionHandle, CURLOPT_FAILONERROR, 1L);
-       curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEFUNCTION, CalDAVOutput);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_TIMEOUT, ConnectionData.Timeout);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEFUNCTION, CalDAVReceive);
        curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEDATA, &ServerData);
        curl_easy_setopt(ConnectionHandle, CURLOPT_WRITEHEADER, &ServerHeader);
        
@@ -138,63 +153,1399 @@ CalDAVServerResult CalDAV::Connect(){
        
 }
 
-bool CalDAVObjectValidSettings(CalDAVConnectionData *ConnData){
+CalDAVServerResult CalDAV::GetServerResult(){
+       
+       return ConnectionServerResult;
+       
+}
 
-       // Check if the passed CalDAV Connection Data is has
-       // an address set. Return false if nullptr is used.
+CalDAVServerSupport CalDAV::GetServerSupport(){
 
-       if (ConnData == nullptr){
+       CalDAVServerSupport ServerStatus;
        
-               return false;
+       // Setup the server connection.
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "OPTIONS");
+       
+       CURLcode ServerResult = curl_easy_perform(ConnectionHandle);
        
+       // Set the results.
+       
+       if (ServerResult == CURLE_OK){
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;          
        }
+       ConnectionServerResult.Code = ServerResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ConnectionServerResult.HTTPCode);
        
-       // Check the server hostname. Return false
-       // if no value has been set.
+       if (ServerResult != CURLE_OK){
+               return ServerStatus;
+       }
        
-       if (ConnData->Hostname.size() == 0){
+       // Check that the server header has data in,
+       // otherwise return an "empty" CalDAVServerSupport.
        
-               return false;
+       if (ServerHeader.size() == 0){
+               return ServerStatus;
+       }
        
+       // Process each line looking for the first DAV header 
+       // line.
+       
+       bool NewlineMode = true;
+       
+       string DAVLine;
+       
+       for (int CharSeek = 0; CharSeek < ServerHeader.size(); CharSeek++){
+               
+               if (NewlineMode == true){
+                       
+                       // Check if we have reached the end of the string.
+                       
+                       if (CharSeek >= ServerHeader.size()){
+                               
+                               break;
+                               
+                       }
+                       
+                       // Check the first four letters to make sure
+                       // they are 'DAV:'.
+                       
+                       string DAVHeaderCheck = "";
+                       
+                       try {
+                               DAVHeaderCheck = ServerHeader.substr(CharSeek, 4);
+                       }
+                       
+                       catch (out_of_range &oor){
+                               break;
+                       }
+                       
+                       if (DAVHeaderCheck == "DAV:"){
+                               
+                               CharSeek += 5;
+                               
+                               for (; CharSeek < ServerHeader.size(); CharSeek++){
+                                       
+                                       if (ServerHeader[CharSeek] == '\n'){
+                                       
+                                               break;
+                                               
+                                       }
+                                       
+                                       DAVLine.push_back(ServerHeader[CharSeek]);
+                                       
+                               }
+                               
+                               break;
+                               
+                       }
+                       
+                       NewlineMode = false;
+                       
+               }
+               
+               if (ServerHeader[CharSeek] == '\n'){
+                       
+                       NewlineMode = true;
+                       
+               }
+               
        }
        
-       // Check the server port. Return false if
-       // no value has been set or the port number
-       // is less than 1 or higher than 65535.
+       // Process the DAV line.
        
-       if (ConnData->Port < 1 || ConnData->Port > 65535){
+       vector<string> DAVLineData;
+       string DAVSegmentString;
        
-               return false;
+       for (int CharSeek = 0; CharSeek < DAVLine.size(); CharSeek++){
+               
+               if (DAVLine[CharSeek] == ' '){
+                       continue;
+               }
+               
+               if (DAVLine[CharSeek] == ','){
+                       
+                       DAVLineData.push_back(DAVSegmentString);
+                       DAVSegmentString.clear();
+                       continue;
+                       
+               }
+               
+               DAVSegmentString += DAVLine[CharSeek];
+               
+       }
        
+       // Process the DAV values and set each value
+       // to true as required.
+       
+       for (int DAVItemSeek = 0; 
+               DAVItemSeek < DAVLineData.size();
+               DAVItemSeek++){
+                       
+               if (DAVLineData.at(DAVItemSeek) == "calendar-access"){
+                       
+                       ServerStatus.BasicSupport = true;
+               
+               }
+                       
        }
        
-       // Check the server username. Return false
-       // if no value has been set.
+       // Reset the connection status.
        
-       if (ConnData->Username.size() == 0){
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);
+       
+       return ServerStatus;
+       
+}
+
+string CalDAV::GetUserPrincipal(){
+       
+       string CurrentUserPrincipal = "";
+       string UserPrincipalRequest = "";
+       CalDAVSendData UserPrincipalSendData;
+       
+       UserPrincipalRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+       "<d:propfind xmlns:d=\"DAV:\">\n"
+       " <d:prop>\n"
+       "  <d:current-user-principal />\n"
+       " </d:prop>\n"
+       "</d:propfind>";
+       
+       UserPrincipalSendData.readptr = &UserPrincipalRequest;
+       UserPrincipalSendData.sizeleft = UserPrincipalRequest.size();
+       
+       // Setup the header.
+       
+       struct curl_slist *UserPrincipalRequestHeader = NULL;
+       
+       UserPrincipalRequestHeader = curl_slist_append(UserPrincipalRequestHeader, "Depth: 0");
+       UserPrincipalRequestHeader = curl_slist_append(UserPrincipalRequestHeader, "Prefer: return-minimal");
+       UserPrincipalRequestHeader = curl_slist_append(UserPrincipalRequestHeader, "Content-Type: application/xml; charset=utf-8");
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, UserPrincipalRequestHeader);
+
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "PROPFIND");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &UserPrincipalSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Process the data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerResult = curl_easy_perform(ConnectionHandle);
+       
+       // Set the results.
+       
+       if (ServerResult == CURLE_OK){
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;          
+       }
+       ConnectionServerResult.Code = ServerResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ConnectionServerResult.HTTPCode);
+       
+       if (ServerResult != CURLE_OK){
                
-               return false;
+               return CurrentUserPrincipal;
                
-       }       
+       }
        
-       // Check the server password. Return false
-       // if no value has been set.
+       // Process the User Principal from the ServerData.
+
+       CurrentUserPrincipal = ProcessXMLUserPrincipal();
        
-       if (ConnData->Password.size() == 0){
+       // Reset the changed settings.
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+
+       return CurrentUserPrincipal;
+
+}
+
+string CalDAV::GetCalendarHome(string UserPrincipalURI){
+       
+       string CalendarHomeURI = "";
+
+       // Build the Calendar Home URL address.
+       
+       string CalendarHomeURL = BuildServerAddress(&ConnectionData, UserPrincipalURI);
+       
+       // Setup the header request.
+       
+       CalDAVSendData CalendarHomeSendData;
+       
+       string CalendarHomeRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+       "<d:propfind xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">\n"
+       " <d:prop>\n"
+       "  <c:calendar-home-set />\n"
+       " </d:prop>\n"
+       "</d:propfind>";
+       
+       CalendarHomeSendData.readptr = &CalendarHomeRequest;
+       CalendarHomeSendData.sizeleft = CalendarHomeRequest.size();
+       
+       // Setup the header.
+       
+       struct curl_slist *CalendarRequestHeader = NULL;
+       
+       CalendarRequestHeader = curl_slist_append(CalendarRequestHeader, "Depth: 0");
+       CalendarRequestHeader = curl_slist_append(CalendarRequestHeader, "Prefer: return-minimal");
+       CalendarRequestHeader = curl_slist_append(CalendarRequestHeader, "Content-Type: application/xml; charset=utf-8");
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, CalendarRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, CalendarHomeURL.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "PROPFIND");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &CalendarHomeSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Process the data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerResult = curl_easy_perform(ConnectionHandle);
+       
+       // Set the results.
+       
+       if (ServerResult == CURLE_OK){
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;          
+       }
+       ConnectionServerResult.Code = ServerResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ConnectionServerResult.HTTPCode);
+       
+       if (ServerResult != CURLE_OK){
                
-               return false;
+               return CalendarHomeURI;
                
        }
+       
+       // Process the User Principal from the ServerData.
 
-       // Cannot check UseSSL: It is either true
-       // or false.
+       CalendarHomeURI = ProcessXMLCalendarHome();
        
-       // Cannot check Prefix: The prefix may need
-       // to be worked out first.
+       // Reset the changed settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
+       
+       return CalendarHomeURI;
+       
+}
 
-       // No errors were found whilst checking so
-       // return true.
+CalDAVCalendarList CalDAV::GetCalendars(){
        
-       return true;
+       CalDAVCalendarList ServerList;
+       CalDAVSendData CalendarListSendData;
+       
+       // Build the server address.
+       
+       string UserPrincipalURI = "";
+       UserPrincipalURI = GetUserPrincipal();
+       
+       if (UserPrincipalURI.size() == 0){
+               
+               return ServerList;
+               
+       }
+       
+       string CalendarHomeURI = "";
+       CalendarHomeURI = GetCalendarHome(UserPrincipalURI);
+       
+       string CalendarListURLAddress = BuildServerAddress(&ConnectionData, CalendarHomeURI);
+       
+       string CalendarListRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+       "<d:propfind xmlns:d=\"DAV:\" xmlns:cs=\"http://calendarserver.org/ns/\""
+       " xmlns:c=\"urn:ietf:params:xml:ns:caldav\" xmlns:x0=\"http://apple.com/ns/ical/\">\n"
+       " <d:prop>\n"
+        "  <d:resourcetype />\n"
+       "  <d:displayname />\n"
+       "  <d:sync-token />\n"
+       "  <x0:calendar-color />\n"
+       "  <x0:calendar-order />\n"
+       "  <cs:getctag />\n"
+       "  <c:supported-calendar-component-set />\n"
+       "  <c:calendar-description />\n"
+       " </d:prop>\n"
+       "</d:propfind>";
+       
+       CalendarListSendData.readptr = &CalendarListRequest;
+       CalendarListSendData.sizeleft = CalendarListRequest.size();
+       
+       // Setup the header.
+       
+       struct curl_slist *CalendarListRequestHeader = NULL;
+       
+       CalendarListRequestHeader = curl_slist_append(CalendarListRequestHeader, "Depth: 1");
+       CalendarListRequestHeader = curl_slist_append(CalendarListRequestHeader, "Prefer: return-minimal");
+       CalendarListRequestHeader = curl_slist_append(CalendarListRequestHeader, "Content-Type: application/xml; charset=utf-8");
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, CalendarListRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, CalendarListURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "PROPFIND");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &CalendarListSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Process the data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerResult = curl_easy_perform(ConnectionHandle);
+       
+       //ServerList = ProcessXMLCalendarList();
+       
+       if (ServerResult == CURLE_OK){
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;          
+       }
+       ConnectionServerResult.Code = ServerResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ConnectionServerResult.HTTPCode);
+       
+       if (ServerResult != CURLE_OK){
+               
+               return ServerList;
+               
+       }
+       
+       // Process the received XML data into a list of calendars
+       // and locations.
+       
+       ServerList = ProcessXMLCalendarList();
+       
+       // Restore the original settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       
+       return ServerList;
+       
+}
+
+CalDAVEntryList CalDAV::GetEntryList(string *CalendarHREF){
+       
+       CalDAVEntryList EntryList;
+       CalDAVSendData EntryListSendData;
+       
+       if (CalendarHREF->size() == 0){
+               
+               return EntryList;
+               
+       }
+       
+       string EntryListURLAddress = BuildServerAddress(&ConnectionData, *CalendarHREF);
+       
+       string EntryListRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+       
+       /*if (CalendarTag == nullptr){*/
+               
+       EntryListRequest += "<c:calendar-query xmlns:d=\"DAV:\" xmlns:cs=\"http://calendarserver.org/ns/\""
+       " xmlns:c=\"urn:ietf:params:xml:ns:caldav\" xmlns:x0=\"http://apple.com/ns/ical/\">\n"
+       " <d:prop>\n"
+       "  <d:getetag />\n"
+       "  <c:calendar-data />\n"
+       " </d:prop>\n"
+       " <c:filter>\n"
+       "  <c:comp-filter name=\"VCALENDAR\" />\n"
+       " </c:filter>\n"
+       "</c:calendar-query>";
+               
+       /*} else {
+
+               EntryListRequest += "<d:sync-collection xmlns:d=\"DAV:\" xmlns:cs=\"http://calendarserver.org/ns/\""
+               " xmlns:c=\"urn:ietf:params:xml:ns:caldav\" xmlns:x0=\"http://apple.com/ns/ical/\">\n"          
+               " <d:sync-token>";
+               EntryListRequest += *CalendarTag;
+               EntryListRequest += "</d:sync-token>\n"
+               " <d:sync-level>1</d:sync-level>\n"
+               " <d:prop>\n"
+               "  <d:getetag />\n"
+               "  <c:calendar-data />\n"
+               " </d:prop>\n"
+               "</d:sync-collection>";
+               
+       }*/
+       
+       EntryListSendData.readptr = &EntryListRequest;
+       EntryListSendData.sizeleft = EntryListRequest.size();
+       
+       struct curl_slist *EntryListRequestHeader = NULL;
+       
+       EntryListRequestHeader = curl_slist_append(EntryListRequestHeader, "Content-Type: application/xml; charset=utf-8");
+       
+       /*if (CalendarTag != nullptr){
+       
+               EntryListRequestHeader = curl_slist_append(EntryListRequestHeader, "Content-Type: application/xml; charset=utf-8");
+               EntryListRequestHeader = curl_slist_append(EntryListRequestHeader, "Content-Type: application/xml; charset=utf-8");
+               
+       }*/
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, EntryListRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, EntryListURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "REPORT");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &EntryListSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Process the data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerResult = curl_easy_perform(ConnectionHandle);
+       
+       //ServerList = ProcessXMLCalendarList();
+       
+       if (ServerResult == CURLE_OK){
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;          
+       }
+       ConnectionServerResult.Code = ServerResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ConnectionServerResult.HTTPCode);
+       
+       if (ServerResult != CURLE_OK){
+               
+               return EntryList;
+               
+       }
+       
+       // Process the received XML data into a list of calendars
+       // and locations.
+       
+       EntryList = ProcessXMLEntryList();
+       
+       // Restore the original settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       
+       return EntryList;
+       
+}
+
+CalDAVEntryList CalDAV::GetEntryList(string *CalendarHREF, string *CalendarTag){
+       
+       CalDAVEntryList EntryList;
+       CalDAVSendData EntryListSendData;
+       
+       if (CalendarHREF->size() == 0){
+               
+               return EntryList;
+               
+       }
+       
+       string EntryListURLAddress = BuildServerAddress(&ConnectionData, *CalendarHREF);
+       
+       // First query: Get the list of contacts that need to be updated.
+       
+       string EntryListRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+
+       EntryListRequest += "<d:sync-collection xmlns:d=\"DAV:\" xmlns:cs=\"http://calendarserver.org/ns/\""
+       " xmlns:c=\"urn:ietf:params:xml:ns:caldav\" xmlns:x0=\"http://apple.com/ns/ical/\">\n"
+       " <d:sync-token>";
+       
+       if (CalendarTag != nullptr){
+       
+               EntryListRequest += *CalendarTag;
+               
+       } else {
+       
+               EntryListRequest += "";
+               
+       }
+
+       EntryListRequest += "</d:sync-token>\n"
+       " <d:sync-level>1</d:sync-level>\n"
+       " <d:prop>\n"
+       "  <d:getetag />\n"
+       " </d:prop>\n"
+       "</d:sync-collection>";
+       
+       EntryListSendData.readptr = &EntryListRequest;
+       EntryListSendData.sizeleft = EntryListRequest.size();
+       
+       struct curl_slist *EntryListRequestHeader = NULL;
+       
+       EntryListRequestHeader = curl_slist_append(EntryListRequestHeader, "Content-Type: application/xml; charset=utf-8");
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, EntryListRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, EntryListURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "REPORT");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &EntryListSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Process the data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerResult = curl_easy_perform(ConnectionHandle);
+       
+       if (ServerResult == CURLE_OK){
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;          
+       }
+       ConnectionServerResult.Code = ServerResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ConnectionServerResult.HTTPCode);
+       
+       if (ServerResult != CURLE_OK){
+               
+               return EntryList;
+               
+       }
+       
+       EntryList = ProcessXMLSyncTokenList();
+       
+       // Check the last entry matches the HREF and if it 
+       // does then delete it.
+       
+       if (EntryList.HREF.size() > 0) {
+       
+               if (EntryList.HREF.rbegin()->second == *CalendarHREF){
+                       
+                       EntryList.HREF.erase((EntryList.HREF.size() - 1));
+                       EntryList.Tag.erase((EntryList.HREF.size() - 1));
+                       EntryList.Data.erase((EntryList.HREF.size() - 1));
+               
+               }
+       
+       }
+       
+       // Build the list into a new list for getting the new 
+       // calendar data with.
+       
+       EntryListRequest.clear();
+       
+       EntryListRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
 
+       EntryListRequest += "<c:calendar-multiget xmlns:d=\"DAV:\" "
+       " xmlns:c=\"urn:ietf:params:xml:ns:caldav\">\n"
+       " <d:prop>\n"
+       "  <d:getetag />\n"
+       "  <c:calendar-data />\n"
+       " </d:prop>\n";
+       
+       for (std::map<int,string>::iterator HREFIter = EntryList.HREF.begin(); 
+               HREFIter != EntryList.HREF.end(); HREFIter++){
+               
+               string EntryListHREFString = HREFIter->second;
+                       
+               EntryListRequest += " <d:href>";
+               EntryListRequest += EntryListHREFString;
+               EntryListRequest += "</d:href>\n";
+                       
+       }
+       
+       EntryListRequest += "</c:calendar-multiget>";
+       
+       CalDAVSendData UpdatedEntryListSendData;        
+       
+       UpdatedEntryListSendData.readptr = &EntryListRequest;
+       UpdatedEntryListSendData.sizeleft = EntryListRequest.size();
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, EntryListRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, EntryListURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "REPORT");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &UpdatedEntryListSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Get the updated calendar data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       EntryList.HREF.clear();
+       EntryList.Tag.clear();
+       EntryList.Data.clear();
+       
+       ServerResult = curl_easy_perform(ConnectionHandle);
+
+       // Check the last entry matches the HREF and if it 
+       // does then delete it.
+       
+       if (ServerResult == CURLE_OK){
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ConnectionServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;          
+       }
+       ConnectionServerResult.Code = ServerResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ConnectionServerResult.HTTPCode);
+       
+       if (ServerResult != CURLE_OK){
+               
+               return EntryList;
+               
+       }
+       
+       EntryList = ProcessXMLEntryList();
+       
+       // Second query: Get the list of contact data for the contacts that have
+       // beenchanged.
+       
+       // Restore the original settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       
+       return EntryList;
+       
+}
+
+CalDAVServerResult CalDAV::AddCalendar(string CalendarName){
+       
+       CalDAVServerResult ServerResult;
+       
+       AddCalendar(&CalendarName, nullptr);
+       
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::AddCalendar(string *CalendarName, string *CalendarShortName){
+       
+       CalDAVServerResult ServerResult;
+       CalDAVSendData CalendarAddSendData;
+       
+       // Build the server address.
+       
+       string UserPrincipalURI = "";
+       UserPrincipalURI = GetUserPrincipal();
+       
+       if (UserPrincipalURI.size() == 0){
+               
+               return ServerResult;
+               
+       }
+       
+       string CalendarHomeURI = "";
+       CalendarHomeURI = GetCalendarHome(UserPrincipalURI);
+       
+       // Generate the UUID.
+       
+       string UUIDValue = "";
+       
+       if (CalendarShortName == nullptr){
+       
+               UUIDValue = GenerateUUID();
+               UUIDValue.erase(UUIDValue.end()-1);
+
+       } else {
+       
+               UUIDValue = *CalendarShortName;
+               
+       }
+               
+       string CalendarHomeURL = CalendarHomeURI;
+       CalendarHomeURL.append(UUIDValue);
+       CalendarHomeURL.append("/");
+       
+       // Build the calendar list address.
+       
+       string CalendarListURLAddress = BuildServerAddress(&ConnectionData, CalendarHomeURL);
+       
+       string CalendarAddRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+       "<c:mkcalendar xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">\n"
+       " <d:set>\n"
+       "  <d:prop>\n"
+       "   <d:displayname>";
+       CalendarAddRequest += *CalendarName;
+       CalendarAddRequest += "</d:displayname>\n"
+       "   <c:supported-calendar-component-set>\n"
+       "    <c:comp name=\"VTODO\"/>\n"
+       "    <c:comp name=\"VEVENT\"/>\n"
+       "   </c:supported-calendar-component-set>\n"
+       "  </d:prop>\n"
+       " </d:set>\n"
+       "</c:mkcalendar>";
+       
+       CalendarAddSendData.readptr = &CalendarAddRequest;
+       CalendarAddSendData.sizeleft = CalendarAddRequest.size();
+       
+       // Setup the header.
+       
+       struct curl_slist *CalendarRequestHeader = NULL;
+       
+       //curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, CalendarRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, CalendarListURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "MKCALENDAR");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &CalendarAddSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Process the data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
+       
+       if (ServerConnectionResult == CURLE_OK){
+               ServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
+       }
+       ServerResult.Code = ServerConnectionResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
+       
+       // Restore the original settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::EditCalendarProcess(string *CalendarHREF,
+                       string *CalendarName,
+                       Colour *CalendarColour,
+                       string *CalendarDescription,
+                       int *CalendarOrder){
+
+       CalDAVServerResult ServerResult;
+       CalDAVSendData CalendarEditSendData;
+       
+       // Build the server address.
+       
+       string UserPrincipalURI = "";
+       UserPrincipalURI = GetUserPrincipal();
+       
+       if (UserPrincipalURI.size() == 0){
+               
+               return ServerResult;
+               
+       }
+       
+       string CalendarHomeURI = "";
+       CalendarHomeURI = GetCalendarHome(UserPrincipalURI);
+       
+       // Generate the UUID.
+       
+       string UUIDValue = GenerateUUID();
+       UUIDValue.erase(UUIDValue.end()-1);
+       
+       string CalendarHomeURL = CalendarHomeURI;
+       CalendarHomeURL.append(UUIDValue);
+       CalendarHomeURL.append("/");
+       
+       // Build the calendar list address.
+       
+       string CalendarEditURLAddress = BuildServerAddress(&ConnectionData, (*CalendarHREF));
+       
+       string CalendarEditRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+       "<d:propertyupdate xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\"\n"
+       "       xmlns:x0=\"http://apple.com/ns/ical/\">\n"
+       " <d:set>\n"
+       "  <d:prop>\n";
+       
+       // Update the calendar name.
+       
+       if (CalendarName != nullptr){
+       
+               CalendarEditRequest += "<d:displayname>";
+               CalendarEditRequest += (*CalendarName);
+               CalendarEditRequest += "</d:displayname>\n";
+               
+       }
+       
+       // Update the calendar colour.
+       
+       if (CalendarColour != nullptr){
+               
+               CalendarEditRequest += "<x0:calendar-color>";
+               CalendarEditRequest += (*CalendarColour);
+               CalendarEditRequest += "</x0:calendar-color>\n";
+               
+       }
+       
+       // Update the calendar description.
+       
+       if (CalendarDescription != nullptr){
+               
+               CalendarEditRequest += "<c:calendar-description>";
+               CalendarEditRequest += (*CalendarDescription);
+               CalendarEditRequest += "</c:calendar-description>\n";           
+               
+       }
+       
+       // Update the calendar order.
+       
+       if (CalendarOrder != nullptr){
+               
+               CalendarEditRequest += "<x0:calendar-order>";
+               CalendarEditRequest += to_string((*CalendarOrder));
+               CalendarEditRequest += "</x0:calendar-order>\n";
+               
+       }
+       
+       CalendarEditRequest += "  </d:prop>\n"
+       " </d:set>\n"
+       "</d:propertyupdate>";
+       
+       CalendarEditSendData.readptr = &CalendarEditRequest;
+       CalendarEditSendData.sizeleft = CalendarEditRequest.size();
+       
+       // Setup the header.
+       
+       struct curl_slist *CalendarRequestHeader = NULL;
+       
+       //curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, CalendarRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, CalendarEditURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "PROPPATCH");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &CalendarEditSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Process the data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
+       
+       if (ServerConnectionResult == CURLE_OK){
+               ServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
+       }
+       ServerResult.Code = ServerConnectionResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
+       
+       // Restore the original settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       
+       return ServerResult;
+
+}
+
+CalDAVServerResult CalDAV::EditCalendar(string *CalendarHREF,
+                       string *CalendarName,
+                       Colour *CalendarColour,
+                       string *CalendarDescription,
+                       int *CalendarOrder){
+       
+       CalDAVServerResult ServerResult;
+       
+       ServerResult = EditCalendarProcess(CalendarHREF,
+               CalendarName,
+               CalendarColour,
+               CalendarDescription,
+               CalendarOrder);
+                               
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::EditCalendar(string *CalendarHREF,
+                       Colour *CalendarColour){
+       
+
+       CalDAVServerResult ServerResult;
+
+       ServerResult = EditCalendarProcess(CalendarHREF,
+               nullptr,
+               CalendarColour,
+               nullptr,
+               nullptr);
+                               
+       return ServerResult;    
+       
+}
+
+CalDAVServerResult CalDAV::EditCalendar(string *CalendarHREF,
+                       string *CalendarName){
+       
+       CalDAVServerResult ServerResult;
+       
+       ServerResult = EditCalendarProcess(CalendarHREF,
+               CalendarName,
+               nullptr,
+               nullptr,
+               nullptr);       
+       
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::EditCalendar(string *CalendarHREF,
+                       int *CalendarOrder){
+       
+       CalDAVServerResult ServerResult;
+       
+       ServerResult = EditCalendarProcess(CalendarHREF,
+               nullptr,
+               nullptr,
+               nullptr,
+               CalendarOrder);
+       
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::EditCalendarDescription(string *CalendarHREF,
+                       string *CalendarDescription){
+       
+       CalDAVServerResult ServerResult;
+       
+       ServerResult = EditCalendarProcess(CalendarHREF,
+               nullptr,
+               nullptr,
+               CalendarDescription,
+               nullptr);
+       
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::DeleteCalendar(string *CalendarHREF){
+
+       CalDAVServerResult ServerResult;
+       
+       // Build the server address.
+       
+       string UserPrincipalURI = "";
+       UserPrincipalURI = GetUserPrincipal();
+       
+       if (UserPrincipalURI.size() == 0){
+               
+               return ServerResult;
+               
+       }
+       
+       string CalendarHomeURI = "";
+       CalendarHomeURI = GetCalendarHome(UserPrincipalURI);
+       
+       // Generate the UUID.
+       
+       string UUIDValue = GenerateUUID();
+       UUIDValue.erase(UUIDValue.end()-1);
+       
+       string CalendarHomeURL = CalendarHomeURI;
+       CalendarHomeURL.append(UUIDValue);
+       CalendarHomeURL.append("/");
+       
+       // Build the calendar list address.
+       
+       struct curl_slist *DeleteRequestHeader = NULL;
+       
+       DeleteRequestHeader = curl_slist_append(DeleteRequestHeader, "Depth: infinity");
+       
+       string CalendarDeleteURLAddress = BuildServerAddress(&ConnectionData, (*CalendarHREF));
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, DeleteRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, CalendarDeleteURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
+       
+       // Delete the calendar.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
+       
+       if (ServerConnectionResult == CURLE_OK){
+               ServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
+       }
+       ServerResult.Code = ServerConnectionResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
+       
+       // Restore the original settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
+       
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::GetEntryETag(string *CalendarEntryHREF, string *ETagValue){
+       
+       CalDAVServerResult ServerResult;
+       CalDAVSendData EntryETagGetData;
+       
+       // Build the server address.
+       
+       string UserPrincipalURI = "";
+       UserPrincipalURI = GetUserPrincipal();
+       
+       if (UserPrincipalURI.size() == 0){
+               
+               return ServerResult;
+               
+       }
+       
+       string CalendarHomeURI = "";
+       CalendarHomeURI = GetCalendarHome(UserPrincipalURI);
+
+       // Split the path and filename.
+       
+       string EntryURIPath;
+       string EntryFilename;
+       
+       SplitPathFilename(CalendarEntryHREF, &EntryURIPath, &EntryFilename);
+       
+       // Build the request for the server.
+
+       string EntryETagRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+       "<c:calendar-multiget xmlns:d=\"DAV:\" xmlns:c=\"urn:ietf:params:xml:ns:caldav\">\n"
+       " <d:prop>\n"
+       "  <d:getetag />\n"
+       " </d:prop>\n"
+       " <d:href>";
+       EntryETagRequest += (*CalendarEntryHREF);
+       EntryETagRequest += "</d:href>\n"
+       "</c:calendar-multiget>";
+       
+       EntryETagGetData.readptr = &EntryETagRequest;
+       EntryETagGetData.sizeleft = EntryETagRequest.size();
+       
+       // Build the calendar list address.
+       
+       struct curl_slist *GetETagRequestHeader = NULL;
+
+       GetETagRequestHeader = curl_slist_append(GetETagRequestHeader, "Depth: 1");     
+       GetETagRequestHeader = curl_slist_append(GetETagRequestHeader, "Prefer: return-minimal");
+       GetETagRequestHeader = curl_slist_append(GetETagRequestHeader, "Content-Type: application/xml; charset=utf-8");
+       
+       string GetETagURLAddress = BuildServerAddress(&ConnectionData, EntryURIPath);
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, GetETagRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, GetETagURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "REPORT");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &EntryETagGetData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Attempt to get the entity tag.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
+       
+       if (ServerConnectionResult == CURLE_OK){
+               ServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
+       }
+       ServerResult.Code = ServerConnectionResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
+       
+       if (ServerConnectionResult != CURLE_OK){
+               return ServerResult;
+       }
+       
+       // Get the entity tag from the result.
+       
+       *ETagValue = ProcessXMLEntryETag();
+       
+       // Restore the original settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
+       
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::AddEntry(string *CalendarEntryHREF, string *EntryData){
+       
+       // Add an entry to the calendar collection.
+       
+       CalDAVServerResult ServerResult;
+       CalDAVSendData EntryAddSendData;
+       
+       // Build the calendar list address.
+       
+       string EntryAddURLAddress = BuildServerAddress(&ConnectionData, (*CalendarEntryHREF));
+       
+       EntryAddSendData.readptr = EntryData;
+       EntryAddSendData.sizeleft = EntryData->size();
+       
+       struct curl_slist *CalendarRequestHeader = NULL;
+       
+       CalendarRequestHeader = curl_slist_append(CalendarRequestHeader, "Content-Type: text/calendar; charset=utf-8");
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, CalendarRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, EntryAddURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "PUT");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &EntryAddSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Process the data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
+       
+       if (ServerConnectionResult == CURLE_OK){
+               ServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
+       }
+       ServerResult.Code = ServerConnectionResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
+       
+       // Restore the original settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
+       
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::EditEntry(string *CalendarEntryHREF, string *EntryData, string *EntryETag){
+       
+       // Edit an entry in the calendar collection.
+
+       // Add an entry to the calendar collection.
+       
+       CalDAVServerResult ServerResult;
+       CalDAVSendData EntryAddSendData;
+       
+       // Build the calendar list address.
+       
+       string EntryAddURLAddress = BuildServerAddress(&ConnectionData, (*CalendarEntryHREF));
+       
+       EntryAddSendData.readptr = EntryData;
+       EntryAddSendData.sizeleft = EntryData->size();
+       
+       string IfMatchHeader = "If-Match: \"";
+       IfMatchHeader.append(*EntryETag);
+       IfMatchHeader.append("\"");
+       
+       struct curl_slist *CalendarRequestHeader = NULL;
+       
+       CalendarRequestHeader = curl_slist_append(CalendarRequestHeader, "Content-Type: text/calendar; charset=utf-8");
+       CalendarRequestHeader = curl_slist_append(CalendarRequestHeader, IfMatchHeader.c_str());        
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, CalendarRequestHeader);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, EntryAddURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "PUT");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 1L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, &EntryAddSendData);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, CalDAVSend);
+       
+       // Process the data.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
+       
+       if (ServerConnectionResult == CURLE_OK){
+               ServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
+       }
+       ServerResult.Code = ServerConnectionResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
+       
+       // Restore the original settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
+       
+       return ServerResult;
+       
+}
+
+CalDAVServerResult CalDAV::DeleteEntry(string *CalendarEntryHREF){
+       
+       // Delete an entry in the calendar collection.
+       
+       CalDAVServerResult ServerResult;
+       
+       // Build the calendar list address.
+       
+       string EntryDeleteURLAddress = BuildServerAddress(&ConnectionData, (*CalendarEntryHREF));
+       
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, EntryDeleteURLAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, "DELETE");
+       
+       // Delete the calendar.
+       
+       ServerData.clear();
+       ServerHeader.clear();
+       
+       CURLcode ServerConnectionResult = curl_easy_perform(ConnectionHandle);
+       
+       if (ServerConnectionResult == CURLE_OK){
+               ServerResult.Result = CALDAVQUERYRESULT_OK;
+       } else {
+               ServerResult.Result = CALDAVQUERYRESULT_SERVERERROR;            
+       }
+       ServerResult.Code = ServerConnectionResult;
+       curl_easy_getinfo(ConnectionHandle, CURLINFO_RESPONSE_CODE, &ServerResult.HTTPCode);
+       
+       // Restore the original settings.
+       
+       string OriginalServerAddress = BuildServerAddress(&ConnectionData, "/principals/");
+       curl_easy_setopt(ConnectionHandle, CURLOPT_URL, OriginalServerAddress.c_str());
+       curl_easy_setopt(ConnectionHandle, CURLOPT_CUSTOMREQUEST, NULL);        
+       curl_easy_setopt(ConnectionHandle, CURLOPT_UPLOAD, 0L);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL);
+       curl_easy_setopt(ConnectionHandle, CURLOPT_HTTPHEADER, NULL);
+       
+       return ServerResult;
+       
+}
+
+bool CalDAVObjectValidSettings(CalDAVConnectionData *ConnData){
+
+       // Check if the passed CalDAV Connection Data is has
+       // an address set. Return false if nullptr is used.
+
+       if (ConnData == nullptr){
+       
+               return false;
+       
+       }
+       
+       // Check the server hostname. Return false
+       // if no value has been set.
+       
+       if (ConnData->Hostname.size() == 0){
+       
+               return false;
+       
+       }
+       
+       // Check the server port. Return false if
+       // no value has been set or the port number
+       // is less than 1 or higher than 65535.
+       
+       if (ConnData->Port < 1 || ConnData->Port > 65535){
+       
+               return false;
+       
+       }
+       
+       // Check the server username. Return false
+       // if no value has been set.
+       
+       if (ConnData->Username.size() == 0){
+               
+               return false;
+               
+       }       
+       
+       // Check the server password. Return false
+       // if no value has been set.
+       
+       if (ConnData->Password.size() == 0){
+               
+               return false;
+               
+       }
+
+       // Cannot check UseSSL: It is either true
+       // or false.
+       
+       // Cannot check Prefix: The prefix may need
+       // to be worked out first.
+
+       // No errors were found whilst checking so
+       // return true.
+       
+       return true;
+
+}
+
+string BuildServerAddress(CalDAVConnectionData *ConnData, string URIAddress){
+       
+       string ServerAddress;
+       
+       // Setup the server address.
+       
+       if (ConnData->UseSSL == true){
+               ServerAddress += "https://";
+       } else {
+               ServerAddress += "http://";
+       }
+       
+       ServerAddress += ConnData->Hostname;
+       
+       // Check if server port is 80, otherwise
+       // specifiy the port number in the address.
+       
+       if (ConnData->Port != 80){
+               ServerAddress += ":";
+               ServerAddress += to_string(ConnData->Port);
+       }
+       
+       ServerAddress += URIAddress;
+       
+       return ServerAddress;
+       
 }
\ No newline at end of file
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