1 // CalDAV-XMLProcessing.cpp - CalDAV Connection Object - XML Processing.
3 // (c) 2016 Xestia Software Development.
5 // This file is part of Xestia Calendar.
7 // Xestia Address Book 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.
11 // Xestia Address Book 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.
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/>
23 string CalDAV::ProcessXMLUserPrincipal(){
25 string UserPrincipalURI;
27 xmlDocPtr xmlCalDAVDoc;
28 xmlCalDAVDoc = xmlReadMemory(ServerData.c_str(), (int)ServerData.size(), "noname.xml", NULL, 0);
31 bool NodeFound = false;
33 // Start with the first node, look for multistatus.
35 for (NodeSeek = xmlCalDAVDoc->children;
37 NodeSeek = NodeSeek->next)
40 if (!xmlStrcmp(NodeSeek->name, (const xmlChar *)"multistatus") ||
41 !xmlStrcmp(NodeSeek->name, (const xmlChar *)"d:multistatus") ||
42 !xmlStrcmp(NodeSeek->name, (const xmlChar *)"D:multistatus")
54 if (NodeFound == false){ return UserPrincipalURI; } else { NodeFound = false; }
55 NodeFound = MatchXMLNameTransverse(&NodeSeek, "response");
59 if (NodeFound == false){ return UserPrincipalURI; } else { NodeFound = false; }
60 NodeFound = MatchXMLNameTransverse(&NodeSeek, "propstat");
64 if (NodeFound == false){ return UserPrincipalURI; } else { NodeFound = false; }
65 NodeFound = MatchXMLNameTransverse(&NodeSeek, "prop");
67 // Look for current-user-principal.
69 if (NodeFound == false){ return UserPrincipalURI; } else { NodeFound = false; }
70 NodeFound = MatchXMLNameTransverse(&NodeSeek, "current-user-principal");
74 if (NodeFound == false){ return UserPrincipalURI; } else { NodeFound = false; }
75 NodeFound = MatchXMLNameTransverse(&NodeSeek, "href");
77 // Get the data from href.
79 UserPrincipalURI = FetchXMLData(&NodeSeek);
81 xmlFreeDoc(xmlCalDAVDoc);
83 return UserPrincipalURI;
87 string CalDAV::ProcessXMLCalendarHome(){
89 string CalendarHomeURI;
91 xmlDocPtr xmlCalDAVDoc;
92 xmlCalDAVDoc = xmlReadMemory(ServerData.c_str(), (int)ServerData.size(), "noname.xml", NULL, 0);
95 bool NodeFound = false;
97 // Start with the first node, look for multistatus.
99 for (NodeSeek = xmlCalDAVDoc->children;
101 NodeSeek = NodeSeek->next)
104 if (!xmlStrcmp(NodeSeek->name, (const xmlChar *)"multistatus") ||
105 !xmlStrcmp(NodeSeek->name, (const xmlChar *)"d:multistatus") ||
106 !xmlStrcmp(NodeSeek->name, (const xmlChar *)"D:multistatus")
116 // Look for response.
118 if (NodeFound == false){ return CalendarHomeURI; } else { NodeFound = false; }
119 NodeFound = MatchXMLNameTransverse(&NodeSeek, "response");
121 // Look for propstat.
123 if (NodeFound == false){ return CalendarHomeURI; } else { NodeFound = false; }
124 NodeFound = MatchXMLNameTransverse(&NodeSeek, "propstat");
128 if (NodeFound == false){ return CalendarHomeURI; } else { NodeFound = false; }
129 NodeFound = MatchXMLNameTransverse(&NodeSeek, "prop");
131 // Look for calendar-home-set.
133 if (NodeFound == false){ return CalendarHomeURI; } else { NodeFound = false; }
134 NodeFound = MatchXMLNameTransverse(&NodeSeek, "calendar-home-set");
138 if (NodeFound == false){ return CalendarHomeURI; } else { NodeFound = false; }
139 NodeFound = MatchXMLNameTransverse(&NodeSeek, "href");
141 // Get the data from href.
143 CalendarHomeURI = FetchXMLData(&NodeSeek);
145 xmlFreeDoc(xmlCalDAVDoc);
147 return CalendarHomeURI;
151 CalDAVCalendarList CalDAV::ProcessXMLCalendarList(){
153 CalDAVCalendarList CalendarList;
155 xmlDocPtr xmlCalDAVDoc;
156 xmlCalDAVDoc = xmlReadMemory(ServerData.c_str(), (int)ServerData.size(), "noname.xml", NULL, 0);
158 xmlNodePtr NodeSeek = NULL;
159 xmlNodePtr NodeResponse = NULL;
160 xmlNodePtr NodeMatch = NULL;
161 xmlNodePtr NodeData = NULL;
162 bool NodeFound = false;
163 int ResponseCount = 0;
165 // Start with the first node, look for multistatus.
167 for (NodeSeek = xmlCalDAVDoc->children;
169 NodeSeek = NodeSeek->next)
172 if (!xmlStrcmp(NodeSeek->name, (const xmlChar *)"multistatus") ||
173 !xmlStrcmp(NodeSeek->name, (const xmlChar *)"d:multistatus") ||
174 !xmlStrcmp(NodeSeek->name, (const xmlChar *)"D:multistatus")
177 NodeResponse = NodeSeek->children;
185 for (NodeResponse = NodeSeek->children;
186 NodeResponse != nullptr;
187 NodeResponse = NodeResponse->next)
190 // Go through each of the responses and find the calendars.
192 NodeMatch = xmlCopyNode(NodeResponse, 1);
194 if (MatchXMLName(&NodeMatch, "response")){
195 \r NodeData = xmlCopyNode(NodeMatch, 1);
197 // Check the resource type is a calendar.
199 if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; }
200 if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; }
201 if (!MatchXMLNameTransverse(&NodeData, "resourcetype")){ continue; }
202 if (!MatchXMLNameTransverse(&NodeData, "calendar")){ continue; }
206 NodeData = xmlCopyNode(NodeMatch, 1);
208 if (!MatchXMLNameTransverse(&NodeData, "href")){ continue; }
210 string HREFAddress = FetchXMLData(&NodeData);
212 // Get the calendar name.
214 NodeData = xmlCopyNode(NodeMatch, 1);
216 if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; }
217 if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; }
218 if (!MatchXMLNameTransverse(&NodeData, "displayname")){ continue; }
220 string CalendarName = FetchXMLData(&NodeData);
222 // Get the calendar description.
224 NodeData = xmlCopyNode(NodeMatch, 1);
226 string CalendarDescription = "";
228 if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; }
229 if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; }
230 if (MatchXMLNameTransverse(&NodeData, "calendar-description")){
232 CalendarDescription = FetchXMLData(&NodeData);
236 // Get the calendar colour.
238 NodeData = xmlCopyNode(NodeMatch, 1);
240 Colour CalendarColour;
241 bool ColourResult = false;
243 if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; }
244 if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; }
245 if (MatchXMLNameTransverse(&NodeData, "calendar-color")){
247 string CalendarColourString = "";
248 string CalendarColourHexValue = "";
250 bool KeepRunning = true;
252 CalendarColourString = FetchXMLData(&NodeData);
254 while(KeepRunning == true){
256 if (CalendarColourString.substr(0,1) == "#" && CalendarColourString.length() == 9){
258 // Get the red colour.
260 CalendarColourHexValue = CalendarColourString.substr(1,2);
261 if (!HexToInt(&CalendarColourHexValue, &ColourNumber)){ break; }
262 CalendarColour.red = ColourNumber;
264 // Get the green colour.
266 CalendarColourHexValue = CalendarColourString.substr(3,2);
267 if (!HexToInt(&CalendarColourHexValue, &ColourNumber)){ break; }
268 CalendarColour.green = ColourNumber;
270 // Get the blue colour.
272 CalendarColourHexValue = CalendarColourString.substr(5,2);
273 if (!HexToInt(&CalendarColourHexValue, &ColourNumber)){ break; };
274 CalendarColour.blue = ColourNumber;
278 CalendarColourHexValue = CalendarColourString.substr(7,2);
279 if (!HexToInt(&CalendarColourHexValue, &ColourNumber)){ break; };
280 CalendarColour.alpha = ColourNumber;
286 ColourResult = false;
296 if (ColourResult == false){
298 CalendarColour.red = 0;
299 CalendarColour.blue = 0;
300 CalendarColour.green = 0;
301 CalendarColour.alpha = 0;
305 // Get the calendar order.
307 NodeData = xmlCopyNode(NodeMatch, 1);
309 int CalendarOrder = 0;
311 if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; }
312 if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; }
313 if (MatchXMLNameTransverse(&NodeData, "calendar-order")){
315 string CalendarOrderString = FetchXMLData(&NodeData);
316 if (!HexToInt(&CalendarOrderString, &CalendarOrder)){
322 // Get the calendar tag.
324 NodeData = xmlCopyNode(NodeMatch, 1);
326 string CalendarTag = "";
328 if (!MatchXMLNameTransverse(&NodeData, "propstat")){ continue; }
329 if (!MatchXMLNameTransverse(&NodeData, "prop")){ continue; }
330 if (MatchXMLNameTransverse(&NodeData, "getctag")){
332 CalendarTag = FetchXMLData(&NodeData);
336 // Insert the calendar information into the
337 // list if all the information is there.
339 CalendarList.Name.insert(make_pair(ResponseCount, CalendarName));
340 CalendarList.Description.insert(make_pair(ResponseCount, CalendarDescription));
341 CalendarList.HREF.insert(make_pair(ResponseCount, HREFAddress));
342 CalendarList.CalColour.insert(make_pair(ResponseCount, CalendarColour));
343 CalendarList.Order.insert(make_pair(ResponseCount, CalendarOrder));
344 CalendarList.Tag.insert(make_pair(ResponseCount, CalendarTag));
352 xmlFreeDoc(xmlCalDAVDoc);
358 bool CalDAV::MatchXMLNameTransverse(xmlNodePtr *NodePtr, string NodeName){
360 string NodeNameSmallD = "d:" + NodeName;
361 string NodeNameLargeD = "D:" + NodeName;
363 for ((*NodePtr) = (*NodePtr)->children;
365 (*NodePtr) = (*NodePtr)->next)
368 if (!xmlStrcmp((*NodePtr)->name, (const xmlChar *)NodeName.c_str()) ||
369 !xmlStrcmp((*NodePtr)->name, (const xmlChar *)NodeNameSmallD.c_str()) ||
370 !xmlStrcmp((*NodePtr)->name, (const xmlChar *)NodeNameLargeD.c_str())
383 bool CalDAV::MatchXMLName(xmlNodePtr *NodePtrOriginal, string NodeName){
385 if (NodePtrOriginal == nullptr){
391 string NodeNameSmallD = "d:" + NodeName;
392 string NodeNameLargeD = "D:" + NodeName;
394 xmlNodePtr *NodePtr = NodePtrOriginal;
396 if (!xmlStrcmp((*NodePtr)->name, (const xmlChar *)NodeName.c_str()) ||
397 !xmlStrcmp((*NodePtr)->name, (const xmlChar *)NodeNameSmallD.c_str()) ||
398 !xmlStrcmp((*NodePtr)->name, (const xmlChar *)NodeNameLargeD.c_str())
413 string CalDAV::FetchXMLData(xmlNodePtr *NodePtr){
415 for ((*NodePtr) = (*NodePtr)->children;
417 (*NodePtr) = (*NodePtr)->next)
420 return (const char*)(*NodePtr)->content;