Libical API Documentation 4.0 STABLE VERSION [Visit the v3.0 documentation]
Loading...
Searching...
No Matches
icalfileset.c
Go to the documentation of this file.
1/*======================================================================
2 FILE: icalfileset.c
3 CREATOR: eric 23 December 1999
4
5 SPDX-FileCopyrightText: 2000, Eric Busboom <eric@civicknowledge.com>
6 SPDX-License-Identifier: LGPL-2.1-only OR MPL-2.0
7
8 The Original Code is eric. The Initial Developer of the Original
9 Code is Eric Busboom
10======================================================================*/
11//krazy:excludeall=cpp
12
18
19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
22
23#include "icalfileset.h"
24#include "icalfilesetimpl.h"
25#include "icalerror_p.h"
26#include "icalparser.h"
27#include "icalvalue.h"
28#include "icalmemory.h"
29
30#include <errno.h>
31#include <stdlib.h>
32
33#if defined(_MSC_VER)
34typedef int mode_t;
35#endif
36
37#if defined(_WIN32_WCE)
38#include <winbase.h>
39#endif
40
42icalfileset_options icalfileset_options_default = {O_RDWR | O_CREAT, 0644, 0, NULL};
43
44static int _compare_ids(const char *compid, const char *matchid);
45
46static int icalfileset_lock(icalfileset *set);
47static int icalfileset_unlock(icalfileset *set);
48static icalerrorenum icalfileset_read_file(icalfileset *set, int mode);
49static long icalfileset_filesize(icalfileset *set);
50
51icalset *icalfileset_new(const char *path)
52{
54}
55
56icalset *icalfileset_new_reader(const char *path)
57{
59
60 reader_options.flags = O_RDONLY;
61
62 return icalset_new(ICAL_FILE_SET, path, &reader_options);
63}
64
65icalset *icalfileset_new_writer(const char *path)
66{
68
69 writer_options.flags = O_RDONLY;
70
71 return icalset_new(ICAL_FILE_SET, path, &writer_options);
72}
73
74icalset *icalfileset_init(icalset *set, const char *path, void *options_in)
75{
76 const icalfileset_options *options = options_in ? options_in : &icalfileset_options_default;
77 icalfileset *fset = (icalfileset *)set;
78 int flags;
79 int mode;
80 long cluster_file_size;
81
83 icalerror_check_arg_rz((path != 0), "path");
84 icalerror_check_arg_rz((fset != 0), "fset");
85
86 fset->path = strdup(path);
87 fset->options = *options;
88
89 flags = options->flags;
90 mode = options->mode;
91
92 cluster_file_size = icalfileset_filesize(fset);
93
94 if (cluster_file_size < 0) {
96 return 0;
97 }
98
99 fset->fd = open(fset->path, flags, (mode_t)mode);
100
101 if (fset->fd < 0) {
103 icalfileset_free(set);
104 return 0;
105 }
106
107 (void)icalfileset_lock(fset);
108
109 if (cluster_file_size > 0) {
110 if (icalfileset_read_file(fset, mode) != ICAL_NO_ERROR) {
111 icalfileset_free(set);
112 return 0;
113 }
114 }
115
116 if (options->cluster) {
117 fset->cluster = icalcomponent_clone(icalcluster_get_component(options->cluster));
118 fset->changed = 1;
119 }
120
121 if (fset->cluster == 0) {
123 }
124
125 return set;
126}
127
129{
130 icalset *fileset;
131 icalcluster *ret;
132
133 bool errstate = icalerror_get_errors_are_fatal();
134
136
137 fileset = icalfileset_new_reader(path);
138
139 if (fileset == 0 || icalerrno == ICAL_FILE_ERROR) {
140 /* file does not exist */
141 ret = icalcluster_new(path, NULL);
142 } else {
143 ret = icalcluster_new(path, ((icalfileset *)fileset)->cluster);
144 icalfileset_free(fileset);
145 }
146
149 return ret;
150}
151
152static char *icalfileset_read_from_file(char *s, size_t size, void *d)
153{
154 char *p;
155 icalfileset *set = d;
156
157 /* Simulate fgets -- read single characters and stop at '\n' */
158
159 for (p = s; p < s + size - 1; p++) {
160 if (read(set->fd, p, 1) != 1 || *p == '\n') {
161 p++;
162 break;
163 }
164 }
165
166 *p = '\0';
167
168 if (*s == 0) {
169 return 0;
170 } else {
171 return s;
172 }
173}
174
175icalerrorenum icalfileset_read_file(icalfileset *set, int mode)
176{
177 icalparser *parser;
178
179 _unused(mode);
180
181 parser = icalparser_new();
182
183 icalparser_set_gen_data(parser, set);
184 set->cluster = icalparser_parse(parser, icalfileset_read_from_file);
185 icalparser_free(parser);
186
187 if (set->cluster == 0 || icalerrno != ICAL_NO_ERROR) {
189 /*return ICAL_PARSE_ERROR; */
190 }
191
192 if (icalcomponent_isa(set->cluster) != ICAL_XROOT_COMPONENT) {
193 /* The parser got a single component, so it did not put it in
194 an XROOT. */
195 icalcomponent *cl = set->cluster;
196
198 icalcomponent_add_component(set->cluster, cl);
199 }
200
201 return ICAL_NO_ERROR;
202}
203
204long icalfileset_filesize(icalfileset *fset)
205{
206 struct stat sbuf;
207
208 if (!fset || !fset->path || fset->path[0] == '\0') {
209 return -1;
210 }
211
212 if (stat(fset->path, &sbuf) != 0) {
213 /* A file by the given name does not exist, or there was
214 another error */
215 if (errno == ENOENT) {
216 /* It was because the file does not exist */
217 return 0;
218 } else {
219 /* It was because of another error */
221 return -1;
222 }
223 } else {
224 /* A file by the given name exists, but is it a regular file? */
225
226 if (!S_ISREG(sbuf.st_mode)) {
227 /* Nope, not a regular file */
229 return -1;
230 } else {
231 /* Let's assume that it is a file of the right type */
232 return (long)sbuf.st_size;
233 }
234 }
235}
236
237void icalfileset_free(icalset *set)
238{
239 icalfileset *fset;
240
241 icalerror_check_arg_rv((set != 0), "set");
242
243 fset = (icalfileset *)set;
244
245 if (fset->cluster != 0) {
246 (void)icalfileset_commit(set);
247 icalcomponent_free(fset->cluster);
248 fset->cluster = 0;
249 }
250
251 if (fset->gauge != 0) {
252 icalgauge_free(fset->gauge);
253 fset->gauge = 0;
254 }
255
256 if (fset->fd > 0) {
257 (void)icalfileset_unlock(fset);
258 close(fset->fd);
259 fset->fd = -1;
260 }
261
262 if (fset->path != 0) {
263 free(fset->path);
264 fset->path = 0;
265 }
266}
267
268const char *icalfileset_path(icalset *set)
269{
270 icalerror_check_arg_rz((set != 0), "set");
271
272 return ((icalfileset *)set)->path;
273}
274
275int icalfileset_lock(icalfileset *set)
276{
277#if !defined(_WIN32)
278 struct flock lock;
279 int rtrn;
280
281 icalerror_check_arg_rz((set->fd > 0), "set->fd");
282 errno = 0;
283 lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */
284 lock.l_start = 0; /* byte offset relative to l_whence */
285 lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
286 lock.l_len = 0; /* #bytes (0 means to EOF) */
287
288 rtrn = fcntl(set->fd, F_SETLKW, &lock);
289
290 return rtrn;
291#else
292 _unused(set);
293 return 0;
294#endif
295}
296
297int icalfileset_unlock(icalfileset *set)
298{
299#if !defined(_WIN32)
300 struct flock lock;
301
302 icalerror_check_arg_rz((set->fd > 0), "set->fd");
303
304 lock.l_type = F_WRLCK; /* F_RDLCK, F_WRLCK, F_UNLCK */
305 lock.l_start = 0; /* byte offset relative to l_whence */
306 lock.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
307 lock.l_len = 0; /* #bytes (0 means to EOF) */
308
309 return (fcntl(set->fd, F_UNLCK, &lock));
310#else
311 _unused(set);
312 return 0;
313#endif
314}
315
316/* Lifted from https://stackoverflow.com/questions/29079011/copy-file-function-in-c */
317static int file_copy(const char *fileSource, const char *fileDestination)
318{
319 char c[1024]; // or any other constant you like
320 FILE *stream_R, *stream_W;
321
322 if ((stream_R = fopen(fileSource, "r")) == (FILE *)NULL) {
323 return -1;
324 }
325 if ((stream_W = fopen(fileDestination, "w")) == (FILE *)NULL) {
326 fclose(stream_R);
327 return -1;
328 }
329
330 size_t bytes;
331 while (!feof(stream_R) && !ferror(stream_R) && (bytes = fread(c, 1, sizeof(c), stream_R)) != 0) {
332 (void)fwrite(c, 1, bytes, stream_W);
333 }
334
335 //close streams
336 fclose(stream_R);
337 fclose(stream_W);
338
339 return 0;
340}
341
343{
344 char backupFile[MAXPATHLEN];
345 char *str;
346 icalcomponent *c;
347#if !defined(_WIN32)
348 size_t write_size = 0;
349#endif
350 icalfileset *fset = (icalfileset *)set;
351
352 icalerror_check_arg_re((fset != 0), "set", ICAL_BADARG_ERROR);
353
354 icalerror_check_arg_re((fset->fd > 0), "set->fd is invalid", ICAL_INTERNAL_ERROR);
355
356 if (fset->changed == 0) {
357 return ICAL_NO_ERROR;
358 }
359
360 if (fset->options.safe_saves == 1) {
361 strncpy(backupFile, fset->path, MAXPATHLEN - 4);
362 strncat(backupFile, ".bak", MAXPATHLEN - 1);
363 if (file_copy(fset->path, backupFile) != 0) {
365 return ICAL_FILE_ERROR;
366 }
367 }
368
369 if (lseek(fset->fd, 0, SEEK_SET) < 0) {
371 return ICAL_FILE_ERROR;
372 }
373
375 c != 0; c = icalcomponent_get_next_component(fset->cluster, ICAL_ANY_COMPONENT)) {
376 IO_SSIZE_T sz;
377
379 if (!str) {
382 }
383 sz = write(fset->fd, str, (IO_SIZE_T)strlen(str));
384 if (sz != (IO_SSIZE_T)strlen(str)) {
385 perror("write");
388 return ICAL_FILE_ERROR;
389 }
390
392#if !defined(_WIN32)
393 write_size += (size_t)sz;
394#endif
395 }
396
397 fset->changed = 0;
398
399#if !defined(_WIN32)
400 if (ftruncate(fset->fd, (off_t)write_size) < 0) {
401 return ICAL_FILE_ERROR;
402 }
403#else
404#if !defined(_WIN32_WCE)
405 chsize(fset->fd, tell(fset->fd));
406#else
407 SetEndOfFile(fset->fd);
408#endif
409#endif
410
411 return ICAL_NO_ERROR;
412}
413
414void icalfileset_mark(icalset *set)
415{
416 icalerror_check_arg_rv((set != 0), "set");
417
418 ((icalfileset *)set)->changed = 1;
419}
420
421icalcomponent *icalfileset_get_component(icalset *set)
422{
423 const icalfileset *fset;
424
425 icalerror_check_arg_rz((set != 0), "set");
426
427 fset = (icalfileset *)set;
428 return fset->cluster;
429}
430
431/* manipulate the components in the set */
432
433icalerrorenum icalfileset_add_component(icalset *set, icalcomponent *child)
434{
435 icalfileset *fset;
436
437 icalerror_check_arg_re((set != 0), "set", ICAL_BADARG_ERROR);
438 icalerror_check_arg_re((child != 0), "child", ICAL_BADARG_ERROR);
439
440 fset = (icalfileset *)set;
441 icalcomponent_add_component(fset->cluster, child);
442
443 icalfileset_mark(set);
444
445 return ICAL_NO_ERROR;
446}
447
448icalerrorenum icalfileset_remove_component(icalset *set, icalcomponent *child)
449{
450 icalfileset *fset;
451
452 icalerror_check_arg_re((set != 0), "set", ICAL_BADARG_ERROR);
453 icalerror_check_arg_re((child != 0), "child", ICAL_BADARG_ERROR);
454
455 fset = (icalfileset *)set;
456 icalcomponent_remove_component(fset->cluster, child);
457
458 icalfileset_mark(set);
459
460 return ICAL_NO_ERROR;
461}
462
464{
465 icalfileset *fset;
466
467 if (set == 0) {
469 return -1;
470 }
471
472 fset = (icalfileset *)set;
473 return icalcomponent_count_components(fset->cluster, kind);
474}
475
476icalerrorenum icalfileset_select(icalset *set, icalgauge *gauge)
477{
478 icalfileset *fset;
479
480 icalerror_check_arg_re(gauge != 0, "gauge", ICAL_BADARG_ERROR);
481
482 fset = (icalfileset *)set;
483 fset->gauge = gauge;
484
485 return ICAL_NO_ERROR;
486}
487
488void icalfileset_clear(icalset *set)
489{
490 icalfileset *fset;
491
492 icalerror_check_arg_rv(set != 0, "set");
493
494 fset = (icalfileset *)set;
495 fset->gauge = 0;
496}
497
498icalcomponent *icalfileset_fetch(icalset *set, icalcomponent_kind kind, const char *uid)
499{
500 icalfileset *fset;
501 icalcompiter i;
502
503 _unused(kind);
504
505 icalerror_check_arg_rz(set != 0, "set");
506 fset = (icalfileset *)set;
507
508 for (i = icalcomponent_begin_component(fset->cluster, ICAL_ANY_COMPONENT);
510 icalcomponent *this = icalcompiter_deref(&i);
511 icalcomponent *inner;
512
514 inner != 0; inner = icalcomponent_get_next_component(this, ICAL_ANY_COMPONENT)) {
515 icalproperty *p = icalcomponent_get_first_property(inner, ICAL_UID_PROPERTY);
516 if (p) {
517 const char *this_uid = icalproperty_get_uid(p);
518
519 if (this_uid == 0) {
520 icalerror_warn("icalfileset_fetch found a component with no UID");
521 continue;
522 }
523
524 if (strcmp(uid, this_uid) == 0) {
525 return this;
526 }
527 }
528 }
529 }
530
531 return 0;
532}
533
534int icalfileset_has_uid(icalset *set, const char *uid)
535{
536 _unused(set);
537 _unused(uid);
538 assert(0); /* HACK, not implemented */
539 return 0;
540}
541
542/******* support routines for icalfileset_fetch_match *********/
543
544struct icalfileset_id {
545 char *uid;
546 char *recurrence_id;
547 int sequence;
548};
549
550static void icalfileset_id_free(struct icalfileset_id *id)
551{
552 if (id->recurrence_id != 0) {
553 free(id->recurrence_id);
554 }
555
556 if (id->uid != 0) {
557 free(id->uid);
558 }
559}
560
561static struct icalfileset_id icalfileset_get_id(const icalcomponent *comp)
562{
563 icalcomponent *inner;
564 struct icalfileset_id id;
565 icalproperty *p;
566
568
570
571 assert(p != 0);
572
573 id.uid = strdup(icalproperty_get_uid(p));
574
576
577 if (p == 0) {
578 id.sequence = 0;
579 } else {
580 id.sequence = icalproperty_get_sequence(p);
581 }
582
584
585 if (p == 0) {
586 id.recurrence_id = NULL;
587 } else {
588 icalvalue *v;
589
591 id.recurrence_id = icalvalue_as_ical_string_r(v);
592
593 assert(id.recurrence_id != 0);
594 }
595
596 return id;
597}
598
599/* Find the component that is related to the given
600 component. Currently, it just matches based on UID and
601 RECURRENCE-ID */
602
603static int _compare_ids(const char *compid, const char *matchid)
604{
605 if (compid != NULL && matchid != NULL) {
606 if (strcmp(compid, matchid) == 0) {
607 return 1;
608 }
609 }
610
611 if (compid == NULL && matchid == NULL) {
612 return 1;
613 }
614
615 return 0;
616}
617
618icalcomponent *icalfileset_fetch_match(icalset *set, const icalcomponent *comp)
619{
620 icalfileset *fset = (icalfileset *)set;
621 icalcompiter i;
622
623 struct icalfileset_id comp_id, match_id;
624
625 comp_id = icalfileset_get_id(comp);
626
627 for (i = icalcomponent_begin_component(fset->cluster, ICAL_ANY_COMPONENT);
629 icalcomponent *match = icalcompiter_deref(&i);
630
631 match_id = icalfileset_get_id(match);
632
633 if (_compare_ids(comp_id.uid, match_id.uid) &&
634 _compare_ids(comp_id.recurrence_id, match_id.recurrence_id)) {
635 /* HACK. What to do with SEQUENCE? */
636
637 icalfileset_id_free(&match_id);
638 icalfileset_id_free(&comp_id);
639 return match;
640 }
641
642 icalfileset_id_free(&match_id);
643 }
644
645 icalfileset_id_free(&comp_id);
646 return 0;
647}
648
649icalerrorenum icalfileset_modify(icalset *set, icalcomponent *old, icalcomponent *new)
650{
651 _unused(set);
652 _unused(old);
653 _unused(new);
654 assert(0); /* HACK, not implemented */
655 return ICAL_NO_ERROR;
656}
657
658/* Iterate through components */
659icalcomponent *icalfileset_get_current_component(icalset *set)
660{
661 icalfileset *fset;
662
663 icalerror_check_arg_rz((set != 0), "set");
664
665 fset = (icalfileset *)set;
666 return icalcomponent_get_current_component(fset->cluster);
667}
668
669icalcomponent *icalfileset_get_first_component(icalset *set)
670{
671 icalcomponent *c = 0;
672 icalfileset *fset;
673
674 icalerror_check_arg_rz((set != 0), "set");
675 fset = (icalfileset *)set;
676
677 do {
678 if (c == 0) {
680 } else {
682 }
683
684 if (c != 0 && (fset->gauge == 0 || icalgauge_compare(fset->gauge, c))) {
685 return c;
686 }
687
688 } while (c != 0);
689
690 return 0;
691}
692
693icalcomponent *icalfileset_get_next_component(icalset *set)
694{
695 icalfileset *fset;
696 icalcomponent *c;
697
698 icalerror_check_arg_rz((set != 0), "set");
699 fset = (icalfileset *)set;
700
701 do {
703
704 if (c != 0 && (fset->gauge == 0 || icalgauge_compare(fset->gauge, c))) {
705 return c;
706 }
707
708 } while (c != 0);
709
710 return 0;
711}
712
713/*
714icalsetiter icalfileset_begin_component(icalset* set, icalcomponent_kind kind, icalgauge* gauge)
715{
716 icalsetiter itr = icalsetiter_null;
717 icalcomponent* comp = NULL;
718 icalcompiter citr;
719 icalfileset *fset = (icalfileset*)set;
720
721 icalerror_check_arg_re((set!=0), "set", icalsetiter_null);
722
723 itr.gauge = gauge;
724
725 citr = icalcomponent_begin_component(fset->cluster, kind);
726 comp = icalcompiter_deref(&citr);
727
728 while (comp != 0) {
729 comp = icalcompiter_deref(&citr);
730 if (gauge == 0 || icalgauge_compare(itr.gauge, comp) == 1) {
731 itr.iter = citr;
732 return itr;
733 }
734 comp = icalcompiter_next(&citr);
735 }
736
737 return icalsetiter_null;
738}
739
740*/
741
743 const char *tzid)
744{
746 icalcomponent *comp = NULL;
747 icalcompiter citr;
748 icalfileset *fset;
749 struct icaltimetype start, next;
750 icalproperty *rrule;
751
752 _unused(tzid);
753
754 icalerror_check_arg_re((set != 0), "set", icalsetiter_null);
755
756 start = icaltime_from_timet_with_zone(time(0), false, NULL);
757 itr.gauge = gauge;
758
759 fset = (icalfileset *)set;
760 citr = icalcomponent_begin_component(fset->cluster, kind);
761 comp = icalcompiter_deref(&citr);
762
763 if (gauge == 0) {
764 itr.iter = citr;
765 return itr;
766 }
767
768 while (comp != 0) {
769 /* check if it is a recurring component and with gauge expand, if so
770 we need to add recurrence-id property to the given component */
772 struct icalrecurrencetype *recur = rrule ? icalproperty_get_rrule(rrule) : NULL;
773 int g = icalgauge_get_expand(gauge);
774 if (recur != 0 && g == 1) {
776 icalproperty *dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
777 if (dtstart) {
778 start = icalproperty_get_dtstart(dtstart);
779 }
780 } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) {
781 icalproperty *due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY);
782 if (due) {
783 start = icalproperty_get_due(due);
784 }
785 }
786
787 if (itr.last_component == NULL) {
788 itr.ritr = icalrecur_iterator_new(recur, start);
789 next = icalrecur_iterator_next(itr.ritr);
790 itr.last_component = comp;
791 } else {
792 next = icalrecur_iterator_next(itr.ritr);
793 if (icaltime_is_null_time(next)) {
794 itr.last_component = NULL;
796 itr.ritr = NULL;
797 return icalsetiter_null;
798 } else {
799 itr.last_component = comp;
800 }
801 }
802
803 /* add recurrence-id to the component
804 if there is a recurrence-id already, remove it, then add the new one */
806 if (prop) {
808 }
810 }
811
812 if (icalgauge_compare(itr.gauge, comp)) {
813 /* matches and returns */
814 itr.iter = citr;
815 return itr;
816 }
817
818 /* if there is no previous component pending, then get the next component */
819 if (itr.last_component == NULL) {
820 comp = icalcompiter_next(&citr);
821 }
822 }
823
824 return icalsetiter_null;
825}
826
828{
829 icalcomponent *comp = NULL;
830 struct icaltimetype start, next;
831 icalproperty *rrule, *prop;
832 struct icalrecurrencetype *recur;
833
834 start = icaltime_from_timet_with_zone(time(0), false, NULL);
835 comp = itr->last_component;
836
837 if (comp == NULL || itr->gauge == NULL) {
838 return NULL;
839 }
840
842 recur = rrule ? icalproperty_get_rrule(rrule) : NULL;
843
844 if (recur == NULL) {
845 return NULL;
846 }
847
849 icalproperty *dtstart = icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
850 if (dtstart) {
851 start = icalproperty_get_dtstart(dtstart);
852 }
853 } else if (icalcomponent_isa(comp) == ICAL_VTODO_COMPONENT) {
854 icalproperty *due = icalcomponent_get_first_property(comp, ICAL_DUE_PROPERTY);
855 if (due) {
856 start = icalproperty_get_due(due);
857 }
858 }
859
860 if (itr->ritr == NULL) {
861 itr->ritr = icalrecur_iterator_new(recur, start);
862 next = icalrecur_iterator_next(itr->ritr);
863 itr->last_component = comp;
864 } else {
865 next = icalrecur_iterator_next(itr->ritr);
866 if (icaltime_is_null_time(next)) {
867 /* no more recurrence, returns */
868 itr->last_component = NULL;
870 itr->ritr = NULL;
871 return NULL;
872 } else {
873 itr->last_component = comp;
874 }
875 }
876
877 /* add recurrence-id to the component
878 * if there is a recurrence-id already, remove it, then add the new one */
880 if (prop) {
882 }
884
885 if (itr->gauge == 0 || icalgauge_compare(itr->gauge, comp)) {
886 /* matches and returns */
887 return comp;
888 }
889 /* not matched */
890 return NULL;
891}
892
893icalcomponent *icalfilesetiter_to_next(icalset *set, icalsetiter *i)
894{
895 icalcomponent *c = NULL;
896 struct icaltimetype start, next;
897 icalproperty *dtstart, *rrule, *prop, *due;
898 struct icalrecurrencetype *recur;
899 int g = 0;
900
901 _unused(set);
902
903 start = icaltime_from_timet_with_zone(time(0), false, NULL);
904 next = icaltime_from_timet_with_zone(time(0), false, NULL);
905
906 do {
907 c = icalcompiter_next(&(i->iter));
908
909 if (c == 0) {
910 continue;
911 }
912 if (i->gauge == 0) {
913 return c;
914 }
915
917 recur = rrule ? icalproperty_get_rrule(rrule) : NULL;
919
920 /* a recurring component with expand query */
921 if (recur != 0 && g == 1) {
924 if (dtstart) {
925 start = icalproperty_get_dtstart(dtstart);
926 }
927 } else if (icalcomponent_isa(c) == ICAL_VTODO_COMPONENT) {
929 if (due) {
930 start = icalproperty_get_due(due);
931 }
932 }
933
934 if (i->ritr == NULL) {
935 i->ritr = icalrecur_iterator_new(recur, start);
936 next = icalrecur_iterator_next(i->ritr);
937 i->last_component = c;
938 } else {
939 next = icalrecur_iterator_next(i->ritr);
940 if (icaltime_is_null_time(next)) {
941 /* no more recurrence, returns */
942 i->last_component = NULL;
944 i->ritr = NULL;
945 return NULL;
946 } else {
947 i->last_component = c;
948 }
949 }
950 }
951
952 /* add recurrence-id to the component
953 * if there is a recurrence-id already, remove it, then add the new one */
955 if (prop) {
957 }
959
960 if ((i->gauge == 0 || icalgauge_compare(i->gauge, c))) {
961 return c;
962 }
963 } while (true);
964
965 return 0;
966}
icalcomponent * icalcluster_get_component(const icalcluster *cluster)
icalcluster * icalcluster_new(const char *key, icalcomponent *data)
Create a cluster with a key/value pair.
Definition icalcluster.c:39
struct icalcluster_impl icalcluster
Definition icalcluster.h:29
icalproperty * icalcomponent_get_first_property(icalcomponent *c, icalproperty_kind kind)
icalcomponent * icalcompiter_next(icalcompiter *i)
icalcomponent * icalcomponent_get_next_component(icalcomponent *c, icalcomponent_kind kind)
icalcomponent * icalcomponent_get_first_component(icalcomponent *c, icalcomponent_kind kind)
icalcomponent * icalcomponent_get_current_component(icalcomponent *component)
void icalcomponent_remove_property(icalcomponent *component, icalproperty *property)
void icalcomponent_remove_component(icalcomponent *parent, icalcomponent *child)
icalcomponent * icalcompiter_deref(icalcompiter *i)
icalcomponent * icalcomponent_new(icalcomponent_kind kind)
icalcomponent * icalcomponent_get_first_real_component(const icalcomponent *c)
icalcomponent * icalcomponent_clone(const icalcomponent *old)
void icalcomponent_add_property(icalcomponent *component, icalproperty *property)
icalcompiter icalcomponent_begin_component(icalcomponent *component, icalcomponent_kind kind)
char * icalcomponent_as_ical_string_r(const icalcomponent *component)
icalcomponent_kind icalcomponent_isa(const icalcomponent *component)
void icalcomponent_free(icalcomponent *c)
void icalcomponent_add_component(icalcomponent *parent, icalcomponent *child)
int icalcomponent_count_components(icalcomponent *component, icalcomponent_kind kind)
const char * icalproperty_get_uid(const icalproperty *prop)
int icalproperty_get_sequence(const icalproperty *prop)
struct icalrecurrencetype * icalproperty_get_rrule(const icalproperty *prop)
struct icaltimetype icalproperty_get_dtstart(const icalproperty *prop)
@ ICAL_UID_PROPERTY
@ ICAL_RRULE_PROPERTY
@ ICAL_SEQUENCE_PROPERTY
@ ICAL_RECURRENCEID_PROPERTY
@ ICAL_DUE_PROPERTY
@ ICAL_DTSTART_PROPERTY
struct icaltimetype icalproperty_get_due(const icalproperty *prop)
icalproperty * icalproperty_new_recurrenceid(struct icaltimetype v)
struct icalvalue_impl icalvalue
enum icalrequeststatus kind
Definition icalenums.c:26
const char * str
Definition icalenums.c:29
icalcomponent_kind
Definition icalenums.h:29
@ ICAL_XROOT_COMPONENT
Definition icalenums.h:32
@ ICAL_VTODO_COMPONENT
Definition icalenums.h:35
@ ICAL_VEVENT_COMPONENT
Definition icalenums.h:34
@ ICAL_ANY_COMPONENT
Definition icalenums.h:31
void icalerror_set_errors_are_fatal(bool fatal)
Change if errors are fatal.
Definition icalerror.c:31
bool icalerror_get_errors_are_fatal(void)
Determine if errors are fatal.
Definition icalerror.c:36
void icalerror_set_errno(icalerrorenum x)
Sets the icalerrno to a given error.
Definition icalerror.c:90
void icalerror_clear_errno(void)
Resets icalerrno to ICAL_NO_ERROR.
Definition icalerror.c:85
icalerrorenum
Represents the different types of errors that can be triggered in libical.
Definition icalerror.h:42
@ ICAL_BADARG_ERROR
Definition icalerror.h:47
@ ICAL_FILE_ERROR
Definition icalerror.h:68
@ ICAL_ALLOCATION_ERROR
Definition icalerror.h:53
@ ICAL_INTERNAL_ERROR
Definition icalerror.h:65
@ ICAL_NO_ERROR
Definition icalerror.h:44
@ ICAL_PARSE_ERROR
Definition icalerror.h:62
#define icalerrno
Access the current icalerrno value.
Definition icalerror.h:133
icalset * icalfileset_new(const char *path)
Definition icalfileset.c:51
icalcluster * icalfileset_produce_icalcluster(const char *path)
int icalfileset_has_uid(icalset *set, const char *uid)
icalcomponent * icalfileset_get_current_component(icalset *set)
void icalfileset_mark(icalset *set)
const char * icalfileset_path(icalset *set)
icalerrorenum icalfileset_select(icalset *set, icalgauge *gauge)
icalerrorenum icalfileset_modify(icalset *set, icalcomponent *old, icalcomponent *new)
Modifies components according to the MODIFY method of CAP.
void icalfileset_clear(icalset *set)
Clears the gauge.
icalcomponent * icalfileset_get_component(icalset *set)
icalset * icalfileset_new_reader(const char *path)
Definition icalfileset.c:56
icalfileset_options icalfileset_options_default
Definition icalfileset.c:42
icalcomponent * icalfileset_get_next_component(icalset *set)
icalerrorenum icalfileset_remove_component(icalset *set, icalcomponent *child)
int icalfileset_count_components(icalset *set, icalcomponent_kind kind)
icalcomponent * icalfileset_form_a_matched_recurrence_component(icalsetiter *itr)
icalcomponent * icalfilesetiter_to_next(icalset *set, icalsetiter *i)
icalerrorenum icalfileset_add_component(icalset *set, icalcomponent *child)
icalcomponent * icalfileset_fetch(icalset *set, icalcomponent_kind kind, const char *uid)
Gets and searches for a component by uid.
icalset * icalfileset_init(icalset *set, const char *path, void *options_in)
Definition icalfileset.c:74
icalcomponent * icalfileset_fetch_match(icalset *set, const icalcomponent *comp)
icalerrorenum icalfileset_commit(icalset *set)
void icalfileset_free(icalset *set)
icalsetiter icalfileset_begin_component(icalset *set, icalcomponent_kind kind, icalgauge *gauge, const char *tzid)
icalcomponent * icalfileset_get_first_component(icalset *set)
icalset * icalfileset_new_writer(const char *path)
Definition icalfileset.c:65
Manages a database of ical components and offers interfaces for reading, writing and searching for co...
struct icalfileset_impl icalfileset
Definition icalfileset.h:25
bool icalgauge_compare(icalgauge *gauge, icalcomponent *comp)
Definition icalgauge.c:216
void icalgauge_free(icalgauge *gauge)
Definition icalgauge.c:72
int icalgauge_get_expand(const icalgauge *gauge)
Definition icalgauge.c:66
void icalmemory_free_buffer(void *buf)
Releases a buffer.
Definition icalmemory.c:355
Common memory management routines.
icalcomponent * icalparser_parse(icalparser *parser, icalparser_line_gen_func line_gen_func)
Message oriented parsing.
Definition icalparser.c:588
void icalparser_free(icalparser *parser)
Frees an icalparser object.
Definition icalparser.c:112
icalparser * icalparser_new(void)
Creates a new icalparser.
Definition icalparser.c:89
void icalparser_set_gen_data(icalparser *parser, void *data)
Sets the data that icalparser_parse will give to the line_gen_func as the parameter 'd'.
Definition icalparser.c:129
Line-oriented parsing.
icalvalue * icalproperty_get_value(const icalproperty *prop)
void icalrecur_iterator_free(icalrecur_iterator *impl)
Definition icalrecur.c:2469
icalrecur_iterator * icalrecur_iterator_new(struct icalrecurrencetype *rule, struct icaltimetype dtstart)
Definition icalrecur.c:2341
struct icaltimetype icalrecur_iterator_next(icalrecur_iterator *impl)
Definition icalrecur.c:3714
icalsetiter icalsetiter_null
Definition icalset.c:413
icalset * icalset_new(icalset_kind kind, const char *dsn, void *options)
Definition icalset.c:193
@ ICAL_FILE_SET
Definition icalset.h:39
struct icaltimetype icaltime_from_timet_with_zone(const icaltime_t tm, const bool is_date, const icaltimezone *zone)
Constructor.
Definition icaltime.c:214
bool icaltime_is_null_time(const struct icaltimetype t)
Definition icaltime.c:644
char * icalvalue_as_ical_string_r(const icalvalue *value)
Definition icalvalue.c:1244
Defines the data structure representing iCalendar parameter values.
Options for opening an icalfileset.
icalcluster * cluster
icalcompiter iter
Definition icalset.h:46
icalrecur_iterator * ritr
Definition icalset.h:48
icalgauge * gauge
Definition icalset.h:47
icalcomponent * last_component
Definition icalset.h:49