X-Git-Url: http://Server1/repobrowser/?a=blobdiff_plain;f=source%2Fobjects%2FCalDAV%2FCalDAV-XMLProcessing.cpp;h=0018ebf6484bde2e8e73dd4b08c750350ac6ea6f;hb=cba151c4b833a26c63984769f921bab5e755decd;hp=d29f0585112512f9e3548caf6086e300a0ad9962;hpb=42cc19d39aad2a362b878f7e56a0ebb7cf94bd4c;p=xestiacalendar%2F.git diff --git a/source/objects/CalDAV/CalDAV-XMLProcessing.cpp b/source/objects/CalDAV/CalDAV-XMLProcessing.cpp index d29f058..0018ebf 100644 --- a/source/objects/CalDAV/CalDAV-XMLProcessing.cpp +++ b/source/objects/CalDAV/CalDAV-XMLProcessing.cpp @@ -1,14 +1,14 @@ // CalDAV-XMLProcessing.cpp - CalDAV Connection Object - XML Processing. // -// (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. @@ -49,6 +49,12 @@ string CalDAV::ProcessXMLUserPrincipal(){ } + if (NodeFound == false){ + + return UserPrincipalURI; + + } + // Look for response. if (NodeFound == false){ return UserPrincipalURI; } else { NodeFound = false; } @@ -113,6 +119,12 @@ string CalDAV::ProcessXMLCalendarHome(){ } + if (NodeFound == false){ + + return CalendarHomeURI; + + } + // Look for response. if (NodeFound == false){ return CalendarHomeURI; } else { NodeFound = false; } @@ -148,6 +160,516 @@ 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; + + } + + } + + if (NodeFound == false){ + + return CalendarList; + + } + + 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); + + } + + // Get the calendar tag URL. + + NodeData = xmlCopyNode(NodeMatch, 1); + + string CalendarTagURL = ""; + + if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; } + if (MatchXMLNameTransverse(&NodeData, "sync-token")){ + + CalendarTagURL = 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)); + CalendarList.TagURL.insert(make_pair(ResponseCount, CalendarTagURL)); + + ResponseCount++; + + } + + } + + xmlFreeDoc(xmlCalDAVDoc); + + return CalendarList; + +} + +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; + + } + + } + + if (NodeFound == false){ + + return EntryETag; + + } + + // 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; + +} + +CalDAVEntryList CalDAV::ProcessXMLEntryList(){ + + CalDAVEntryList EntryList; + + 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; + + } + + } + + if (NodeFound == false){ + + return EntryList; + + } + + 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); + + // Get the HREF. + + NodeData = xmlCopyNode(NodeMatch, 1); + + if (!MatchXMLNameTransverse(&NodeData, "href")){ continue; } + + string HREFAddress = FetchXMLData(&NodeData); + + // Get the calendar data. + + NodeData = xmlCopyNode(NodeMatch, 1); + + string EntryDescription = ""; + + if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; } + if (MatchXMLNameTransverse(&NodeData, "calendar-data")){ + + // Note: libxml2 will strip the CDATA part at the start and + // end of each calendar-data section. + + EntryDescription = FetchXMLData(&NodeData); + + } + + // Get the entry entity tag. + + NodeData = xmlCopyNode(NodeMatch, 1); + + string EntryEntityTag = ""; + + if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; } + if (MatchXMLNameTransverse(&NodeData, "getetag")){ + + EntryEntityTag = FetchXMLData(&NodeData); + + } + + // Insert the calendar information into the + // list if all the information is there. + + EntryList.HREF.insert(make_pair(ResponseCount, HREFAddress)); + EntryList.Data.insert(make_pair(ResponseCount, EntryDescription)); + EntryList.Tag.insert(make_pair(ResponseCount, EntryEntityTag)); + + ResponseCount++; + + } + + } + + xmlFreeDoc(xmlCalDAVDoc); + + return EntryList; + +} + +CalDAVEntryList CalDAV::ProcessXMLSyncTokenList(){ + + CalDAVEntryList EntryList; + + 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; + + } + + } + + if (NodeFound == false){ + + return EntryList; + + } + + 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); + + // Get the HREF. + + NodeData = xmlCopyNode(NodeMatch, 1); + + if (!MatchXMLNameTransverse(&NodeData, "href")){ continue; } + + string HREFAddress = FetchXMLData(&NodeData); + + // Get the entry entity tag. + + NodeData = xmlCopyNode(NodeMatch, 1); + + string EntryEntityTag = ""; + + if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; } + if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; } + if (MatchXMLNameTransverse(&NodeData, "getetag")){ + + EntryEntityTag = FetchXMLData(&NodeData); + + } + + // Insert the calendar information into the + // list if all the information is there. + + EntryList.HREF.insert(make_pair(ResponseCount, HREFAddress)); + EntryList.Data.insert(make_pair(ResponseCount, "")); + EntryList.Tag.insert(make_pair(ResponseCount, EntryEntityTag)); + + ResponseCount++; + + } + + } + + xmlFreeDoc(xmlCalDAVDoc); + + return EntryList; + +} + bool CalDAV::MatchXMLNameTransverse(xmlNodePtr *NodePtr, string NodeName){ string NodeNameSmallD = "d:" + NodeName; @@ -173,6 +695,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;