From 3c82d9b1245400208b2d167683a82a39cdbc2689 Mon Sep 17 00:00:00 2001 From: Steve Brokenshire Date: Sat, 30 Apr 2016 21:43:49 +0100 Subject: [PATCH] Added code and unit tests for deleting entries in the CalDAV object Added the following subroutines to the CalDAV object: GetEntryETag(*string); Unit tests setup for deleting calendars under CalDAV/GetEntryETag testing the above function. --- .../objects/CalDAV/CalDAV-XMLProcessing.cpp | 70 ++++++++++++++ source/objects/CalDAV/CalDAV.cpp | 95 +++++++++++++++++++ source/objects/CalDAV/CalDAV.h | 3 + source/tests/xestiacalendar_caldav.h | 72 ++++++++++++++ 4 files changed, 240 insertions(+) diff --git a/source/objects/CalDAV/CalDAV-XMLProcessing.cpp b/source/objects/CalDAV/CalDAV-XMLProcessing.cpp index 38e26c7..f84daed 100644 --- a/source/objects/CalDAV/CalDAV-XMLProcessing.cpp +++ b/source/objects/CalDAV/CalDAV-XMLProcessing.cpp @@ -355,6 +355,76 @@ CalDAVCalendarList CalDAV::ProcessXMLCalendarList(){ } +string CalDAV::ProcessXMLEntryETag(){ + + string EntryETag; + + xmlDocPtr xmlCalDAVDoc; + xmlCalDAVDoc = xmlReadMemory(ServerData.c_str(), (int)ServerData.size(), "noname.xml", NULL, 0); + + xmlNodePtr NodeSeek; + bool NodeFound = false; + + // Start with the first node, look for multistatus. + + for (NodeSeek = xmlCalDAVDoc->children; + NodeSeek != NULL; + NodeSeek = NodeSeek->next) + { + + if (!xmlStrcmp(NodeSeek->name, (const xmlChar *)"multistatus") || + !xmlStrcmp(NodeSeek->name, (const xmlChar *)"d:multistatus") || + !xmlStrcmp(NodeSeek->name, (const xmlChar *)"D:multistatus") + ){ + + NodeFound = true; + break; + + } + + } + + // Look for response. + + if (NodeFound == false){ return EntryETag; } else { NodeFound = false; } + NodeFound = MatchXMLNameTransverse(&NodeSeek, "response"); + + // Look for propstat. + + if (NodeFound == false){ return EntryETag; } else { NodeFound = false; } + NodeFound = MatchXMLNameTransverse(&NodeSeek, "propstat"); + + // Look for prop. + + if (NodeFound == false){ return EntryETag; } else { NodeFound = false; } + NodeFound = MatchXMLNameTransverse(&NodeSeek, "prop"); + + // Look for calendar-home-set. + + if (NodeFound == false){ return EntryETag; } else { NodeFound = false; } + NodeFound = MatchXMLNameTransverse(&NodeSeek, "getetag"); + + // Get the data from href. + + EntryETag = FetchXMLData(&NodeSeek); + + xmlFreeDoc(xmlCalDAVDoc); + + // Check if the entity tag contains quote marks + // at the start and end and remove them (if needed). + + if (EntryETag.substr(0,1) == "\"" && + EntryETag.substr(EntryETag.size()-1, 1) == "\"" && EntryETag.size() > 2){ + + EntryETag.erase(EntryETag.begin()); + EntryETag.erase(EntryETag.end()-1); + + } + + return EntryETag; + +} + bool CalDAV::MatchXMLNameTransverse(xmlNodePtr *NodePtr, string NodeName){ string NodeNameSmallD = "d:" + NodeName; diff --git a/source/objects/CalDAV/CalDAV.cpp b/source/objects/CalDAV/CalDAV.cpp index bc62ff2..d103c81 100644 --- a/source/objects/CalDAV/CalDAV.cpp +++ b/source/objects/CalDAV/CalDAV.cpp @@ -908,6 +908,101 @@ CalDAVServerResult CalDAV::DeleteCalendar(string *CalendarHREF){ } +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 = "\n" + "\n" + " \n" + " \n" + " \n" + " "; + EntryETagRequest += (*CalendarEntryHREF); + EntryETagRequest += "\n" + ""; + + 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. diff --git a/source/objects/CalDAV/CalDAV.h b/source/objects/CalDAV/CalDAV.h index f990b76..d632a60 100644 --- a/source/objects/CalDAV/CalDAV.h +++ b/source/objects/CalDAV/CalDAV.h @@ -123,6 +123,7 @@ class CalDAV{ string ProcessXMLUserPrincipal(); string ProcessXMLCalendarHome(); CalDAVCalendarList ProcessXMLCalendarList(); + string ProcessXMLEntryETag(); bool MatchXMLNameTransverse(xmlNodePtr *NodePtr, string NodeName); bool MatchXMLName(xmlNodePtr *NodePtrOriginal, string NodeName); string FetchXMLData(xmlNodePtr *NodePtr); @@ -172,6 +173,8 @@ class CalDAV{ string GetUserPrincipal(); string GetCalendarHome(string UserPrincipalURI); + + CalDAVServerResult GetEntryETag(string *CalendarEntryHREF, string *ETagValue); }; diff --git a/source/tests/xestiacalendar_caldav.h b/source/tests/xestiacalendar_caldav.h index bbbef3d..e07fe2a 100644 --- a/source/tests/xestiacalendar_caldav.h +++ b/source/tests/xestiacalendar_caldav.h @@ -921,6 +921,78 @@ TEST(CalDAV, AddEntry){ EntryCalendarHREFProcessing = EntryAddHREF; } + +TEST(CalDAV, GetEntryETag){ + + CalDAVConnectionData ConnNormal; + string CurrentUserPrincipal; + + bool ValidDataNormal = false; + + // Attempt to read the caldavtest.auth file. + + ProcessConnectionDataFileResult DataFileResult = ProcessConnectionDataFile("caldavtest.auth", &ConnNormal); + if (DataFileResult == PROCESSCONNECTIONDATAFILE_OK){ + ValidDataNormal = true; + } + + ASSERT_EQ(true, ValidDataNormal); + + // Setup the connection. + + CalDAV ServerConnection; + + ServerConnection.SetupConnectionData(&ConnNormal); + + // Verify the connection settings. + + CalDAVStatus CalDAVStatus = ServerConnection.GetConnectionData(); + + ASSERT_EQ(CalDAVStatus.Hostname, ConnNormal.Hostname); + ASSERT_EQ(CalDAVStatus.Username, ConnNormal.Username); + ASSERT_EQ(CalDAVStatus.Port, ConnNormal.Port); + ASSERT_EQ(CalDAVStatus.Prefix, ConnNormal.Prefix); + ASSERT_EQ(CalDAVStatus.UseSSL, ConnNormal.UseSSL); + + // Connect to the server. + + CalDAVServerResult ConnResult = ServerConnection.Connect(); + + EXPECT_EQ(CALDAVQUERYRESULT_OK, ConnResult.Result); + ASSERT_EQ(200, ConnResult.HTTPCode); + ASSERT_EQ(CURLE_OK, ConnResult.Code); + + // Check that the server supports CalDAV. + + CalDAVServerSupport ConnSupport = ServerConnection.GetServerSupport(); + ConnResult = ServerConnection.GetServerResult(); + + EXPECT_EQ(CALDAVQUERYRESULT_OK, ConnResult.Result); + ASSERT_EQ(200, ConnResult.HTTPCode); + ASSERT_EQ(CURLE_OK, ConnResult.Code); + ASSERT_EQ(true, ConnSupport.BasicSupport); + + // Get the list of calendars. + + CalDAVCalendarList CalendarList = ServerConnection.GetCalendars(); + + // Check the response result from the server. + + ConnResult = ServerConnection.GetServerResult(); + + EXPECT_EQ(CALDAVQUERYRESULT_OK, ConnResult.Result); + ASSERT_EQ(207, ConnResult.HTTPCode); + ASSERT_EQ(CURLE_OK, ConnResult.Code); + + string ETagValue; + + ConnResult = ServerConnection.GetEntryETag(&EntryCalendarHREFProcessing, &ETagValue); + + EXPECT_EQ(CALDAVQUERYRESULT_OK, ConnResult.Result); + ASSERT_EQ(207, ConnResult.HTTPCode); + ASSERT_EQ(CURLE_OK, ConnResult.Code); + +} } -- 2.39.2