Home | News | Projects | Releases
Bugs | RFE | Repositories | Help
5a15e1d593c58c1530c75a28e521b2f9a1d1bbde
[xestiacalendar/.git] / source / objects / calendarobject / CalendarObject.cpp
1 // CalendarObject.cpp - CalendarObject class functions
2 //
3 // (c) 2016-2017 Xestia Software Development.
4 //
5 // This file is part of Xestia Calendar.
6 //
7 // Xestia Calendar 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.
10 //
11 // Xestia Calendar 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.
15 //
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/>
19 #include "CalendarObject.h"
20 #include "../../common/file.h"
22 using namespace std;
24 CalendarObjectLoadResult CalendarObject::LoadFile(std::string LoadFilename){
26         // Check if the file exists and return 
27         // CALENDAROBJECTLOAD_CANNOTOPEN if not.
28         
29         if (!FileExists(LoadFilename)){
30                 return CALENDAROBJECTLOAD_MISSING;
31         }
32         
33         ifstream FileStream;
34         string ReceivedStringData = "";
35         
36         FileStream.open(LoadFilename, ifstream::in);
37         
38         if (FileStream.rdstate() & ifstream::failbit){
39                 return CALENDAROBJECTLOAD_CANNOTOPEN;
40         }
42         if (FileStream.rdstate() & ifstream::badbit){
43                 return CALENDAROBJECTLOAD_CANNOTOPEN;
44         }
45         
46         // Read the data into a string.
47         
48         char *BufferRead = new char[256];
49         
50         while (!FileStream.eof()){
51                 
52                 FileStream.getline(BufferRead, 256);
53                 ReceivedStringData.append(BufferRead);
54                 ReceivedStringData.append("\n");
55                 
56         }
57         
58         delete[] BufferRead;
59         
60         CalendarObjectLoadResult StringProcResult = CALENDAROBJECTLOAD_UNITTESTFAIL;
61         
62         StringProcResult = LoadString(&ReceivedStringData);
63         
64         return StringProcResult;
65         
66 }
68 CalendarObjectLoadResult CalendarObject::LoadString(std::string *LoadStringData){
70         bool NewLine = false;
71         bool SkipMode = false;
72         bool ColonFound = false;
73         bool QuoteMode = false;
74         char BufferChar = 0;
75         int StringDataSize = LoadStringData->size();
76         int SeekCount = 0;
77         string PropertyName;
78         string PropertyValue;
80         while (SeekCount < StringDataSize){
81                 
82                 // Check if character is blank or a tab and is the first character
83                 // on a new line.
84                 
85                 if (((*LoadStringData)[SeekCount] == ' ' || 
86                         (*LoadStringData)[SeekCount] == '\t')
87                         && NewLine == true){
88                         
89                         // Character is on a new line and it is a space or
90                         // tab. Ignore this character as it is not part
91                         // of the value.
93                         NewLine = false;
94                                 
95                 } else if ((*LoadStringData)[SeekCount] == '\"'){
96                         
97                         if (QuoteMode == false){
98                                 QuoteMode = true;
99                         } else {
100                                 QuoteMode = false;
101                         }
102                         
103                         BufferChar = (*LoadStringData)[SeekCount];
104                         
105                         if (ColonFound == false){
106                                 PropertyName += BufferChar;
107                         } else {
108                                 PropertyValue += BufferChar;
109                         }
110                         
111                 } else if (NewLine == true){
112                 
113                         // Character is on a new line but not a space or
114                         // tab so check if the colon has been found
115                         // and add the property name and value to
116                         // the lists.
118                         if (ColonFound == true){
119                                 ObjectName.push_back(PropertyName);
120                                 ObjectData.push_back(PropertyValue);
121                         }
122                         
123                         ColonFound = false;
124                         NewLine = false;
125                         PropertyName.clear();
126                         PropertyValue.clear();
127                         
128                         BufferChar = (*LoadStringData)[SeekCount];
129                         PropertyName += BufferChar;                     
130                         
131                 } else if ((*LoadStringData)[SeekCount] == '\n'){
132                 
133                         // Character is the new line character so mark
134                         // the NewLine boolean as true.
135                         
136                         NewLine = true;
137                         
138                 } else if ((*LoadStringData)[SeekCount] == ':' &&
139                                 QuoteMode == false){
140                 
141                         // Character is the colon. Set the colon
142                         // found boolen to true.
143                         
144                         BufferChar = (*LoadStringData)[SeekCount];
145                                         
146                         if (ColonFound == true){
147                                 PropertyValue += BufferChar;
148                         } else {
149                                 ColonFound = true;
150                         }
151                         
152                 } else {
153                         
154                         // Character is not part of a new line and is not
155                         // the new line character itself.
156                         
157                         BufferChar = (*LoadStringData)[SeekCount];
158                         
159                         if (ColonFound == false){
160                                 PropertyName += BufferChar;
161                         } else {
162                                 PropertyValue += BufferChar;
163                         }
164                         
165                 }
166                 
167                 SeekCount++;
168                 
169         }
170         
171         // Finish off processing any data that wasn't processed
172         // when the end of the string was reached.
173         
174         if (ColonFound == true && 
175                 PropertyName.size() > 0 &&
176                 PropertyValue.size() > 0){
177                 
178                 ObjectName.push_back(PropertyName);
179                 ObjectData.push_back(PropertyValue);
180                         
181         }
182         
183         // Check that the object contains valid data.
184         
185         CalendarObjectLoadResult StringProcResult = CALENDAROBJECTLOAD_UNITTESTFAIL;
186         CalendarObjectValidResult BaseDataResult = ValidBaseObject();
187         CalendarObjectValidResult EventDataResult = ValidObject();
188         
189         if (BaseDataResult != CALENDAROBJECTVALID_OK || 
190                 EventDataResult != CALENDAROBJECTVALID_OK){
191                         
192                 StringProcResult = CALENDAROBJECTLOAD_INVALIDFORMAT;
193                         
194         } else {
195                 
196                 StringProcResult = CALENDAROBJECTLOAD_OK;
197                 
198         }
199         
200         ProcessBaseData();
201         ProcessData();
202         
203         return StringProcResult;
204         
207 CalendarObjectValidResult CalendarObject::ValidBaseObject(){
208         
209         bool ValidBegin = false;
210         bool ValidAlarmBegin = false;
211         bool ValidVersion = false;
212         bool ValidEnd = false;
213         int SeekCount = 0;
214         vector<int> DeleteLines;
215         vector<string> AlarmObjectName;
216         vector<string> AlarmObjectData;
217         
218         // Check that the first line contains BEGIN:VCALENDAR
219         // and it only appears once.
220         
221         for (vector<string>::iterator iter = ObjectName.begin();
222                 iter != ObjectName.end(); iter++){
224                 if (ObjectName[SeekCount] == "BEGIN" &&
225                         ObjectData[SeekCount] == "VCALENDAR"){
226                         
227                         if (ValidBegin == false){
228                                 ValidBegin = true;
229                         } else {
230                                 return CALENDAROBJECTVALID_INVALIDFORMAT;
231                         }
232                                 
233                 }
234                 
235                 if (ObjectName[SeekCount] == "END" &&
236                         ObjectData[SeekCount] == "VCALENDAR" &&
237                         ValidBegin == false){
238                 
239                         return CALENDAROBJECTVALID_INVALIDFORMAT;
240                                 
241                 } else if (ObjectName[SeekCount] == "END" &&
242                         ObjectData[SeekCount] == "VALARM" &&
243                         ValidAlarmBegin == false){
245                         return CALENDAROBJECTVALID_INVALIDFORMAT;
246                                 
247                 } else if (ObjectName[SeekCount] == "END" &&
248                         ObjectData[SeekCount] == "VCALENDAR" &&
249                         ValidAlarmBegin == true){
251                         return CALENDAROBJECTVALID_INVALIDFORMAT;
252                                 
253                 }
254                 
255                 // Look for any VALARM sections.
256                 
257                 if (ValidAlarmBegin == true){
258                         
259                         AlarmObjectName.push_back(ObjectName[SeekCount]);
260                         AlarmObjectData.push_back(ObjectData[SeekCount]);
261                         DeleteLines.push_back(SeekCount);
262                         
263                 }
264                 
265                 if (ObjectName[SeekCount] == "END" &&
266                         ObjectData[SeekCount] == "VALARM" && 
267                         ValidAlarmBegin == true){
268                                 
269                         EventAlarmName.push_back(AlarmObjectName);
270                         EventAlarmData.push_back(AlarmObjectData);
271                         
272                         AlarmObjectName.clear();
273                         AlarmObjectData.clear();
275                         ValidAlarmBegin = false;
276                                 
277                 }
278                 
279                 if (ObjectName[SeekCount] == "BEGIN" &&
280                         ObjectData[SeekCount] == "VALARM" && 
281                         ValidBegin == true){
282                                 
283                         if (ValidAlarmBegin == false){
284                                 ValidAlarmBegin = true;
285                         } else {
286                                 return CALENDAROBJECTVALID_INVALIDFORMAT;
287                         }
288                         
289                         AlarmObjectName.push_back(ObjectName[SeekCount]);
290                         AlarmObjectData.push_back(ObjectData[SeekCount]);
291                         DeleteLines.push_back(SeekCount);
292                         
293                 }
294                 
295                 SeekCount++;
296                         
297         }
298         
299         SeekCount = 0;
300         
301         // Check that the last line contains END:VCALENDAR
302         // and it only appears once.
303         
304         for (vector<string>::iterator iter = ObjectName.begin();
305                 iter != ObjectName.end(); iter++){
306                 
307                 if (ObjectName[SeekCount] == "END" &&
308                         ObjectData[SeekCount] == "VCALENDAR"){
309                         
310                         if (ValidEnd == false){
311                                 ValidEnd = true;
312                         } else {
313                                 return CALENDAROBJECTVALID_INVALIDFORMAT;
314                         }
315                                 
316                 }
317                         
318                 SeekCount++;
319                         
320         }
321         
322         SeekCount = 0;
323         
324         // Check that the VERSION value contains 2.0 and that
325         // it only appears once.
326         
327         for (vector<string>::iterator iter = ObjectName.begin();
328                 iter != ObjectName.end(); iter++){
329                 
330                 if (ObjectName[SeekCount] == "VERSION" &&
331                         ObjectData[SeekCount] == "2.0"){
332                         
333                         if (ValidVersion == false){
334                                 ValidVersion = true;
335                         } else {
336                                 return CALENDAROBJECTVALID_INVALIDFORMAT;
337                         }
338                                 
339                 }
340                 
341                 SeekCount++;
342                         
343         }
345         // Remove lines that aren't needed as they have
346         // been moved to the EventAlarm section.
347         
348         for (vector<int>::reverse_iterator deliter = DeleteLines.rbegin();
349                 deliter != DeleteLines.rend(); deliter++){
351                 ObjectName.erase(ObjectName.begin()+(*deliter));
352                 ObjectData.erase(ObjectData.begin()+(*deliter));
353                         
354         }
356         if (ValidBegin == true && 
357                 ValidEnd == true && 
358                 ValidVersion == true &&
359                 ValidAlarmBegin == false){
360         
361                 return CALENDAROBJECTVALID_OK;
362                         
363         } else {
364                 
365                 return CALENDAROBJECTVALID_INVALIDFORMAT;
366                 
367         }
368         
371 void CalendarObject::ProcessBaseData(){
372         
373         // Process the base object data.
374         
375         multimap<string,string> DataReceived;
376         
377         // Get the method (METHOD).
378         
379         DataReceived = ProcessTextVectors(&ObjectName, &ObjectData, false, "METHOD");
380         
381         if (DataReceived.begin() != DataReceived.end()){
382                 
383                 try {
384                         MethodTokens = DataReceived.begin()->first.substr(7);
385                 }
386                 
387                 catch(const out_of_range &oor){
388                         // Do nothing as there is no data.
389                 }               
390                 
391                 MethodData = DataReceived.begin()->second;
392                 
393         }
394         
395         // Get the calendar scale (CALSCALE).
396         
397         DataReceived = ProcessTextVectors(&ObjectName, &ObjectData, false, "CALSCALE");
398         
399         if (DataReceived.begin() != DataReceived.end()){
400                 
401                 try {
402                         CalendarScaleTokens = DataReceived.begin()->first.substr(9);
403                 }
404                 
405                 catch(const out_of_range &oor){
406                         // Do nothing as there is no data.
407                 }               
408                 
409                 CalendarScaleData = DataReceived.begin()->second;
410                 
411         }
412         
Xestia Software Development
Yn Maystri
© 2006 - 2019 Xestia Software Development
Software

Xestia Address Book
Xestia Calendar
Development

Xestia Gelforn
Everything else

About
News
Privacy Policy