// CalendarJournal.cpp - CalendarJournal class functions // // (c) 2016-2017 Xestia Software Development. // // This file is part of Xestia Calendar. // // 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 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. // // You should have received a copy of the GNU General Public License along // with Xestia Calendar. If not, see #include "CalendarJournal.h" using namespace std; CalendarObjectValidResult CalendarJournalObject::ValidObject(){ bool validBegin = false; bool validEnd = false; bool validDateTimeStamp = false; bool validUniqueID = false; int seekCount = 0; string propertyName; // Look for BEGIN:VJOURNAL. for (vector::iterator iter = objectName.begin(); iter != objectName.end(); iter++){ if (objectName[seekCount] == "BEGIN" && objectData[seekCount] == "VJOURNAL"){ if (validBegin == false){ validBegin = true; } else { return CALENDAROBJECTVALID_INVALIDFORMAT; } } if (objectName[seekCount] == "END" && objectData[seekCount] == "VJOURNAL" && validBegin == false){ return CALENDAROBJECTVALID_INVALIDFORMAT; } seekCount++; } seekCount = 0; // Look for DTSTAMP. for (vector::iterator iter = objectName.begin(); iter != objectName.end(); iter++){ try{ propertyName = objectName[seekCount].substr(0,7); } catch(const out_of_range& oor){ continue; } if (propertyName == "DTSTAMP"){ if (validDateTimeStamp == false){ validDateTimeStamp = true; } else { return CALENDAROBJECTVALID_INVALIDFORMAT; } } seekCount++; } seekCount = 0; // Look for UID. for (vector::iterator iter = objectName.begin(); iter != objectName.end(); iter++){ try{ propertyName = objectName[seekCount].substr(0,3); } catch(const out_of_range& oor){ continue; } if (propertyName == "UID"){ if (validUniqueID == false){ validUniqueID = true; } else { return CALENDAROBJECTVALID_INVALIDFORMAT; } } seekCount++; } seekCount = 0; // Look for END:VJOURNAL. for (vector::iterator iter = objectName.begin(); iter != objectName.end(); iter++){ if (objectName[seekCount] == "END" && objectData[seekCount] == "VJOURNAL"){ if (validEnd == false){ validEnd = true; } else { return CALENDAROBJECTVALID_INVALIDFORMAT; } } seekCount++; } // Check if the VJOURNAL is valid. if (validBegin == true && validEnd == true && validDateTimeStamp == true && validUniqueID == true){ return CALENDAROBJECTVALID_OK; } else { return CALENDAROBJECTVALID_INVALIDFORMAT; } } void CalendarJournalObject::ProcessData(){ // Process the data. multimap dataReceived; map propertyData; string *propertyNameData = nullptr; int objectSeekCount = 0; // Get the Date Time Stamp (DTSTAMP). dataReceived = ProcessTextVectors(&objectName, &objectData, false, "DTSTAMP"); // Process the data from DTSTAMP. if (dataReceived.begin() != dataReceived.end()){ try { dateTimeStampTokens = dataReceived.begin()->first.substr(8); } catch(const out_of_range &oor){ // Do nothing as there is no data. } dateTimeStampData = dataReceived.begin()->second; } // Get the Unique ID (UID). dataReceived = ProcessTextVectors(&objectName, &objectData, false, "UID"); // Process the data from UID. if (dataReceived.begin() != dataReceived.end()){ try { uniqueIDTokens = dataReceived.begin()->first.substr(4); } catch(const out_of_range &oor){ // Do nothing as there is no data. } uniqueID = dataReceived.begin()->second; } // Process the data from CLASS. dataReceived = ProcessTextVectors(&objectName, &objectData, false, "CLASS"); if (dataReceived.begin() != dataReceived.end()){ try { classDataTokens = dataReceived.begin()->first.substr(6); } catch(const out_of_range &oor){ // Do nothing as there is no data. } classData = dataReceived.begin()->second; } // Get the Date Time Start value. dataReceived = ProcessTextVectors(&objectName, &objectData, false, "DTSTART"); // Process the data from DTSTART. if (dataReceived.begin() != dataReceived.end()){ bool tokenData = false; string propertyTokens; propertyNameData = (string*)&dataReceived.begin()->first; propertyData = SplitValues(*propertyNameData); for(map::iterator iter = propertyData.begin(); iter != propertyData.end(); iter++){ if (iter->first == "VALUE"){ dateTimeStartDataValue = iter->second; } else if (iter->first == "TZID"){ dateTimeStartDataTimeZoneID = iter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += iter->first; propertyTokens += "="; propertyTokens += iter->second; } } if (propertyTokens.size() > 0){ dateTimeStartDataTokens = propertyTokens; } dateTimeStartData = dataReceived.begin()->second; } // Process the data from LAST-MODIFIED. dataReceived = ProcessTextVectors(&objectName, &objectData, false, "LAST-MODIFIED"); if (dataReceived.begin() != dataReceived.end()){ try { lastModifiedTokens = dataReceived.begin()->first.substr(14); } catch(const out_of_range &oor){ // Do nothing as there is no data. } lastModifiedData = dataReceived.begin()->second; } // Process the data from ORGANIZER. dataReceived = ProcessTextVectors(&objectName, &objectData, false, "ORGANIZER"); if (dataReceived.begin() != dataReceived.end()){ bool tokenData = false; string propertyTokens; propertyNameData = (string*)&dataReceived.begin()->first; propertyData = SplitValues(*propertyNameData); for(map::iterator iter = propertyData.begin(); iter != propertyData.end(); iter++){ if (iter->first == "CN"){ organiserDataCommonName = iter->second; } else if (iter->first == "DIR"){ organiserDataDirectoryEntry = iter->second; } else if (iter->first == "SENT-BY"){ organiserDataSentByParam = iter->second; } else if (iter->first == "LANGUAGE"){ organiserDataLanguage = iter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += iter->first; propertyTokens += "="; propertyTokens += iter->second; } } if (propertyTokens.size() > 0){ organiserDataTokens = propertyTokens; } organiserData = dataReceived.begin()->second; } // Process the data from RECURRENCE-ID. dataReceived = ProcessTextVectors(&objectName, &objectData, false, "RECURRENCE-ID"); if (dataReceived.begin() != dataReceived.end()){ bool tokenData = false; string propertyTokens; propertyNameData = (string*)&dataReceived.begin()->first; propertyData = SplitValues(*propertyNameData); for(map::iterator iter = propertyData.begin(); iter != propertyData.end(); iter++){ if (iter->first == "TZID"){ recurranceIDDataTimeZoneParam = iter->second; } else if (iter->first == "VALUE"){ recurranceIDDataValue = iter->second; } else if (iter->first == "RANGE"){ recurranceIDDataRangeParam = iter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += iter->first; propertyTokens += "="; propertyTokens += iter->second; } } if (propertyTokens.size() > 0){ recurranceIDDataTokens = propertyTokens; } recurranceIDData = dataReceived.begin()->second; } // Process the data from SEQUENCE. dataReceived = ProcessTextVectors(&objectName, &objectData, false, "SEQUENCE"); if (dataReceived.begin() != dataReceived.end()){ try { sequenceTokens = dataReceived.begin()->first.substr(9); } catch(const out_of_range &oor){ // Do nothing as there is no data. } try { sequenceData = stoi(dataReceived.begin()->second); } catch(const invalid_argument &oor){ sequenceTokens.clear(); } } // Process the data from STATUS. dataReceived = ProcessTextVectors(&objectName, &objectData, false, "STATUS"); if (dataReceived.begin() != dataReceived.end()){ bool tokenData = false; string propertyTokens; propertyNameData = (string*)&dataReceived.begin()->first; propertyData = SplitValues(*propertyNameData); for(map::iterator iter = propertyData.begin(); iter != propertyData.end(); iter++){ if (iter->first == "LANGUAGE"){ statusLanguage = iter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += iter->first; propertyTokens += "="; propertyTokens += iter->second; } } if (propertyTokens.size() > 0){ statusTokens = propertyTokens; } statusData = dataReceived.begin()->second; } // Process the data from SUMMARY. dataReceived = ProcessTextVectors(&objectName, &objectData, false, "SUMMARY"); if (dataReceived.begin() != dataReceived.end()){ bool tokenData = false; string propertyTokens; propertyNameData = (string*)&dataReceived.begin()->first; propertyData = SplitValues(*propertyNameData); for(map::iterator iter = propertyData.begin(); iter != propertyData.end(); iter++){ if (iter->first == "ALTREP"){ summaryDataAltRep = iter->second; } else if (iter->first == "LANGUAGE"){ summaryDataLanguage = iter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += iter->first; propertyTokens += "="; propertyTokens += iter->second; } } if (propertyTokens.size() > 0){ summaryDataTokens = propertyTokens; } summaryData = dataReceived.begin()->second; } // Process the data from URL. dataReceived = ProcessTextVectors(&objectName, &objectData, false, "URL"); if (dataReceived.begin() != dataReceived.end()){ try { urlDataTokens = dataReceived.begin()->first.substr(4); } catch(const out_of_range &oor){ // Do nothing as there is no data. } urlData = dataReceived.begin()->second; } // Process the data from RRULE. dataReceived = ProcessTextVectors(&objectName, &objectData, false, "RRULE"); if (dataReceived.begin() != dataReceived.end()){ try { recurranceRuleDataTokens = dataReceived.begin()->first.substr(6); } catch(const out_of_range &oor){ // Do nothing as there is no data. } recurranceRuleData = dataReceived.begin()->second; } // Process the data from ATTACH. dataReceived = ProcessTextVectors(&objectName, &objectData, true, "ATTACH"); for(multimap::iterator iter = dataReceived.begin(); iter != dataReceived.end(); ++iter){ attachListEncoding.push_back(""); attachListValue.push_back(""); attachListFormatType.push_back(""); attachListTokens.push_back(""); attachList.push_back(""); bool tokenData = false; string propertyTokens; propertyNameData = (string*)&iter->first; propertyData = SplitValues(*propertyNameData); for(map::iterator dataiter = propertyData.begin(); dataiter != propertyData.end(); dataiter++){ if (dataiter->first == "ENCODING"){ attachListEncoding[objectSeekCount] = dataiter->second; } else if (dataiter->first == "VALUE"){ attachListValue[objectSeekCount] = dataiter->second; } else if (dataiter->first == "FMTTYPE"){ attachListFormatType[objectSeekCount] = dataiter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += dataiter->first; propertyTokens += "="; propertyTokens += dataiter->second; } } if (propertyTokens.size() > 0){ attachListTokens[objectSeekCount] = propertyTokens; } attachList[objectSeekCount] = iter->second; objectSeekCount++; } // Process the data from ATTENDEE. dataReceived = ProcessTextVectors(&objectName, &objectData, true, "ATTENDEE"); objectSeekCount = 0; for(multimap::iterator iter = dataReceived.begin(); iter != dataReceived.end(); ++iter){ attendeeListMember.push_back(""); attendeeListDelegatedFrom.push_back(""); attendeeListDelegatedTo.push_back(""); attendeeListRole.push_back(""); attendeeListRSVP.push_back(""); attendeeListDirectoryEntry.push_back(""); attendeeListSentBy.push_back(""); attendeeListCommonName.push_back(""); attendeeListCalendarUserType.push_back(""); attendeeListParticipationStatus.push_back(""); attendeeListLanguage.push_back(""); attendeeListTokens.push_back(""); attendeeList.push_back(""); bool tokenData = false; string propertyTokens; propertyNameData = (string*)&iter->first; propertyData = SplitValues(*propertyNameData); for(map::iterator dataiter = propertyData.begin(); dataiter != propertyData.end(); dataiter++){ if (dataiter->first == "CUTYPE"){ attendeeListCalendarUserType[objectSeekCount] = dataiter->second; } else if (dataiter->first == "MEMBER"){ attendeeListMember[objectSeekCount] = dataiter->second; } else if (dataiter->first == "ROLE"){ attendeeListRole[objectSeekCount] = dataiter->second; } else if (dataiter->first == "PARTSTAT"){ attendeeListParticipationStatus[objectSeekCount] = dataiter->second; } else if (dataiter->first == "RSVP"){ attendeeListRSVP[objectSeekCount] = dataiter->second; } else if (dataiter->first == "DELEGATED-TO"){ attendeeListDelegatedTo[objectSeekCount] = dataiter->second; } else if (dataiter->first == "DELEGATED-FROM"){ attendeeListDelegatedFrom[objectSeekCount] = dataiter->second; } else if (dataiter->first == "SENT-BY"){ attendeeListSentBy[objectSeekCount] = dataiter->second; } else if (dataiter->first == "CN"){ attendeeListCommonName[objectSeekCount] = dataiter->second; } else if (dataiter->first == "DIR"){ attendeeListDirectoryEntry[objectSeekCount] = dataiter->second; } else if (dataiter->first == "LANGUAGE"){ attendeeListLanguage[objectSeekCount] = dataiter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += dataiter->first; propertyTokens += "="; propertyTokens += dataiter->second; } } if (propertyTokens.size() > 0){ attendeeListTokens[objectSeekCount] = propertyTokens; } attendeeList[objectSeekCount] = iter->second; objectSeekCount++; } // Process the data from CATEGORIES. dataReceived = ProcessTextVectors(&objectName, &objectData, true, "CATEGORIES"); objectSeekCount = 0; for(multimap::iterator iter = dataReceived.begin(); iter != dataReceived.end(); ++iter){ categoriesListTokens.push_back(""); categoriesListLanguage.push_back(""); categoriesList.push_back(""); bool tokenData = false; string propertyTokens; propertyNameData = (string*)&iter->first; propertyData = SplitValues(*propertyNameData); for(map::iterator dataiter = propertyData.begin(); dataiter != propertyData.end(); dataiter++){ if (dataiter->first == "LANGUAGE"){ categoriesListLanguage[objectSeekCount] = dataiter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += dataiter->first; propertyTokens += "="; propertyTokens += dataiter->second; } } if (propertyTokens.size() > 0){ categoriesListTokens[objectSeekCount] = propertyTokens; } categoriesList[objectSeekCount] = iter->second; objectSeekCount++; } // Process the data from COMMENT. dataReceived = ProcessTextVectors(&objectName, &objectData, true, "COMMENT"); objectSeekCount = 0; for(multimap::iterator iter = dataReceived.begin(); iter != dataReceived.end(); ++iter){ commentListTokens.push_back(""); commentListAltRep.push_back(""); commentListLanguage.push_back(""); commentList.push_back(""); bool tokenData = false; string propertyTokens; propertyNameData = (string*)&iter->first; propertyData = SplitValues(*propertyNameData); for(map::iterator dataiter = propertyData.begin(); dataiter != propertyData.end(); dataiter++){ if (dataiter->first == "ALTREP"){ commentListAltRep[objectSeekCount] = dataiter->second; } else if (dataiter->first == "LANGUAGE"){ commentListLanguage[objectSeekCount] = dataiter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += dataiter->first; propertyTokens += "="; propertyTokens += dataiter->second; } } if (propertyTokens.size() > 0){ commentListTokens[objectSeekCount] = propertyTokens; } commentList[objectSeekCount] = iter->second; objectSeekCount++; } // Process the data from CONTACT. dataReceived = ProcessTextVectors(&objectName, &objectData, true, "CONTACT"); objectSeekCount = 0; for(multimap::iterator iter = dataReceived.begin(); iter != dataReceived.end(); ++iter){ contactListTokens.push_back(""); contactListAltRep.push_back(""); contactListLanguage.push_back(""); contactList.push_back(""); bool tokenData = false; string propertyTokens; propertyNameData = (string*)&iter->first; propertyData = SplitValues(*propertyNameData); for(map::iterator dataiter = propertyData.begin(); dataiter != propertyData.end(); dataiter++){ if (dataiter->first == "ALTREP"){ contactListAltRep[objectSeekCount] = dataiter->second; } else if (dataiter->first == "LANGUAGE"){ contactListLanguage[objectSeekCount] = dataiter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += dataiter->first; propertyTokens += "="; propertyTokens += dataiter->second; } } if (propertyTokens.size() > 0){ contactListTokens[objectSeekCount] = propertyTokens; } contactList[objectSeekCount] = iter->second; objectSeekCount++; } // Process the data from Description. dataReceived = ProcessTextVectors(&objectName, &objectData, true, "DESCRIPTION"); objectSeekCount = 0; for(multimap::iterator iter = dataReceived.begin(); iter != dataReceived.end(); ++iter){ descriptionListTokens.push_back(""); descriptionListAltRep.push_back(""); descriptionListLanguage.push_back(""); descriptionList.push_back(""); bool tokenData = false; string propertyTokens; propertyNameData = (string*)&iter->first; propertyData = SplitValues(*propertyNameData); for(map::iterator dataiter = propertyData.begin(); dataiter != propertyData.end(); dataiter++){ if (dataiter->first == "ALTREP"){ descriptionListAltRep[objectSeekCount] = dataiter->second; } else if (dataiter->first == "LANGUAGE"){ descriptionListLanguage[objectSeekCount] = dataiter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += dataiter->first; propertyTokens += "="; propertyTokens += dataiter->second; } } if (propertyTokens.size() > 0){ descriptionListTokens[objectSeekCount] = propertyTokens; } descriptionList[objectSeekCount] = iter->second; objectSeekCount++; } // Process the data from EXDATE. dataReceived = ProcessTextVectors(&objectName, &objectData, true, "EXDATE"); objectSeekCount = 0; for(multimap::iterator iter = dataReceived.begin(); iter != dataReceived.end(); ++iter){ excludeDateDataTokens.push_back(""); excludeDateDataValue.push_back(""); excludeDateDataTimeZoneParam.push_back(""); excludeDateData.push_back(""); bool tokenData = false; string propertyTokens; propertyNameData = (string*)&iter->first; propertyData = SplitValues(*propertyNameData); for(map::iterator dataiter = propertyData.begin(); dataiter != propertyData.end(); dataiter++){ if (dataiter->first == "VALUE"){ excludeDateDataValue[objectSeekCount] = dataiter->second; } else if (dataiter->first == "TZID"){ excludeDateDataTimeZoneParam[objectSeekCount] = dataiter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += dataiter->first; propertyTokens += "="; propertyTokens += dataiter->second; } } if (propertyTokens.size() > 0){ excludeDateDataTokens[objectSeekCount] = propertyTokens; } excludeDateData[objectSeekCount] = iter->second; objectSeekCount++; } // Process the data from RELATED-TO. dataReceived = ProcessTextVectors(&objectName, &objectData, true, "RELATED-TO"); objectSeekCount = 0; for(multimap::iterator iter = dataReceived.begin(); iter != dataReceived.end(); ++iter){ relatedToDataTokens.push_back(""); relatedToDataRelationType.push_back(""); relatedToData.push_back(""); bool tokenData = false; string propertyTokens; propertyNameData = (string*)&iter->first; propertyData = SplitValues(*propertyNameData); for(map::iterator dataiter = propertyData.begin(); dataiter != propertyData.end(); dataiter++){ if (dataiter->first == "RELTYPE"){ relatedToDataRelationType[objectSeekCount] = dataiter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += dataiter->first; propertyTokens += "="; propertyTokens += dataiter->second; } } if (propertyTokens.size() > 0){ relatedToDataTokens[objectSeekCount] = propertyTokens; } relatedToData[objectSeekCount] = iter->second; objectSeekCount++; } // Process the data from RDATE. dataReceived = ProcessTextVectors(&objectName, &objectData, true, "RDATE"); objectSeekCount = 0; for(multimap::iterator iter = dataReceived.begin(); iter != dataReceived.end(); ++iter){ recurranceDateDataTokens.push_back(""); recurranceDateDataValue.push_back(""); recurranceDateDataTimeZoneParam.push_back(""); recurranceDateData.push_back(""); bool tokenData = false; string propertyTokens; propertyNameData = (string*)&iter->first; propertyData = SplitValues(*propertyNameData); for(map::iterator dataiter = propertyData.begin(); dataiter != propertyData.end(); dataiter++){ if (dataiter->first == "VALUE"){ recurranceDateDataValue[objectSeekCount] = dataiter->second; } else if (dataiter->first == "TZID"){ recurranceDateDataTimeZoneParam[objectSeekCount] = dataiter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += dataiter->first; propertyTokens += "="; propertyTokens += dataiter->second; } } if (propertyTokens.size() > 0){ recurranceDateDataTokens[objectSeekCount] = propertyTokens; } recurranceDateData[objectSeekCount] = iter->second; objectSeekCount++; } // Process the data from REQUEST-STATUS. dataReceived = ProcessTextVectors(&objectName, &objectData, true, "REQUEST-STATUS"); objectSeekCount = 0; for(multimap::iterator iter = dataReceived.begin(); iter != dataReceived.end(); ++iter){ requestStatusTokens.push_back(""); requestStatusLanguage.push_back(""); requestStatusData.push_back(""); bool tokenData = false; string propertyTokens; propertyNameData = (string*)&iter->first; propertyData = SplitValues(*propertyNameData); for(map::iterator dataiter = propertyData.begin(); dataiter != propertyData.end(); dataiter++){ if (dataiter->first == "LANGUAGE"){ requestStatusLanguage[objectSeekCount] = dataiter->second; } else { if (tokenData == false){ tokenData = true; } else { propertyTokens += ";"; } propertyTokens += dataiter->first; propertyTokens += "="; propertyTokens += dataiter->second; } } if (propertyTokens.size() > 0){ requestStatusTokens[objectSeekCount] = propertyTokens; } requestStatusData[objectSeekCount] = iter->second; objectSeekCount++; } objectSeekCount = 0; // Process data from X-* for(vector::iterator iter = objectName.begin(); iter != objectName.end(); ++iter){ bool tokenData = false; string propertyTokens; if (iter->substr(0,2) == "X-" && iter->size() > 2){ xTokensData.push_back(objectData[objectSeekCount]); xTokensDataTokens.push_back(objectName[objectSeekCount]); } objectSeekCount++; } }