From fb7334af110912e40389f059adcf58c4a289a881 Mon Sep 17 00:00:00 2001 From: Steve Brokenshire Date: Sun, 17 Apr 2016 16:59:23 +0100 Subject: [PATCH] Added code and unit tests to list calendars from the server. --- .../objects/CalDAV/CalDAV-XMLProcessing.cpp | 237 ++++++++++++++++++ source/objects/CalDAV/CalDAV.cpp | 18 +- source/objects/CalDAV/CalDAV.h | 12 + source/tests/xestiacalendar_caldav.h | 18 -- 4 files changed, 261 insertions(+), 24 deletions(-) diff --git a/source/objects/CalDAV/CalDAV-XMLProcessing.cpp b/source/objects/CalDAV/CalDAV-XMLProcessing.cpp index d29f058..38e26c7 100644 --- a/source/objects/CalDAV/CalDAV-XMLProcessing.cpp +++ b/source/objects/CalDAV/CalDAV-XMLProcessing.cpp @@ -148,6 +148,213 @@ string CalDAV::ProcessXMLCalendarHome(){ } +CalDAVCalendarList CalDAV::ProcessXMLCalendarList(){ + + CalDAVCalendarList CalendarList; + + xmlDocPtr xmlCalDAVDoc; + xmlCalDAVDoc = xmlReadMemory(ServerData.c_str(), (int)ServerData.size(), "noname.xml", NULL, 0); + + xmlNodePtr NodeSeek = NULL; + xmlNodePtr NodeResponse = NULL; + xmlNodePtr NodeMatch = NULL; + xmlNodePtr NodeData = NULL; + bool NodeFound = false; + int ResponseCount = 0; + + // 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") + ){ + + NodeResponse = NodeSeek->children; + NodeFound = true; + break; + + } + + } + + for (NodeResponse = NodeSeek->children; + NodeResponse != nullptr; + NodeResponse = NodeResponse->next) + { + + // Go through each of the responses and find the calendars. + + NodeMatch = xmlCopyNode(NodeResponse, 1); + + if (MatchXMLName(&NodeMatch, "response")){ + NodeData = xmlCopyNode(NodeMatch, 1); + + // Check the resource type is a calendar. + + if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "resourcetype")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "calendar")){ continue; } + + // Get the HREF. + + NodeData = xmlCopyNode(NodeMatch, 1); + + if (!MatchXMLNameTransverse(&NodeData, "href")){ continue; } + + string HREFAddress = FetchXMLData(&NodeData); + + // Get the calendar name. + + NodeData = xmlCopyNode(NodeMatch, 1); + + if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "displayname")){ continue; } + + string CalendarName = FetchXMLData(&NodeData); + + // Get the calendar description. + + NodeData = xmlCopyNode(NodeMatch, 1); + + string CalendarDescription = ""; + + if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; } + if (MatchXMLNameTransverse(&NodeData, "calendar-description")){ + + CalendarDescription = FetchXMLData(&NodeData); + + } + + // Get the calendar colour. + + NodeData = xmlCopyNode(NodeMatch, 1); + + Colour CalendarColour; + bool ColourResult = false; + + if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; } + if (MatchXMLNameTransverse(&NodeData, "calendar-color")){ + + string CalendarColourString = ""; + string CalendarColourHexValue = ""; + int ColourNumber; + bool KeepRunning = true; + + CalendarColourString = FetchXMLData(&NodeData); + + while(KeepRunning == true){ + + if (CalendarColourString.substr(0,1) == "#" && CalendarColourString.length() == 9){ + + // Get the red colour. + + CalendarColourHexValue = CalendarColourString.substr(1,2); + if (!HexToInt(&CalendarColourHexValue, &ColourNumber)){ break; } + CalendarColour.red = ColourNumber; + + // Get the green colour. + + CalendarColourHexValue = CalendarColourString.substr(3,2); + if (!HexToInt(&CalendarColourHexValue, &ColourNumber)){ break; } + CalendarColour.green = ColourNumber; + + // Get the blue colour. + + CalendarColourHexValue = CalendarColourString.substr(5,2); + if (!HexToInt(&CalendarColourHexValue, &ColourNumber)){ break; }; + CalendarColour.blue = ColourNumber; + + // Get the alpha. + + CalendarColourHexValue = CalendarColourString.substr(7,2); + if (!HexToInt(&CalendarColourHexValue, &ColourNumber)){ break; }; + CalendarColour.alpha = ColourNumber; + + ColourResult = true; + + } else { + + ColourResult = false; + + } + + break; + + } + + } + + if (ColourResult == false){ + + CalendarColour.red = 0; + CalendarColour.blue = 0; + CalendarColour.green = 0; + CalendarColour.alpha = 0; + + } + + // Get the calendar order. + + NodeData = xmlCopyNode(NodeMatch, 1); + + int CalendarOrder = 0; + + if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; } + if (MatchXMLNameTransverse(&NodeData, "calendar-order")){ + + string CalendarOrderString = FetchXMLData(&NodeData); + if (!HexToInt(&CalendarOrderString, &CalendarOrder)){ + CalendarOrder = 0; + } + + } + + // Get the calendar tag. + + NodeData = xmlCopyNode(NodeMatch, 1); + + string CalendarTag = ""; + + if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; } + if (MatchXMLNameTransverse(&NodeData, "getctag")){ + + CalendarTag = FetchXMLData(&NodeData); + + } + + // Insert the calendar information into the + // list if all the information is there. + + CalendarList.Name.insert(make_pair(ResponseCount, CalendarName)); + CalendarList.Description.insert(make_pair(ResponseCount, CalendarDescription)); + CalendarList.HREF.insert(make_pair(ResponseCount, HREFAddress)); + CalendarList.CalColour.insert(make_pair(ResponseCount, CalendarColour)); + CalendarList.Order.insert(make_pair(ResponseCount, CalendarOrder)); + CalendarList.Tag.insert(make_pair(ResponseCount, CalendarTag)); + + ResponseCount++; + + } + + } + + xmlFreeDoc(xmlCalDAVDoc); + + return CalendarList; + +} + bool CalDAV::MatchXMLNameTransverse(xmlNodePtr *NodePtr, string NodeName){ string NodeNameSmallD = "d:" + NodeName; @@ -173,6 +380,36 @@ bool CalDAV::MatchXMLNameTransverse(xmlNodePtr *NodePtr, string NodeName){ } +bool CalDAV::MatchXMLName(xmlNodePtr *NodePtrOriginal, string NodeName){ + + if (NodePtrOriginal == nullptr){ + + return false; + + } + + string NodeNameSmallD = "d:" + NodeName; + string NodeNameLargeD = "D:" + NodeName; + + xmlNodePtr *NodePtr = NodePtrOriginal; + + if (!xmlStrcmp((*NodePtr)->name, (const xmlChar *)NodeName.c_str()) || + !xmlStrcmp((*NodePtr)->name, (const xmlChar *)NodeNameSmallD.c_str()) || + !xmlStrcmp((*NodePtr)->name, (const xmlChar *)NodeNameLargeD.c_str()) + ){ + + return true; + + } else { + + return false; + + } + + return false; + +} + string CalDAV::FetchXMLData(xmlNodePtr *NodePtr){ for ((*NodePtr) = (*NodePtr)->children; diff --git a/source/objects/CalDAV/CalDAV.cpp b/source/objects/CalDAV/CalDAV.cpp index a34ca07..51a1ec6 100644 --- a/source/objects/CalDAV/CalDAV.cpp +++ b/source/objects/CalDAV/CalDAV.cpp @@ -467,12 +467,8 @@ CalDAVCalendarList CalDAV::GetCalendars(){ string CalendarHomeURI = ""; CalendarHomeURI = GetCalendarHome(UserPrincipalURI); - cout << ServerData << endl; - string CalendarListURLAddress = BuildServerAddress(&ConnectionData, CalendarHomeURI); - cout << CalendarListURLAddress << endl; - string CalendarListRequest = "\n" "\n" @@ -483,6 +479,7 @@ CalDAVCalendarList CalDAV::GetCalendars(){ " \n" " \n" " \n" + " \n" " \n" ""; @@ -511,8 +508,6 @@ CalDAVCalendarList CalDAV::GetCalendars(){ CURLcode ServerResult = curl_easy_perform(ConnectionHandle); - cout << ServerData << endl; - //ServerList = ProcessXMLCalendarList(); // Restore the original settings. @@ -524,6 +519,17 @@ CalDAVCalendarList CalDAV::GetCalendars(){ curl_easy_setopt(ConnectionHandle, CURLOPT_READDATA, NULL); curl_easy_setopt(ConnectionHandle, CURLOPT_READFUNCTION, NULL); + // Process the received XML data into a list of calendars + // and locations. + + if (ServerResult != CURLE_OK){ + + return ServerList; + + } + + ServerList = ProcessXMLCalendarList(); + return ServerList; } diff --git a/source/objects/CalDAV/CalDAV.h b/source/objects/CalDAV/CalDAV.h index a10c468..aee045a 100644 --- a/source/objects/CalDAV/CalDAV.h +++ b/source/objects/CalDAV/CalDAV.h @@ -26,6 +26,9 @@ #include #include #include +#include +#include "../../common/colour.h" +#include "../../common/text.h" using namespace std; @@ -40,6 +43,13 @@ enum CalDAVQueryResult { }; struct CalDAVCalendarList { + + map Name; + map HREF; + map Order; + map Description; + map CalColour; + map Tag; }; @@ -111,7 +121,9 @@ class CalDAV{ private: string ProcessXMLUserPrincipal(); string ProcessXMLCalendarHome(); + CalDAVCalendarList ProcessXMLCalendarList(); bool MatchXMLNameTransverse(xmlNodePtr *NodePtr, string NodeName); + bool MatchXMLName(xmlNodePtr *NodePtrOriginal, string NodeName); string FetchXMLData(xmlNodePtr *NodePtr); CalDAVConnectionData ConnectionData; diff --git a/source/tests/xestiacalendar_caldav.h b/source/tests/xestiacalendar_caldav.h index fc5a501..8c9860b 100644 --- a/source/tests/xestiacalendar_caldav.h +++ b/source/tests/xestiacalendar_caldav.h @@ -497,26 +497,8 @@ TEST(CalDAV, ListCalendars){ ConnResult = ServerConnection.GetServerResult(); - EXPECT_EQ(CALDAVQUERYRESULT_OK, ConnResult.Result); - ASSERT_EQ(200, ConnResult.HTTPCode); - ASSERT_EQ(CURLE_OK, ConnResult.Code); - - // Get the user principal. - - CurrentUserPrincipal = ServerConnection.GetUserPrincipal(); - - // Check the response from the server. - - ConnResult = ServerConnection.GetServerResult(); - EXPECT_EQ(CALDAVQUERYRESULT_OK, ConnResult.Result); ASSERT_EQ(207, ConnResult.HTTPCode); ASSERT_EQ(CURLE_OK, ConnResult.Code); - // Get the list of calendars. - - - - - } \ No newline at end of file -- 2.39.2