mirror of
https://github.com/Llewellynvdm/conky.git
synced 2024-12-27 20:44:56 +00:00
faba25d197
it's surprising to pass 2 nullptr arguments at most of the callsites of a logging function, so instead let callers explicitly state whether they have auxiliary data to free
196 lines
5.7 KiB
C++
196 lines
5.7 KiB
C++
/*
|
|
*
|
|
* Conky, a system monitor, based on torsmo
|
|
*
|
|
* Please see COPYING for details
|
|
*
|
|
* Copyright (c) 2005-2021 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include <libical/ical.h>
|
|
#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);
|
|
}
|