/* * * Conky, a system monitor, based on torsmo * * Please see COPYING for details * * Copyright (c) 2005-2024 Brenden Matthews, Philip Kovacs, et. al. * (see AUTHORS) * All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include "conky.h" #include "logging.h" struct ical_event { icaltimetype start; icalcomponent *event; ical_event *next, *prev; }; struct obj_ical { struct ical_event *list; icalcomponent *comps; icalparser *parser; unsigned int num; }; char *read_stream(char *s, size_t size, void *d) { return fgets(s, size, (FILE *)d); } struct ical_event *add_event(struct ical_event *listend, icalcomponent *new_ev) { struct ical_event *ev_new, *ev_cur; icaltimetype start; start = icalcomponent_get_dtstart(new_ev); if (icaltime_compare( start, icaltime_from_timet_with_zone(time(nullptr), 0, NULL)) <= 0) { icalproperty *rrule = icalcomponent_get_first_property(new_ev, ICAL_RRULE_PROPERTY); if (rrule) { icalrecur_iterator *ritr = icalrecur_iterator_new(icalproperty_get_rrule(rrule), start); icaltimetype nexttime = icalrecur_iterator_next(ritr); while (!icaltime_is_null_time(nexttime)) { if (icaltime_compare(nexttime, icaltime_from_timet_with_zone( time(nullptr), 0, NULL)) > 0) { start = nexttime; break; } nexttime = icalrecur_iterator_next(ritr); } icalrecur_iterator_free(ritr); } else return nullptr; } ev_new = (struct ical_event *)malloc(sizeof(struct ical_event)); memset(ev_new, 0, sizeof(struct ical_event)); ev_new->event = new_ev; ev_new->start = start; if (listend) { // list already contains events ev_cur = listend; while (icaltime_compare(ev_new->start, ev_cur->start) <= 0) { if (!ev_cur->prev) { // ev_new starts first ev_new->next = ev_cur; ev_cur->prev = ev_new; return listend; } ev_cur = ev_cur->prev; } if (ev_cur == listend) { // ev_new starts last ev_cur->next = ev_new; ev_new->prev = ev_cur; return ev_new; } // ev_new somewhere in the middle ev_new->prev = ev_cur; ev_new->next = ev_cur->next; ev_cur->next->prev = ev_new; ev_cur->next = ev_new; return listend; } return ev_new; } void parse_ical_args(struct text_object *obj, const char *arg, void *free_at_crash, void *free_at_crash2) { char *filename = strdup(arg); FILE *file; icalparser *parser; icalcomponent *allc, *curc; struct ical_event *ll_start, *ll_end, *ll_new; struct obj_ical *opaque; unsigned int num; if (sscanf(arg, "%d %s", &num, filename) != 2) { free(filename); free(obj); CRIT_ERR_FREE(free_at_crash, free_at_crash2, "wrong number of arguments for $ical"); } file = fopen(filename, "r"); if (!file) { free(obj); free(free_at_crash); CRIT_ERR_FREE(filename, free_at_crash2, "Can't read file %s", filename); return; } free(filename); parser = icalparser_new(); icalparser_set_gen_data(parser, file); allc = icalparser_parse(parser, read_stream); fclose(file); curc = icalcomponent_get_first_component(allc, ICAL_VEVENT_COMPONENT); if (!curc) { icalparser_free(parser); icalcomponent_free(allc); NORM_ERR("No ical events available"); return; } ll_start = add_event(nullptr, curc); ll_end = ll_start; while (1) { curc = icalcomponent_get_next_component(allc, ICAL_VEVENT_COMPONENT); if (!curc) break; ll_new = add_event(ll_end, curc); if (!ll_start) { // first component was not added ll_start = ll_new; ll_end = ll_new; } else if (ll_start->prev) { ll_start = ll_start->prev; } else if (ll_end->next) { ll_end = ll_end->next; } } opaque = (struct obj_ical *)malloc(sizeof(struct obj_ical)); opaque->list = ll_start; opaque->parser = parser; opaque->comps = allc; opaque->num = num; obj->data.opaque = opaque; free(opaque); } void print_ical(struct text_object *obj, char *p, unsigned int p_max_size) { struct obj_ical *ical_obj = (struct obj_ical *)obj->data.opaque; struct ical_event *ll_current; if (!ical_obj) return; ll_current = ical_obj->list; unsigned int i = 1; while (1) { if (!ll_current) return; if (i > ical_obj->num) return; if (i == ical_obj->num) break; if (i < ical_obj->num) { ll_current = ll_current->next; i++; } } snprintf(p, p_max_size, "%s", icalproperty_get_summary(icalcomponent_get_first_property( ll_current->event, ICAL_SUMMARY_PROPERTY))); } void free_ical(struct text_object *obj) { struct obj_ical *ical_free_me = (struct obj_ical *)obj->data.opaque; if (!ical_free_me) return; icalcomponent_free(ical_free_me->comps); icalparser_free(ical_free_me->parser); while (ical_free_me->list) { if (ical_free_me->list->next) { ical_free_me->list = ical_free_me->list->next; free_and_zero(ical_free_me->list->prev); } else free_and_zero(ical_free_me->list); } free(obj->data.opaque); }