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