2 * Funambol is a mobile platform developed by Funambol, Inc.
3 * Copyright (C) 2003 - 2007 Funambol, Inc.
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Affero General Public License version 3 as published by
7 * the Free Software Foundation with the addition of the following permission
8 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
9 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
10 * WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program; if not, see http://www.gnu.org/licenses or write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
23 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
25 * The interactive user interfaces in modified source and object code versions
26 * of this program must display Appropriate Legal Notices, as required under
27 * Section 5 of the GNU Affero General Public License version 3.
29 * In accordance with Section 7(b) of the GNU Affero General Public License
30 * version 3, these Appropriate Legal Notices must retain the display of the
31 * "Powered by Funambol" logo. If the display of the logo is not reasonably
32 * feasible for technical reasons, the Appropriate Legal Notices must display
33 * the words "Powered by Funambol".
37 #include "vocl/iCalendar/iCalConverter.h"
38 #include "base/util/WString.h"
39 #include "base/globalsdef.h"
44 iCalConverter::iCalConverter() {
49 iCalConverter::~iCalConverter() {
51 delete [] iCalendar; iCalendar = NULL;
54 delete calendar; calendar = NULL;
58 void iCalConverter::setSource(WCHAR* inputICalendar) {
64 iCalendar = new WCHAR[wcslen(inputICalendar) + 1];
65 wcscpy(iCalendar, inputICalendar);
68 delete calendar; calendar = NULL;
72 void iCalConverter::setSource(Calendar& inputCalendar) {
75 calendar = (Calendar *)inputCalendar.clone();
77 delete [] iCalendar; iCalendar = NULL;
81 void iCalConverter::getICalendar(WCHAR* ouputICalendar) {
85 wcscpy(ouputICalendar, iCalendar);
88 ouputICalendar = NULL;
91 void iCalConverter::getCalendar(Calendar** outputCalendar) {
93 *outputCalendar = (Calendar *)calendar->clone();
96 *outputCalendar = NULL;
99 bool iCalConverter::convert(WString& errorDescription, long* errorCode) {
100 errorDescription = TEXT("");
101 *errorCode = ERROR_SUCCESS;
103 if(!calendar && !iCalendar)
105 if(calendar && iCalendar)
109 iCalendar = calendar->toString();
111 if(!calendar->getProdID() || !calendar->getProdID()->getValue()) {
112 *errorCode = ERROR_KEY_PROPERTY_MISSING;
113 errorDescription = TEXT("'PRODID' property is missing");
114 delete [] iCalendar; iCalendar = NULL;
118 if(!calendar->getVersion() || !calendar->getVersion()->getValue()) {
119 *errorCode = ERROR_KEY_PROPERTY_MISSING;
120 errorDescription = TEXT("'VERSION' property is missing");
121 delete [] iCalendar; iCalendar = NULL;
124 if(calendar->getEvents())
125 for(int i=0; i<calendar->getEvents()->size(); i++)
126 if(!validateEvent(((Event*)calendar->getEvents()->get(i)), errorDescription, errorCode)) {
127 delete [] iCalendar; iCalendar = NULL;
130 if(calendar->getToDos())
131 for(int i=0; i<calendar->getToDos()->size(); i++)
132 if(!validateTodo(((ToDo*)calendar->getToDos()->get(i)), errorDescription, errorCode)) {
133 delete [] iCalendar; iCalendar = NULL;
141 calendar = new Calendar();
142 VObject* vo = VConverter::parse(iCalendar);
144 *errorCode = ERROR_PARSING_ERROR;
145 errorDescription = TEXT("Invalid VObject returned");
149 int n = vo->propertiesCount();
151 if(wcscmp(vo->getProperty(0)->getName(), TEXT("BEGIN")) ||
152 !vo->getProperty(0)->getValue() ||
153 wcscmp(vo->getProperty(0)->getValue(), TEXT("VCALENDAR"))) {
154 *errorCode = ERROR_KEY_PROPERTY_MISSING;
155 errorDescription = TEXT("'BEGIN:VCALENDAR' property is missing");
159 if(wcscmp(vo->getProperty(n-1)->getName(), TEXT("END")) ||
160 !vo->getProperty(n-1)->getValue() ||
161 wcscmp(vo->getProperty(n-1)->getValue(), TEXT("VCALENDAR"))) {
162 *errorCode = ERROR_KEY_PROPERTY_MISSING;
163 errorDescription = TEXT("'END:VCALENDAR' property is missing");
167 if(!vo->containsProperty(TEXT("VERSION"))) {
168 *errorCode = ERROR_KEY_PROPERTY_MISSING;
169 errorDescription = TEXT("'VERSION' property is missing");
173 if(vo->containsProperty(TEXT("VERSION")) &&
174 (!vo->getProperty(TEXT("VERSION")) || wcscmp(vo->getProperty(TEXT("VERSION"))->getValue(), TEXT("2.0")))) {
175 *errorCode = ERROR_ILLEGAL_VERSION_NUMBER;
176 if(vo->getProperty(TEXT("VERSION"))) {
177 errorDescription = TEXT("Illegal version number : ");
178 errorDescription += vo->getProperty(TEXT("VERSION"))->getValue();
181 errorDescription = TEXT("Illegal version number");
186 iCalProperty* prop = new iCalProperty(vo->getProperty(TEXT("VERSION"))->getValue());
187 calendar->setVersion(*prop);
188 vo->removeProperty(TEXT("VERSION"));
192 if(!vo->containsProperty(TEXT("PRODID")) || !vo->getProperty(TEXT("PRODID"))) {
193 *errorCode = ERROR_KEY_PROPERTY_MISSING;
194 errorDescription = TEXT("'PRODID' property is missing");
198 iCalProperty* prop = new iCalProperty(vo->getProperty(TEXT("PRODID"))->getValue());
199 calendar->setProdID(*prop);
200 vo->removeProperty(TEXT("PRODID"));
204 if(vo->containsProperty(TEXT("CALSCALE")) ||
205 vo->getProperty(TEXT("CALSCALE"))) {
206 iCalProperty* prop = new iCalProperty(vo->getProperty(TEXT("CALSCALE"))->getValue());
207 calendar->setCalScale(*prop);
208 vo->removeProperty(TEXT("CALSCALE"));
212 if(vo->containsProperty(TEXT("METHOD")) ||
213 vo->getProperty(TEXT("METHOD"))) {
214 iCalProperty* prop = new iCalProperty(vo->getProperty(TEXT("METHOD"))->getValue());
215 calendar->setMethod(*prop);
216 vo->removeProperty(TEXT("METHOD"));
220 //extract VEVENTs from vo
222 while(ev = extractEvent(vo, errorDescription, errorCode)) {
223 if (!validateEvent(ev, errorDescription, errorCode)) {
224 delete ev; ev = NULL;
227 calendar->addEvent(ev);
228 delete ev; ev = NULL;
231 //extract VTODOs from vo
233 while(task = extractTask(vo, errorDescription, errorCode)) {
234 if (!validateTodo(task, errorDescription, errorCode)) {
235 delete task; task = NULL;
238 calendar->addToDo(task);
239 delete task; task = NULL;
246 Event* iCalConverter::extractEvent(VObject* vo, WString& errorDescription, long* errorCode) {
250 for(i = 0, m = vo->propertiesCount(); i < m ; i++) {
251 if(beginEvent == -1 && !wcscmp(vo->getProperty(i)->getName(), TEXT("BEGIN")) &&
252 vo->getProperty(i)->getValue() &&
253 !wcscmp(vo->getProperty(i)->getValue(), TEXT("VEVENT")))
255 if(endEvent == -1 && !wcscmp(vo->getProperty(i)->getName(),TEXT("END")) &&
256 vo->getProperty(i)->getValue() &&
257 !wcscmp(vo->getProperty(i)->getValue(),TEXT("VEVENT"))) {
266 if(beginEvent > endEvent) {
267 *errorCode = ERROR_INVALID_EVENT_BLOCK;
268 errorDescription = TEXT("BEGIN:VEVENT property found, but END:VEVENT is missing");
272 Event* ret = new Event();
273 for(i = beginEvent; i <= endEvent; i++) {
274 ret->addProperty(vo->getProperty(i));
275 vo->removeProperty(i);
280 extractAlarm((VObject*) ret);
285 ToDo* iCalConverter::extractTask(VObject* vo, WString& errorDescription, long* errorCode) {
289 for(i = 0, m = vo->propertiesCount(); i < m ; i++) {
290 if(beginTask == -1 && !wcscmp(vo->getProperty(i)->getName(), TEXT("BEGIN")) &&
291 vo->getProperty(i)->getValue() &&
292 !wcscmp(vo->getProperty(i)->getValue(), TEXT("VTODO")))
294 if(endTask == -1 && !wcscmp(vo->getProperty(i)->getName(),TEXT("END")) &&
295 vo->getProperty(i)->getValue() &&
296 !wcscmp(vo->getProperty(i)->getValue(),TEXT("VTODO"))) {
305 if(beginTask > endTask) {
306 *errorCode = ERROR_INVALID_TODO_BLOCK;
307 errorDescription = TEXT("BEGIN:VTODO property found, but END:VTODO is missing");
311 ToDo* ret = new ToDo();
312 for(i = beginTask; i <= endTask; i++) {
313 ret->addProperty(vo->getProperty(i));
314 vo->removeProperty(i);
319 extractAlarm((VObject*) ret);
324 void iCalConverter::extractAlarm(VObject* vo){
327 for(int i = 0, m = vo->propertiesCount(); i < m ; i++) {
328 if(beginAlarm== -1 && !wcscmp(vo->getProperty(i)->getName(), TEXT("BEGIN")) &&
329 vo->getProperty(i)->getValue() &&
330 !wcscmp(vo->getProperty(i)->getValue(), TEXT("VALARM")))
332 if(endAlarm == -1 && !wcscmp(vo->getProperty(i)->getName(),TEXT("END")) &&
333 vo->getProperty(i)->getValue() &&
334 !wcscmp(vo->getProperty(i)->getValue(),TEXT("VALARM"))) {
340 if(beginAlarm != -1 && endAlarm > beginAlarm)
341 for(int i = beginAlarm; i <= endAlarm; i++) {
342 vo->removeProperty(i);
348 bool iCalConverter::validateEvent(Event* ev, WString& errorDescription, long* errorCode) {
349 //validate BEGIN, END, UID
350 if(wcscmp(ev->getProperty(0)->getName(), TEXT("BEGIN")) ||
351 wcscmp(ev->getProperty(0)->getValue(), TEXT("VEVENT"))) {
352 *errorCode = ERROR_KEY_PROPERTY_MISSING;
353 errorDescription = TEXT("Invalid EVENT: 'BEGIN' property is missing");
356 if(wcscmp(ev->getProperty(ev->propertiesCount()-1)->getName(), TEXT("END")) ||
357 wcscmp(ev->getProperty(ev->propertiesCount()-1)->getValue(), TEXT("VEVENT"))) {
358 *errorCode = ERROR_KEY_PROPERTY_MISSING;
359 errorDescription = TEXT("Invalid EVENT: 'END' property is missing");
362 if(!ev->containsProperty(TEXT("UID"))) {
363 *errorCode = ERROR_KEY_PROPERTY_MISSING;
364 errorDescription = TEXT("Invalid EVENT: 'UID' property is missing");
367 for(int i = 0; i < ev->propertiesCount(); i++) {
368 if(!wcsstr(EVENT_PROPERTIES_LIST, ev->getProperty(i)->getName()) &&
369 wcsstr(ev->getProperty(i)->getName(),TEXT("X-")) != ev->getProperty(i)->getName()) {
370 *errorCode = ERROR_ILLEGAL_PROPERTY_NAME;
371 errorDescription = TEXT("EVENT - Illegal property name : %s");
372 errorDescription += ev->getProperty(i)->getName();
375 if(ev->getProperty(i)->getValue() && !validatePropery(ev->getProperty(i), errorDescription, errorCode))
380 bool iCalConverter::validateTodo(ToDo* task, WString& errorDescription, long* errorCode) {
381 //validate BEGIN, END, UID
382 if(wcscmp(task->getProperty(0)->getName(), TEXT("BEGIN")) ||
383 wcscmp(task->getProperty(0)->getValue(), TEXT("VTODO"))) {
384 *errorCode = ERROR_KEY_PROPERTY_MISSING;
385 errorDescription = TEXT("Invalid TODO: 'BEGIN' property is missing");
388 if(wcscmp(task->getProperty(task->propertiesCount()-1)->getName(), TEXT("END")) ||
389 wcscmp(task->getProperty(task->propertiesCount()-1)->getValue(), TEXT("VTODO"))) {
390 *errorCode = ERROR_KEY_PROPERTY_MISSING;
391 errorDescription = TEXT("Invalid TODO: 'END' property is missing");
394 if(!task->containsProperty(TEXT("UID"))) {
395 *errorCode = ERROR_KEY_PROPERTY_MISSING;
396 errorDescription = TEXT("Invalid TODO: 'UID' property is missing");
399 for(int i = 0; i < task->propertiesCount(); i++) {
400 if(!wcsstr(TODO_PROPERTIES_LIST, task->getProperty(i)->getName()) &&
401 wcsstr(task->getProperty(i)->getName(),TEXT("X-")) != task->getProperty(i)->getName()) {
402 *errorCode = ERROR_ILLEGAL_PROPERTY_NAME;
403 errorDescription = TEXT("TODO - Illegal property name : ");
404 errorDescription += task->getProperty(i)->getName();
407 if(task->getProperty(i)->getValue() && !validatePropery(task->getProperty(i), errorDescription, errorCode))
412 bool iCalConverter::validatePropery(VProperty* vp, WString& errorDescription, long* errorCode) {
414 if(!wcscmp(vp->getName(), TEXT("CLASS"))) {
415 if(!wcsstr(CLASS_PROPERTY_VALUE, vp->getValue()) &&
416 wcsstr(vp->getValue(),TEXT("X-")) != vp->getValue()) {
417 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
418 errorDescription = TEXT("Property CLASS, Invalid value : ");
419 errorDescription += vp->getValue();
423 else if(!wcscmp(vp->getName(), TEXT("CREATED"))) {
424 if(!validateDT(vp->getValue())) {
425 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
426 errorDescription = TEXT("Property CREATED, Invalid value : ");
427 errorDescription += vp->getValue();
431 else if(!wcscmp(vp->getName(), TEXT("DESCRIPTION"))) {
432 for(int i = 0; i < vp->parameterCount(); i++)
433 if(!wcsstr(COMMENT_PARAM_LIST, vp->getParameter(i)) &&
434 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
435 *errorCode = ERROR_ILLEGAL_PARAMETER;
436 errorDescription = TEXT("Property DESCRIPTION, Invalid parameter : ");
437 errorDescription += vp->getParameter(i);
441 else if(!wcscmp(vp->getName(), TEXT("DTSTART"))) {
442 for(int i = 0; i < vp->parameterCount(); i++) {
443 if(!wcsstr(DT_PARAM_LIST, vp->getParameter(i)) &&
444 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
445 *errorCode = ERROR_ILLEGAL_PARAMETER;
446 errorDescription = TEXT("Property DTSTART, Invalid parameter : ");
447 errorDescription += vp->getParameter(i);
451 if(vp->containsParameter(TEXT("VALUE")) && !wcscmp(vp->getParameterValue(TEXT("VALUE")), TEXT("DATE"))) {
452 if(!validateDate(vp->getValue())) {
453 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
454 errorDescription = TEXT("Property DTSTART, Invalid value : ");
455 errorDescription += vp->getValue();
459 else if(!validateDT(vp->getValue()) && !validateDate(vp->getValue())) {
460 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
461 errorDescription = TEXT("Property DTSTART, Invalid value : ");
462 errorDescription += vp->getValue();
466 else if(!wcscmp(vp->getName(), TEXT("GEO"))) {
467 if(!validateGeo(vp->getValue())) {
468 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
469 errorDescription = TEXT("Property GEO, Invalid value format : ");
470 errorDescription += vp->getValue();
474 else if(!wcscmp(vp->getName(), TEXT("LAST-MODIFIED"))) {
475 if(!validateDT(vp->getValue())) {
476 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
477 errorDescription = TEXT("Property LAST-MODIFIED, Invalid value : ");
478 errorDescription += vp->getValue();
482 else if(!wcscmp(vp->getName(), TEXT("LOCATION"))) {
483 for(int i = 0; i < vp->parameterCount(); i++)
484 if(!wcsstr(COMMENT_PARAM_LIST, vp->getParameter(i)) &&
485 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
486 *errorCode = ERROR_ILLEGAL_PARAMETER;
487 errorDescription = TEXT("Property LOCATION, Invalid parameter : ");
488 errorDescription += vp->getParameter(i);
492 else if(!wcscmp(vp->getName(), TEXT("ORGANIZER"))) {
493 for(int i = 0; i < vp->parameterCount(); i++)
494 if(!wcsstr(ORGANIZER_PARAM_LIST, vp->getParameter(i)) &&
495 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
496 *errorCode = ERROR_ILLEGAL_PARAMETER;
497 errorDescription = TEXT("Property ORGANIZER, Invalid parameter : ");
498 errorDescription += vp->getParameter(i);
502 else if(!wcscmp(vp->getName(), TEXT("PRIORITY"))) {
504 if(wcslen(vp->getValue()) > 1 || !isdigit(vp->getValue()[0])) {
505 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
506 errorDescription = TEXT("Property PRIORITY, Invalid value : ");
507 errorDescription += vp->getValue();
512 else if(!wcscmp(vp->getName(), TEXT("DTSTAMP"))) {
513 if(!validateDT(vp->getValue())) {
514 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
515 errorDescription = TEXT("Property DTSTAMP, Invalid value : ");
516 errorDescription += vp->getValue();
520 else if(!wcscmp(vp->getName(), TEXT("SUMMARY"))) {
521 for(int i = 0; i < vp->parameterCount(); i++)
522 if(!wcsstr(COMMENT_PARAM_LIST, vp->getParameter(i)) &&
523 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
524 *errorCode = ERROR_ILLEGAL_PARAMETER;
525 errorDescription = TEXT("Property SUMMARY, Invalid parameter : ");
526 errorDescription += vp->getParameter(i);
530 else if(!wcscmp(vp->getName(), TEXT("TRANSP"))) {
531 if(wcscmp(vp->getName(), TEXT("OPAQUE")) && wcscmp(vp->getName(), TEXT("TRANSPARENT"))) {
532 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
533 errorDescription = TEXT("Property TRANSP, Invalid value : ");
534 errorDescription += vp->getValue();
539 else if(!wcscmp(vp->getName(), TEXT("RECURRENCE-ID"))) {
540 for(int i = 0; i < vp->parameterCount(); i++) {
541 if(!wcsstr(DT_PARAM_LIST, vp->getParameter(i)) &&
542 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i) &&
543 wcscmp(vp->getParameter(i), TEXT("RANGE"))) {
544 *errorCode = ERROR_ILLEGAL_PARAMETER;
545 errorDescription = TEXT("Property RECURRENCE-ID, Invalid parameter : ");
546 errorDescription += vp->getParameter(i);
550 if(vp->containsParameter(TEXT("VALUE")) && !wcscmp(vp->getParameterValue(TEXT("VALUE")), TEXT("DATE"))) {
551 if(!validateDate(vp->getValue())) {
552 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
553 errorDescription = TEXT("Property RECURRENCE-ID, Invalid value : ");
554 errorDescription += vp->getValue();
558 else if(!validateDT(vp->getValue())) {
559 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
560 errorDescription = TEXT("Property RECURRENCE-ID, Invalid value : ");
561 errorDescription += vp->getValue();
565 else if(!wcscmp(vp->getName(), TEXT("DTEND"))) {
566 for(int i = 0; i < vp->parameterCount(); i++) {
567 if(!wcsstr(DT_PARAM_LIST, vp->getParameter(i)) &&
568 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
569 *errorCode = ERROR_ILLEGAL_PARAMETER;
570 errorDescription = TEXT("Property DTEND, Invalid parameter: ");
571 errorDescription += vp->getParameter(i);
575 if(vp->containsParameter(TEXT("VALUE")) && !wcscmp(vp->getParameterValue(TEXT("VALUE")), TEXT("DATE"))) {
576 if(!validateDate(vp->getValue())) {
577 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
578 errorDescription = TEXT("Property DTEND, Invalid value : ");
579 errorDescription += vp->getValue();
583 else if(!validateDT(vp->getValue()) && !validateDate(vp->getValue())) {
584 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
585 errorDescription = TEXT("Property DTEND, Invalid value : ");
586 errorDescription += vp->getValue();
590 else if(!wcscmp(vp->getName(), TEXT("DUE"))) {
591 for(int i = 0; i < vp->parameterCount(); i++) {
592 if(!wcsstr(DT_PARAM_LIST, vp->getParameter(i)) &&
593 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
594 *errorCode = ERROR_ILLEGAL_PARAMETER;
595 errorDescription = TEXT("Property DUE, Invalid parameter : ");
596 errorDescription += vp->getParameter(i);
600 if(vp->containsParameter(TEXT("VALUE")) && !wcscmp(vp->getParameterValue(TEXT("VALUE")), TEXT("DATE"))) {
601 if(!validateDate(vp->getValue())) {
602 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
603 errorDescription = TEXT("Property DUE, Invalid value : ");
604 errorDescription += vp->getValue();
608 else if(!validateDT(vp->getValue())) {
609 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
610 errorDescription = TEXT("Property DUE, Invalid value : ");
611 errorDescription += vp->getValue();
615 else if(!wcscmp(vp->getName(), TEXT("COMPLETED"))) {
616 if(!validateDT(vp->getValue())) {
617 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
618 errorDescription = TEXT("Property COMPLETED, Invalid value : ");
619 errorDescription += vp->getValue();
623 else if(!wcscmp(vp->getName(), TEXT("PERCENT-COMPLETE"))) {
624 if(wcslen(vp->getValue()) > 2 ||
625 (wcslen(vp->getValue()) == 1 && !isdigit(vp->getValue()[0])) ||
626 (wcslen(vp->getValue()) == 2 && (!isdigit(vp->getValue()[0]) || !isdigit(vp->getValue()[1])))) {
627 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
628 errorDescription = TEXT("Property PERCENT, Invalid value : ");
629 errorDescription += vp->getValue();
633 else if(!wcscmp(vp->getName(), TEXT("ATTACH"))) {
634 for(int i = 0; i < vp->parameterCount(); i++) {
635 if(!wcsstr(ATTACH_PARAM_LIST, vp->getParameter(i)) &&
636 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
637 *errorCode = ERROR_ILLEGAL_PARAMETER;
638 errorDescription = TEXT("Property ATTACH, Invalid parameter : ");
639 errorDescription += vp->getParameter(i);
642 if(!wcscmp(vp->getParameter(i), TEXT("ENCODING"))
643 && wcscmp(vp->getParameterValue(TEXT("ENCODING")), TEXT("BASE64"))) {
644 *errorCode = ERROR_UNSUPPORTED_ENCODING;
645 errorDescription = TEXT("Property ATTACH, unsupported encoding : ");
646 errorDescription += vp->getParameterValue(TEXT("ENCODING"));
651 else if(!wcscmp(vp->getName(), TEXT("ATTENDEE"))) {
652 for(int i = 0; i < vp->parameterCount(); i++) {
653 if(!wcsstr(ATTENDEE_PARAM_LIST, vp->getParameter(i)) &&
654 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
655 *errorCode = ERROR_ILLEGAL_PARAMETER;
656 errorDescription = TEXT("Property ATTENDEE, Invalid parameter : ");
657 errorDescription += vp->getParameter(i);
662 else if(!wcscmp(vp->getName(), TEXT("COMMENT"))) {
663 for(int i = 0; i < vp->parameterCount(); i++)
664 if(!wcsstr(COMMENT_PARAM_LIST, vp->getParameter(i)) &&
665 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
666 *errorCode = ERROR_ILLEGAL_PARAMETER;
667 errorDescription = TEXT("Property COMMENT, Invalid parameter : ");
668 errorDescription += vp->getParameter(i);
672 else if(!wcscmp(vp->getName(), TEXT("CONTACT"))) {
673 for(int i = 0; i < vp->parameterCount(); i++)
674 if(!wcsstr(COMMENT_PARAM_LIST, vp->getParameter(i)) &&
675 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
676 *errorCode = ERROR_ILLEGAL_PARAMETER;
677 errorDescription = TEXT("Property CONTACT, Invalid parameter : ");
678 errorDescription += vp->getParameter(i);
682 else if(!wcscmp(vp->getName(), TEXT("EXDATE"))) {
683 for(int i = 0; i < vp->parameterCount(); i++) {
684 if(!wcsstr(DT_PARAM_LIST, vp->getParameter(i)) &&
685 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
686 *errorCode = ERROR_ILLEGAL_PARAMETER;
687 errorDescription = TEXT("Property EXDATE, Invalid parameter : ");
688 errorDescription += vp->getParameter(i);
692 if(vp->containsParameter(TEXT("VALUE")) && !wcscmp(vp->getParameterValue(TEXT("VALUE")), TEXT("DATE"))) {
693 WCHAR seps[] = TEXT(",");
695 token = wcstok( vp->getValue(), seps );
696 while( token != NULL ) {
697 if(!validateDate(token)) {
698 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
699 errorDescription = TEXT("Property EXDATE, Invalid value : ");
700 errorDescription += vp->getValue();
703 token = wcstok( NULL, seps );
706 else if(!validateDT(vp->getValue())) {
707 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
708 errorDescription = TEXT("Property EXDATE, Invalid value : ");
709 errorDescription += vp->getValue();
713 else if(!wcscmp(vp->getName(), TEXT("EXRULE"))) {
714 if(!validateRecur(vp->getValue())) {
715 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
716 errorDescription = TEXT("Property EXRULE, Invalid value : ");
717 errorDescription += vp->getValue();
721 else if(!wcscmp(vp->getName(), TEXT("REQUEST-STATUS"))) {
722 //statcode ";" statdesc [";" extdata]
723 WCHAR* value = new WCHAR[wcslen(vp->getName())+1];
724 wcscpy(value, vp->getName());
725 if(!isdigit(value[0]) || value[1] != '.' || !wcschr(value, ';')) {
726 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
727 errorDescription = TEXT("Property REQUEST-STATUS, Invalid value : ");
728 errorDescription += vp->getValue();
734 else if(!wcscmp(vp->getName(), TEXT("RELATED-TO"))) {
735 for(int i = 0; i < vp->parameterCount(); i++)
736 if(wcscmp(TEXT("RELTYPE"), vp->getParameter(i)) &&
737 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
738 *errorCode = ERROR_ILLEGAL_PARAMETER;
739 errorDescription = TEXT("Property RELATED-TO, Invalid parameter : ");
740 errorDescription += vp->getParameter(i);
744 else if(!wcscmp(vp->getName(), TEXT("RESOURCES"))) {
745 for(int i = 0; i < vp->parameterCount(); i++)
746 if(!wcsstr(COMMENT_PARAM_LIST, vp->getParameter(i)) &&
747 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
748 *errorCode = ERROR_ILLEGAL_PARAMETER;
749 errorDescription = TEXT("Property RESOURCES, Invalid parameter : ");
750 errorDescription += vp->getParameter(i);
754 else if(!wcscmp(vp->getName(), TEXT("RDATE"))) {
755 for(int i = 0; i < vp->parameterCount(); i++) {
756 if(!wcsstr(RDATE_PARAM_LIST, vp->getParameter(i)) &&
757 wcsstr(vp->getValue(),TEXT("X-")) != vp->getParameter(i)) {
758 *errorCode = ERROR_ILLEGAL_PARAMETER;
759 errorDescription = TEXT("Property RDATE, Invalid parameter : ");
760 errorDescription += vp->getParameter(i);
764 if(vp->containsParameter(TEXT("VALUE")) && !wcscmp(vp->getParameterValue(TEXT("VALUE")), TEXT("DATE"))) {
765 if(!validateDate(vp->getValue())) {
766 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
767 errorDescription = TEXT("Property RDATE, Invalid value : ");
768 errorDescription += vp->getValue();
772 else if(vp->containsParameter(TEXT("VALUE")) && !wcscmp(vp->getParameterValue(TEXT("VALUE")), TEXT("PERIOD"))) {
774 delimiter = wcschr(vp->getValue(), '/');
776 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
777 errorDescription = TEXT("Property RDATE, Invalid value : ");
778 errorDescription += vp->getValue();
782 else if(!validateDT(vp->getValue())) {
783 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
784 errorDescription = TEXT("Property RDATE, Invalid value : ");
785 errorDescription += vp->getValue();
789 else if(!wcscmp(vp->getName(), TEXT("RRULE"))) {
790 if(!validateRecur(vp->getValue())) {
791 *errorCode = ERROR_INVALID_PROPERTY_VALUE;
792 errorDescription = TEXT("Property RRULE, Invalid value : ");
793 errorDescription += vp->getValue();
800 bool iCalConverter::validateGeo(WCHAR* geo) {
804 //expected format: longitude;latitude
806 pDest = wcschr(geo, ';');
811 WCHAR* longitude = new WCHAR[wcslen(geo)+1];
812 wcsncpy(longitude, geo, pDest-geo);
814 WCHAR* latitude = new WCHAR[wcslen(geo)+1];
816 wcscpy(latitude, pDest);
821 // double lon = _wtof(longitude);
822 // double lat = _wtof(latitude);
824 double lon = wcstod(longitude, &stopstring);
825 double lat = wcstod(latitude, &stopstring);
827 if(lon == 0.0 || lat == 0.0)
833 bool iCalConverter::validateDT(WCHAR* dt) {
834 //1997 06 30 T 23 59 60 Z
835 int len = int(wcslen(dt));
836 if(len != 15 && len != 16)
849 wcsncpy(date, dt, 8);
851 if(!validateDate(date)) {
882 bool iCalConverter::validateDate(WCHAR* date) {
883 if(wcslen(date) != 8)
889 int mo = _wtoi(month);
891 if(mo > 12 || mo < 1)
905 bool iCalConverter::validateRecur(WCHAR* recur) {
907 if(wcsstr(recur, TEXT("FREQ")) != recur)
910 WCHAR seps[] = TEXT(";");
914 token = wcstok( recur, seps );
915 while( token != NULL ) {
916 delimiter = wcschr(token, '=');
919 int len = int(wcslen(token));
920 WCHAR* item = new WCHAR[len + 1];
921 wcsncpy(item, token, delimiter - token);
922 item[delimiter - token] = 0;
924 if(!wcsstr(RECRUL_ITEMS_LIST, item) && wcsstr(item,TEXT("X-")) != item) {
925 delete [] item; item = NULL;
929 if(!wcscmp(item, TEXT("FREQ"))) {
930 WCHAR* value = new WCHAR[len + 1];
931 wcscpy(value, ++delimiter);
932 if(!wcsstr(FREQUENCY_VALUES_LIST, value)) {
933 delete [] value; value = NULL;
936 delete [] value; value = NULL;
939 delete [] item; item = NULL;
941 token = wcstok( NULL, seps );