1 /**
2  * @file    vcomponent_cxx.cpp
3  * @author  fnguyen (12/10/01)
4  * @brief   Implementation of C++ Wrapper for icalcomponent.c
5  *
6  * (C) COPYRIGHT 2001, Critical Path
7 
8  This library is free software; you can redistribute it and/or modify
9  it under the terms of either:
10 
11     The LGPL as published by the Free Software Foundation, version
12     2.1, available at: https://www.gnu.org/licenses/lgpl-2.1.html
13 
14  Or:
15 
16     The Mozilla Public License Version 2.0. You may obtain a copy of
17     the License at https://www.mozilla.org/MPL/
18 */
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 #include "vcomponent_cxx.h"
25 #include "icalparameter_cxx.h"
26 #include "icalproperty_cxx.h"
27 #include "icalvalue_cxx.h"
28 using namespace LibICal;
29 
30 extern "C" {
31 #include "icalmemory.h"
32 }
33 
34 #include <cstdlib>
35 
VComponent()36 VComponent::VComponent() : imp(icalcomponent_new(ICAL_ANY_COMPONENT))
37 {
38 }
39 
VComponent(const VComponent & v)40 VComponent::VComponent(const VComponent &v) : imp(icalcomponent_new_clone(v.imp))
41 {
42     if (imp == NULL) {
43         throw icalerrno;
44     }
45 }
46 
operator =(const VComponent & v)47 VComponent &VComponent::operator=(const VComponent &v)
48 {
49     if (this == &v) {
50         return *this;
51     }
52 
53     if (imp != NULL) {
54         icalcomponent_free(imp);
55         imp = icalcomponent_new_clone(v.imp);
56         if (imp == NULL) {
57             throw icalerrno;
58         }
59     }
60 
61     return *this;
62 }
63 
detach()64 void VComponent::detach()
65 {
66     imp = NULL;
67 }
68 
~VComponent()69 VComponent::~VComponent()
70 {
71     if (imp != NULL) {
72         icalcomponent_free(imp);
73     }
74 }
75 
VComponent(icalcomponent * v)76 VComponent::VComponent(icalcomponent *v) : imp(v)
77 {
78 }
79 
80 /* char* returned is in the ring buffer. caller doesn't have to free it */
quote_ical_string(char * str)81 char *VComponent::quote_ical_string(char *str)
82 {
83     const char *p;
84     size_t  buf_sz;
85     buf_sz = strlen(str) * 2; // assume worse case scenarios.
86     // otherwise, we have to parse the string and count \ */
87     char *out = static_cast<char *>(icalmemory_new_buffer(buf_sz)); /* memory from the ring buf */
88     char *pout;
89 
90     if (out == 0) {
91         return 0;
92     }
93 
94     pout = out;
95 
96     for (p = str; *p != 0; p++) {
97 
98         if (*p == '\\') {
99             *pout++ = '\\';
100         }
101         *pout++ = *p;
102     }
103     *pout++ = '\0';
104 
105     return out;
106 }
107 
108 /**
109  * @brief Constructor
110  *
111  * Create a new VComponent from a string.
112  *
113  * @exception ICAL_MALFORMEDDATA_ERROR
114  *            Catch this error if you
115  *
116  */
VComponent(const std::string & str)117 VComponent::VComponent(const std::string &str)
118     : imp(icalcomponent_new_from_string(str.c_str()))
119 {
120     if (imp == NULL) {
121         if (! icalerrno) {
122             icalerrno = ICAL_BADARG_ERROR;
123         }
124         throw icalerrno;
125     }
126 }
127 
VComponent(const icalcomponent_kind & kind)128 VComponent::VComponent(const icalcomponent_kind &kind) : imp(icalcomponent_new(kind))
129 {
130     if (imp == NULL) {
131         throw icalerrno;
132     }
133 }
134 
as_ical_string()135 std::string VComponent::as_ical_string()
136 {
137     char *str = icalcomponent_as_ical_string(imp);
138 
139     if (str == NULL) {
140         throw icalerrno;
141     }
142 
143     return (str);
144 }
145 
is_valid()146 bool VComponent::is_valid()
147 {
148     if (imp == NULL) {
149         return false;
150     }
151     return (icalcomponent_is_valid(imp) != 0);
152 }
153 
isa()154 icalcomponent_kind VComponent::isa()
155 {
156     return icalcomponent_isa(imp);
157 }
158 
isa_component(void * component)159 int VComponent::isa_component(void *component)
160 {
161     return icalcomponent_isa_component(component);
162 }
163 
new_from_string(const std::string & str)164 void VComponent::new_from_string(const std::string &str)
165 {
166     if (imp != NULL) {
167         icalcomponent_free(imp);
168     }
169     imp = icalcomponent_new_from_string(str.c_str());
170 }
171 
172 /* Working with properties */
add_property(ICalProperty * property)173 void VComponent::add_property(ICalProperty *property)
174 {
175     icalcomponent_add_property(imp, *property);
176 }
177 
remove_property(ICalProperty * property)178 void VComponent::remove_property(ICalProperty *property)
179 {
180     icalcomponent_remove_property(imp, *property);
181     icalproperty_free(*property);
182     property->detach();     // set imp to null, it's free already.
183 }
184 
count_properties(const icalproperty_kind & kind)185 int VComponent::count_properties(const icalproperty_kind &kind)
186 {
187     return icalcomponent_count_properties(imp, kind);
188 }
189 
190 /* Iterate through the properties */
get_current_property()191 ICalProperty *VComponent::get_current_property()
192 {
193     icalproperty *t = icalcomponent_get_current_property(imp);
194     return ((t != NULL) ? new ICalProperty(t) : NULL);
195 }
196 
get_first_property(const icalproperty_kind & kind)197 ICalProperty *VComponent::get_first_property(const icalproperty_kind &kind)
198 {
199     icalproperty *t = icalcomponent_get_first_property(imp, kind);
200     return ((t != NULL) ? new ICalProperty(t) : NULL);
201 }
202 
get_next_property(const icalproperty_kind & kind)203 ICalProperty *VComponent::get_next_property(const icalproperty_kind &kind)
204 {
205     icalproperty *t = icalcomponent_get_next_property(imp, kind);
206     return ((t != NULL) ? new ICalProperty(t) : NULL);
207 }
208 
209 /* Working with components */
210 /* Return the first VEVENT, VTODO or VJOURNAL sub-component if it is one of those types */
get_inner()211 VComponent *VComponent::get_inner()
212 {
213     return new VComponent(icalcomponent_get_inner(imp));
214 }
215 
add_component(VComponent * child)216 void VComponent::add_component(VComponent *child)
217 {
218     icalcomponent_add_component(imp, *child);
219 }
220 
remove_component(VComponent * child)221 void VComponent::remove_component(VComponent *child)
222 {
223     icalcomponent_remove_component(imp, *child);
224 }
225 
count_components(const icalcomponent_kind & kind)226 int VComponent::count_components(const icalcomponent_kind &kind)
227 {
228     return  icalcomponent_count_components(imp, kind);
229 }
230 
231 /* Iteration Routines. There are two forms of iterators, internal and
232    external. The internal ones came first, and are almost completely
233    sufficient, but they fail badly when you want to construct a loop that
234    removes components from the container.
235 */
236 
237 /* Iterate through components */
get_current_component()238 VComponent *VComponent::get_current_component()
239 {
240     icalcomponent *t = icalcomponent_get_current_component(imp);
241     return ((t != NULL) ? new VComponent(t) : NULL);
242 }
243 
get_first_component(const icalcomponent_kind & kind)244 VComponent *VComponent::get_first_component(const icalcomponent_kind &kind)
245 {
246     VComponent *result = NULL;
247     icalcomponent *t = icalcomponent_get_first_component(imp, kind);
248     if (t != NULL) {
249         switch (kind) {
250         case ICAL_VALARM_COMPONENT:
251             result = new VAlarm(t);
252             break;
253         case ICAL_VCALENDAR_COMPONENT:
254             result = new VCalendar(t);
255             break;
256         case ICAL_VEVENT_COMPONENT:
257             result = new VEvent(t);
258             break;
259         case ICAL_VQUERY_COMPONENT:
260             result = new VQuery(t);
261             break;
262         case ICAL_VTODO_COMPONENT:
263             result = new VToDo(t);
264             break;
265         case ICAL_VAGENDA_COMPONENT:
266             result = new VAgenda(t);
267             break;
268         default:
269             result = new VComponent(t);
270         }
271     }
272 
273     return (result);
274 }
275 
get_next_component(const icalcomponent_kind & kind)276 VComponent *VComponent::get_next_component(const icalcomponent_kind &kind)
277 {
278     VComponent *result = NULL;
279     icalcomponent *t = icalcomponent_get_next_component(imp, kind);
280     if (t != NULL) {
281         switch (kind) {
282         case ICAL_VALARM_COMPONENT:
283             result = new VAlarm(t);
284             break;
285         case ICAL_VCALENDAR_COMPONENT:
286             result = new VCalendar(t);
287             break;
288         case ICAL_VEVENT_COMPONENT:
289             result = new VEvent(t);
290             break;
291         case ICAL_VQUERY_COMPONENT:
292             result = new VQuery(t);
293             break;
294         case ICAL_VTODO_COMPONENT:
295             result = new VToDo(t);
296             break;
297         case ICAL_VAGENDA_COMPONENT:
298             result = new VAgenda(t);
299             break;
300         default:
301             result = new VComponent(t);
302         }
303     }
304 
305     return (result);
306 }
307 
308 /* Using external iterators */
begin_component(const icalcomponent_kind & kind)309 icalcompiter VComponent::begin_component(const icalcomponent_kind &kind)
310 {
311     return icalcomponent_begin_component(imp, kind);
312 }
313 
end_component(const icalcomponent_kind & kind)314 icalcompiter VComponent::end_component(const icalcomponent_kind &kind)
315 {
316     return icalcomponent_end_component(imp, kind);
317 }
318 
next(icalcompiter * i)319 VComponent *VComponent::next(icalcompiter *i)
320 {
321     return reinterpret_cast<VComponent *>(icalcompiter_next(i));
322 }
323 
prev(icalcompiter * i)324 VComponent *VComponent::prev(icalcompiter *i)
325 {
326     return reinterpret_cast<VComponent *>(icalcompiter_prior(i));
327 }
328 
current(icalcompiter * i)329 VComponent *VComponent::current(icalcompiter *i)
330 {
331     return reinterpret_cast<VComponent *>(icalcompiter_deref(i));
332 }
333 
334 /* Working with embedded error properties */
count_errors()335 int VComponent::count_errors()
336 {
337     return icalcomponent_count_errors(imp);
338 }
339 
340 /* Remove all X-LIC-ERROR properties*/
strip_errors()341 void VComponent::strip_errors()
342 {
343     icalcomponent_strip_errors(imp);
344 }
345 
346 /* Convert some X-LIC-ERROR properties into RETURN-STATUS properties*/
convert_errors()347 void VComponent::convert_errors()
348 {
349     icalcomponent_convert_errors(imp);
350 }
351 
352 /* Kind conversion routines */
string_to_kind(const std::string & str)353 icalcomponent_kind VComponent::string_to_kind(const std::string &str)
354 {
355     return icalcomponent_string_to_kind(str.c_str());
356 }
357 
kind_to_string(const icalcomponent_kind & kind)358 std::string VComponent::kind_to_string(const icalcomponent_kind &kind)
359 {
360     return static_cast<std::string>(icalcomponent_kind_to_string(kind));
361 }
362 
get_dtstart() const363 struct icaltimetype VComponent::get_dtstart() const {
364     return icalcomponent_get_dtstart(imp);
365 }
366 
set_dtstart(const struct icaltimetype & v)367 void VComponent::set_dtstart(const struct icaltimetype &v)
368 {
369     icalcomponent_set_dtstart(imp, v);
370 }
371 
372 /* For the icalcomponent routines only, dtend and duration are tied
373    together. If you call the set routine for one and the other exists,
374    the routine will calculate the change to the other. That is, if
375    there is a DTEND and you call set_duration, the routine will modify
376    DTEND to be the sum of DTSTART and the duration. If you call a get
377    routine for one and the other exists, the routine will calculate
378    the return value. If you call a set routine and neither exists, the
379    routine will create the apcompriate comperty.
380 */
381 
get_dtend() const382 struct icaltimetype VComponent::get_dtend() const {
383     return icalcomponent_get_dtend(imp);
384 }
385 
set_dtend(const struct icaltimetype & v)386 void VComponent::set_dtend(const struct icaltimetype &v)
387 {
388     icalcomponent_set_dtend(imp, v);
389 }
390 
get_due() const391 struct icaltimetype VComponent::get_due() const {
392     return icalcomponent_get_due(imp);
393 }
394 
set_due(const struct icaltimetype & v)395 void VComponent::set_due(const struct icaltimetype &v)
396 {
397     icalcomponent_set_due(imp, v);
398 }
399 
get_duration() const400 struct icaldurationtype VComponent::get_duration() const {
401     return icalcomponent_get_duration(imp);
402 }
403 
set_duration(const struct icaldurationtype & v)404 void VComponent::set_duration(const struct icaldurationtype &v)
405 {
406     icalcomponent_set_duration(imp, v);
407 }
408 
get_method() const409 icalproperty_method VComponent::get_method() const
410 {
411     return icalcomponent_get_method(imp);
412 }
413 
set_method(const icalproperty_method & method)414 void VComponent::set_method(const icalproperty_method &method)
415 {
416     icalcomponent_set_method(imp, method);
417 }
418 
get_dtstamp() const419 struct icaltimetype VComponent::get_dtstamp() const {
420     return icalcomponent_get_dtstamp(imp);
421 }
422 
set_dtstamp(const struct icaltimetype & v)423 void VComponent::set_dtstamp(const struct icaltimetype &v)
424 {
425     icalcomponent_set_dtstamp(imp, v);
426 }
427 
get_summary() const428 std::string VComponent::get_summary() const
429 {
430     return static_cast<std::string>(icalcomponent_get_summary(imp));
431 }
432 
set_summary(const std::string & v)433 void VComponent::set_summary(const std::string &v)
434 {
435     icalcomponent_set_summary(imp, v.c_str());
436 }
437 
get_location() const438 std::string VComponent::get_location() const
439 {
440     return static_cast<std::string>(icalcomponent_get_location(imp));
441 }
442 
set_location(const std::string & v)443 void VComponent::set_location(const std::string &v)
444 {
445     icalcomponent_set_location(imp, v.c_str());
446 }
447 
get_description() const448 std::string VComponent::get_description() const
449 {
450     return static_cast<std::string>(icalcomponent_get_description(imp));
451 }
452 
set_description(const std::string & v)453 void VComponent::set_description(const std::string &v)
454 {
455     icalcomponent_set_description(imp, v.c_str());
456 }
457 
get_comment() const458 std::string VComponent::get_comment() const
459 {
460     return static_cast<std::string>(icalcomponent_get_comment(imp));
461 }
462 
set_comment(const std::string & v)463 void VComponent::set_comment(const std::string &v)
464 {
465     icalcomponent_set_comment(imp, v.c_str());
466 }
467 
get_uid() const468 std::string VComponent::get_uid() const
469 {
470     return static_cast<std::string>(icalcomponent_get_uid(imp));
471 }
472 
set_uid(const std::string & v)473 void VComponent::set_uid(const std::string &v)
474 {
475     icalcomponent_set_uid(imp, v.c_str());
476 }
477 
get_relcalid() const478 std::string VComponent::get_relcalid() const
479 {
480     return static_cast<std::string>(icalcomponent_get_relcalid(imp));
481 }
482 
set_relcalid(const std::string & v)483 void VComponent::set_relcalid(const std::string &v)
484 {
485     icalcomponent_set_relcalid(imp, v.c_str());
486 }
487 
get_recurrenceid() const488 struct icaltimetype VComponent::get_recurrenceid() const {
489     return icalcomponent_get_recurrenceid(imp);
490 }
491 
set_recurrenceid(const struct icaltimetype & v)492 void VComponent::set_recurrenceid(const struct icaltimetype &v)
493 {
494     icalcomponent_set_recurrenceid(imp, v);
495 }
496 
get_sequence() const497 int VComponent::get_sequence() const
498 {
499     return icalcomponent_get_sequence(imp);
500 }
501 
set_sequence(const int & v)502 void VComponent::set_sequence(const int &v)
503 {
504     icalcomponent_set_sequence(imp, v);
505 }
506 
get_status() const507 int VComponent::get_status() const
508 {
509     return icalcomponent_get_status(imp);
510 }
511 
set_status(const enum icalproperty_status & v)512 void VComponent::set_status(const enum icalproperty_status &v)
513 {
514     icalcomponent_set_status(imp, v);
515 }
516 
517 /* For VCOMPONENT: Return a reference to the first VEVENT, VTODO, or VJOURNAL */
get_first_real_component()518 VComponent *VComponent::get_first_real_component()
519 {
520     return reinterpret_cast<VComponent *>(icalcomponent_get_first_real_component(imp));
521 }
522 
523 /* For VEVENT, VTODO, VJOURNAL and VTIMEZONE: report the start and end
524    times of an event in UTC */
get_span()525 struct icaltime_span VComponent::get_span()
526 {
527     return icalcomponent_get_span(imp);
528 }
529 
recurrence_is_excluded(struct icaltimetype * dtstart,struct icaltimetype * recurtime)530 int VComponent::recurrence_is_excluded(struct icaltimetype *dtstart,
531                                        struct icaltimetype *recurtime)
532 {
533     return  icalproperty_recurrence_is_excluded(imp, dtstart, recurtime);
534 }
535 
536 /* Internal operations. They are private, and you should not be using them. */
get_parent()537 VComponent *VComponent::get_parent()
538 {
539     return new VComponent(icalcomponent_get_parent(imp));
540 }
541 
set_parent(VComponent * parent)542 void VComponent::set_parent(VComponent *parent)
543 {
544     icalcomponent_set_parent(imp, *parent);
545 }
546 
547 /* ignoreValue means remove properties even if the data doesn't match */
remove(VComponent & fromVC,bool ignoreValue)548 bool VComponent::remove(VComponent &fromVC, bool ignoreValue)
549 {
550     /* the two components must be the same kind */
551     if (this->isa() != fromVC.isa()) {
552         return false;
553     }
554 
555     /* properties first */
556     ICalPropertyTmpPtr propToBeRemoved;
557     for (propToBeRemoved = fromVC.get_first_property(ICAL_ANY_PROPERTY);
558          propToBeRemoved != NULL;
559          propToBeRemoved = fromVC.get_next_property(ICAL_ANY_PROPERTY)) {
560 
561         /* loop through properties from this component */
562         ICalPropertyTmpPtr next;
563         ICalPropertyTmpPtr p;
564         for (p = this->get_first_property(propToBeRemoved->isa()); p != NULL; p = next) {
565             next = this->get_next_property(propToBeRemoved->isa());
566             if (ignoreValue) {
567                 this->remove_property(p);
568             } else {
569                 if (p == propToBeRemoved) {
570                     this->remove_property(p);
571                     break;
572                 }
573             }
574         }
575     }
576 
577     /* components next - should remove by UID */
578     VComponentTmpPtr comp;
579     for (comp = fromVC.get_first_component(ICAL_ANY_COMPONENT); comp != NULL;
580          comp = fromVC.get_next_component(ICAL_ANY_COMPONENT)) {
581         const std::string fromCompUid = comp->get_uid();
582         VComponentTmpPtr c;
583         for (c = this->get_first_component(comp->isa()); c != NULL;
584              c = this->get_next_component(comp->isa())) {
585             if (strcmp(fromCompUid.c_str(), c->get_uid().c_str()) == 0) {
586                 // recursively go down the components
587                 c->remove(*comp, ignoreValue);
588                 // if all properties are removed and there is no sub-components, then
589                 // remove this compoent
590                 if ((c->count_properties(ICAL_ANY_PROPERTY) == 0) &&
591                     (c->count_components(ICAL_ANY_COMPONENT) == 0)) {
592                     this->remove_component(c);
593                 }
594                 break;
595             }
596         }
597     }
598 
599     return true;
600 }
601 
602 /* removeMissing == true: remove properties that are missing from fromC */
603 /* todo: only change the first occurrence of the property */
604 /* todo: removeMissing is not implemented */
update(VComponent & fromC,bool removeMissing)605 bool VComponent::update(VComponent &fromC, bool removeMissing)
606 {
607     /* make sure they are the same kind */
608     if (this->isa() != fromC.isa()) {
609         return false;
610     }
611 
612     /* property first */
613     ICalPropertyTmpPtr prop;
614     for (prop = fromC.get_first_property(ICAL_ANY_PROPERTY); prop != NULL;
615          prop = fromC.get_next_property(ICAL_ANY_PROPERTY)) {
616         ICalPropertyTmpPtr thisProp;
617         thisProp = this->get_first_property(prop->isa());
618         if (thisProp == NULL) {
619             thisProp = new ICalProperty(prop->isa());
620             this->add_property(thisProp);
621         }
622         ICalValue *tempValue = prop->get_value();
623         ICalValue *value = new ICalValue(*tempValue); // clone the value
624         thisProp->set_value(*value);
625         delete tempValue;
626         delete value;
627     }
628 
629     /* recursively updating sub-components */
630     VComponentTmpPtr comp;
631     for (comp = fromC.get_first_component(ICAL_ANY_COMPONENT); comp != NULL;
632          comp = fromC.get_next_component(ICAL_ANY_COMPONENT)) {
633         VComponentTmpPtr thisComp;
634         thisComp = this->get_first_component(comp->isa());
635         if (thisComp == NULL) {
636             thisComp = new VComponent(comp->isa());
637             this->add_component(thisComp);
638         }
639         bool err = thisComp->update(*comp, removeMissing);
640         if (!err) {
641             return false;
642         }
643     }
644     return true;
645 }
646 
647 /* add components and property. recursively goes down child components */
add(VComponent & fromC)648 bool VComponent::add(VComponent &fromC)
649 {
650     /* make sure the kind are the same */
651     if (this->isa() != fromC.isa()) {
652         return false;
653     }
654 
655     /* properties first */
656     ICalPropertyTmpPtr prop;
657     for (prop = fromC.get_first_property(ICAL_ANY_PROPERTY); prop != NULL;
658          prop = fromC.get_next_property(ICAL_ANY_PROPERTY)) {
659         /* clone another property */
660         ICalProperty *p = new ICalProperty(*prop);
661         add_property(p);
662         delete p;
663     }
664 
665     /* sub-components next */
666     bool err = false;
667     VComponentTmpPtr comp;
668     for (comp = fromC.get_first_component(ICAL_ANY_COMPONENT); comp != NULL;
669          comp = fromC.get_next_component(ICAL_ANY_COMPONENT)) {
670         VComponent *c = new VComponent(comp->isa());
671         err = c->add(*comp);
672         _unused(err);
673         add_component(c);
674         delete c;
675     }
676 
677     return true;
678 }
679 
VCalendar()680 VCalendar::VCalendar() : VComponent(icalcomponent_new_vcalendar())
681 {
682 }
683 
VCalendar(const VCalendar & v)684 VCalendar::VCalendar(const VCalendar &v) : VComponent(v)
685 {
686 }
687 
operator =(const VCalendar & v)688 VCalendar &VCalendar::operator=(const VCalendar &v)
689 {
690     if (this == &v) {
691         return *this;
692     }
693     VComponent::operator=(v);
694 
695     return *this;
696 }
697 
~VCalendar()698 VCalendar::~VCalendar()
699 {
700 }
701 
VCalendar(icalcomponent * v)702 VCalendar::VCalendar(icalcomponent *v) : VComponent(v)
703 {
704 }
705 
VCalendar(const std::string & str)706 VCalendar::VCalendar(const std::string &str) : VComponent(str)
707 {
708 }
709 
710 /* VEvent */
711 
VEvent()712 VEvent::VEvent() : VComponent(icalcomponent_new_vevent())
713 {
714 }
715 
VEvent(const VEvent & v)716 VEvent::VEvent(const VEvent &v) : VComponent(v)
717 {
718 }
719 
operator =(const VEvent & v)720 VEvent &VEvent::operator=(const VEvent &v)
721 {
722     if (this == &v) {
723         return *this;
724     }
725     VComponent::operator=(v);
726 
727     return *this;
728 }
729 
~VEvent()730 VEvent::~VEvent()
731 {
732 }
733 
VEvent(icalcomponent * v)734 VEvent::VEvent(icalcomponent *v) : VComponent(v)
735 {
736 }
737 
VEvent(const std::string & str)738 VEvent::VEvent(const std::string &str) : VComponent(str)
739 {
740 }
741 
742 /* VTodo */
743 
VToDo()744 VToDo::VToDo() : VComponent(icalcomponent_new_vtodo())
745 {
746 }
747 
VToDo(const VToDo & v)748 VToDo::VToDo(const VToDo &v) : VComponent(v)
749 {
750 }
751 
operator =(const VToDo & v)752 VToDo &VToDo::operator=(const VToDo &v)
753 {
754     if (this == &v) {
755         return *this;
756     }
757     VComponent::operator=(v);
758 
759     return *this;
760 }
761 
~VToDo()762 VToDo::~VToDo()
763 {
764 }
765 
VToDo(icalcomponent * v)766 VToDo::VToDo(icalcomponent *v) : VComponent(v)
767 {
768 }
769 
VToDo(const std::string & str)770 VToDo::VToDo(const std::string &str) : VComponent(str)
771 {
772 }
773 
774 /* VAgenda */
775 
VAgenda()776 VAgenda::VAgenda() : VComponent(icalcomponent_new_vagenda())
777 {
778 }
779 
VAgenda(const VAgenda & v)780 VAgenda::VAgenda(const VAgenda &v) : VComponent(v)
781 {
782 }
783 
operator =(const VAgenda & v)784 VAgenda &VAgenda::operator=(const VAgenda &v)
785 {
786     if (this == &v) {
787         return *this;
788     }
789     VComponent::operator=(v);
790 
791     return *this;
792 }
793 
~VAgenda()794 VAgenda::~VAgenda()
795 {
796 }
797 
VAgenda(icalcomponent * v)798 VAgenda::VAgenda(icalcomponent *v) : VComponent(v)
799 {
800 }
801 
VAgenda(const std::string & str)802 VAgenda::VAgenda(const std::string &str) : VComponent(str)
803 {
804 }
805 
806 /* VQuery */
807 
VQuery()808 VQuery::VQuery() : VComponent(icalcomponent_new_vquery())
809 {
810 }
811 
VQuery(const VQuery & v)812 VQuery::VQuery(const VQuery &v) : VComponent(v)
813 {
814 }
815 
operator =(const VQuery & v)816 VQuery &VQuery::operator=(const VQuery &v)
817 {
818     if (this == &v) {
819         return *this;
820     }
821     VComponent::operator=(v);
822 
823     return *this;
824 }
825 
~VQuery()826 VQuery::~VQuery()
827 {
828 }
829 
VQuery(icalcomponent * v)830 VQuery::VQuery(icalcomponent *v) : VComponent(v)
831 {
832 }
833 
VQuery(const std::string & str)834 VQuery::VQuery(const std::string &str) : VComponent(str)
835 {
836 }
837 
838 /* VJournal */
839 
VJournal()840 VJournal::VJournal() : VComponent(icalcomponent_new_vjournal())
841 {
842 }
843 
VJournal(const VJournal & v)844 VJournal::VJournal(const VJournal &v) : VComponent(v)
845 {
846 }
847 
operator =(const VJournal & v)848 VJournal &VJournal::operator=(const VJournal &v)
849 {
850     if (this == &v) {
851         return *this;
852     }
853     VComponent::operator=(v);
854 
855     return *this;
856 }
857 
~VJournal()858 VJournal::~VJournal()
859 {
860 }
861 
VJournal(icalcomponent * v)862 VJournal::VJournal(icalcomponent *v) : VComponent(v)
863 {
864 }
865 
VJournal(const std::string & str)866 VJournal::VJournal(const std::string &str) : VComponent(str)
867 {
868 }
869 
870 /* VAlarm */
871 
VAlarm()872 VAlarm::VAlarm() : VComponent(icalcomponent_new_valarm())
873 {
874 }
875 
VAlarm(const VAlarm & v)876 VAlarm::VAlarm(const VAlarm &v) : VComponent(v)
877 {
878 }
879 
operator =(const VAlarm & v)880 VAlarm &VAlarm::operator=(const VAlarm &v)
881 {
882     if (this == &v) {
883         return *this;
884     }
885     VComponent::operator=(v);
886 
887     return *this;
888 }
889 
~VAlarm()890 VAlarm::~VAlarm()
891 {
892 }
893 
VAlarm(icalcomponent * v)894 VAlarm::VAlarm(icalcomponent *v) : VComponent(v)
895 {
896 }
897 
VAlarm(const std::string & str)898 VAlarm::VAlarm(const std::string &str) : VComponent(str)
899 {
900 }
901 
getTriggerTime(VComponent & c,struct icaltriggertype * tr)902 icalrequeststatus VAlarm::getTriggerTime(VComponent &c, struct icaltriggertype *tr)
903 {
904     ICalPropertyTmpPtr trigger_prop = this->get_first_property(ICAL_TRIGGER_PROPERTY);
905 
906     // all VALARMs must have a TRIGGER
907     if (trigger_prop == NULL) {
908         return ICAL_3_1_INVPROPVAL_STATUS;
909     }
910 
911     *tr = trigger_prop->get_trigger();
912 
913     if (icaltime_is_null_time(tr->time) == 1) {
914         struct icaltimetype tt = icaltime_null_time();
915 
916         // relative time trigger
917 
918         // TRIGGER;RELATED=END:P5M 5 minutes after END
919         // TRIGGER;RELATED=START:-P15M 15 minutes before START
920         // get RELATED parameter
921 
922         ICalParameter *related_param = trigger_prop->get_first_parameter(ICAL_RELATED_PARAMETER);
923 
924         if ((related_param != NULL) && related_param->is_valid()) {
925 
926             // get RELATED parameter value
927             icalparameter_related related = related_param->get_related();
928 
929             if (related != 0) {
930                 switch (related) {
931                 case ICAL_RELATED_END:
932                     if (c.isa() == ICAL_VEVENT_COMPONENT) {
933                         tt = c.get_dtend();
934 
935                         // If a recurrenceid exists, use that to calculate the
936                         // dtend from the dtstart.
937                         struct icaltimetype recur_time = c.get_recurrenceid();
938                         if (icaltime_is_null_time(recur_time) != 1) {
939                             struct icaldurationtype dur = icaltime_subtract(c.get_dtstart(), tt);
940                             tt = icaltime_add(recur_time, dur);
941                         }
942                     } else if (c.isa() == ICAL_VTODO_COMPONENT) {
943                         tt = c.get_due();
944                         struct icaltimetype recur_time = c.get_recurrenceid();
945                         if (icaltime_is_null_time(recur_time) != 1) {
946                             tt = recur_time;
947                         }
948                     }
949                     // @@@ TODO: if not DTEND or DUE, then DTSTART and DURATION must be present
950                     break;
951                 case ICAL_RELATED_START:
952                 case ICAL_RELATED_X:
953                 case ICAL_RELATED_NONE:
954                 default:
955                     tt = c.get_dtstart();
956                     struct icaltimetype recur_time = c.get_recurrenceid();
957                     if (icaltime_is_null_time(recur_time) != 1) {
958                         tt = recur_time;
959                     }
960                     break;
961                 }
962             }
963         } else { // no RELATED explicitly specified, the default is
964             // relative to the start of an event or to-do, rfc2445
965             // if no RELATED, we are forced to use dtstart for VEVENT,
966             // due for VTODO to calculate trigger time.
967             // If a recur time exists, use that. Recur time trumps dtstart or due.
968             struct icaltimetype recur_time = c.get_recurrenceid();
969             if (icaltime_is_null_time(recur_time) != 1) {
970                 tt = recur_time;
971             } else if (c.isa() == ICAL_VEVENT_COMPONENT) {
972                 tt = c.get_dtstart();
973             } else if (c.isa() == ICAL_VTODO_COMPONENT) {
974                 tt = c.get_due();
975             }
976         }
977 
978         delete related_param;
979 
980         // malformed? encapsulating VEVENT or VTODO MUST have DTSTART/DTEND
981         if (icaltime_is_null_time(tt) == 1) {
982             return ICAL_3_1_INVPROPVAL_STATUS;
983         };
984 
985         // now offset using tr.duration
986         tr->time = icaltime_add(tt, tr->duration);
987     }
988     // else absolute time trigger
989 
990     return ICAL_2_0_SUCCESS_STATUS;
991 }
992 
993 /* VFreeBusy */
994 
VFreeBusy()995 VFreeBusy::VFreeBusy() : VComponent(icalcomponent_new_vfreebusy())
996 {
997 }
998 
VFreeBusy(const VFreeBusy & v)999 VFreeBusy::VFreeBusy(const VFreeBusy &v) : VComponent(v)
1000 {
1001 }
1002 
operator =(const VFreeBusy & v)1003 VFreeBusy &VFreeBusy::operator=(const VFreeBusy &v)
1004 {
1005     if (this == &v) {
1006         return *this;
1007     }
1008     VComponent::operator=(v);
1009 
1010     return *this;
1011 }
1012 
~VFreeBusy()1013 VFreeBusy::~VFreeBusy()
1014 {
1015 }
1016 
VFreeBusy(icalcomponent * v)1017 VFreeBusy::VFreeBusy(icalcomponent *v) : VComponent(v)
1018 {
1019 }
1020 
VFreeBusy(const std::string & str)1021 VFreeBusy::VFreeBusy(const std::string &str) : VComponent(str)
1022 {
1023 }
1024 
1025 /* VTimezone */
1026 
VTimezone()1027 VTimezone::VTimezone() : VComponent(icalcomponent_new_vtimezone())
1028 {
1029 }
1030 
VTimezone(const VTimezone & v)1031 VTimezone::VTimezone(const VTimezone &v) : VComponent(v)
1032 {
1033 }
1034 
operator =(const VTimezone & v)1035 VTimezone &VTimezone::operator=(const VTimezone &v)
1036 {
1037     if (this == &v) {
1038         return *this;
1039     }
1040     VComponent::operator=(v);
1041 
1042     return *this;
1043 }
1044 
~VTimezone()1045 VTimezone::~VTimezone()
1046 {
1047 }
1048 
VTimezone(icalcomponent * v)1049 VTimezone::VTimezone(icalcomponent *v) : VComponent(v)
1050 {
1051 }
1052 
VTimezone(const std::string & str)1053 VTimezone::VTimezone(const std::string &str) : VComponent(str)
1054 {
1055 }
1056 
1057 /* XStandard */
1058 
XStandard()1059 XStandard::XStandard() : VComponent(icalcomponent_new_xstandard())
1060 {
1061 }
1062 
XStandard(const XStandard & v)1063 XStandard::XStandard(const XStandard &v) : VComponent(v)
1064 {
1065 }
1066 
operator =(const XStandard & v)1067 XStandard &XStandard::operator=(const XStandard &v)
1068 {
1069     if (this == &v) {
1070         return *this;
1071     }
1072     VComponent::operator=(v);
1073 
1074     return *this;
1075 }
1076 
~XStandard()1077 XStandard::~XStandard()
1078 {
1079 }
1080 
XStandard(icalcomponent * v)1081 XStandard::XStandard(icalcomponent *v) : VComponent(v)
1082 {
1083 }
1084 
XStandard(const std::string & str)1085 XStandard::XStandard(const std::string &str) : VComponent(str)
1086 {
1087 }
1088 
1089 /* XDaylight */
1090 
XDaylight()1091 XDaylight::XDaylight() : VComponent(icalcomponent_new_xdaylight())
1092 {
1093 }
1094 
XDaylight(const XDaylight & v)1095 XDaylight::XDaylight(const XDaylight &v) : VComponent(v)
1096 {
1097 }
1098 
operator =(const XDaylight & v)1099 XDaylight &XDaylight::operator=(const XDaylight &v)
1100 {
1101     if (this == &v) {
1102         return *this;
1103     }
1104     VComponent::operator=(v);
1105 
1106     return *this;
1107 }
1108 
~XDaylight()1109 XDaylight::~XDaylight()
1110 {
1111 }
1112 
XDaylight(icalcomponent * v)1113 XDaylight::XDaylight(icalcomponent *v) : VComponent(v)
1114 {
1115 }
1116 
XDaylight(const std::string & str)1117 XDaylight::XDaylight(const std::string &str) : VComponent(str)
1118 {
1119 }
1120