commit 8b53d98157d6610eb55d31c2e1304625c1c49616
parent 3f582f78e7fcd5169b6243d5951581a0d9f2015a
Author: Andreas Gruhler <agruhl@gmx.ch>
Date: Wed, 26 May 2021 22:14:28 +0200
unfold ical TEXT
Diffstat:
M | caldav.c | | | 21 | +++++++++++++++------ |
M | utils.c | | | 72 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
M | utils.h | | | 3 | ++- |
3 files changed, 76 insertions(+), 20 deletions(-)
diff --git a/caldav.c b/caldav.c
@@ -598,7 +598,7 @@ void caldav_sync(struct tm* date, WINDOW* header, WINDOW* cal, int pad_pos) {
time_t remote_date;
// check remote LAST-MODIFIED:20210521T212441Z of remote event
- char* remote_last_mod = extract_ical_field(event, "LAST-MODIFIED");
+ char* remote_last_mod = extract_ical_field(event, "LAST-MODIFIED", false);
fprintf(stderr, "Remote last modified: %s\n", remote_last_mod);
if (remote_last_mod == NULL) {
remote_file_exists = false;
@@ -629,14 +629,14 @@ void caldav_sync(struct tm* date, WINDOW* header, WINDOW* cal, int pad_pos) {
//put_event(date);
}
- char* remote_desc;
+ char* rmt_desc;
if (timediff < 0 && remote_file_exists) {
//todo: Warn - really sync? remote is more recent and will overwrite
//fprintf(stderr, "Remote file is newer, extracting description from remote...\n");
- remote_desc = extract_ical_field(event, "DESCRIPTION");
- fprintf(stderr, "Remote event description:%s\n", remote_desc);
- if (remote_desc == NULL) {
+ rmt_desc = extract_ical_field(event, "DESCRIPTION", true);
+ fprintf(stderr, "Remote event description:%s\n", rmt_desc);
+ if (rmt_desc == NULL) {
fprintf(stderr, "Failed to fetch description of remote event.\n");
return;
}
@@ -646,7 +646,16 @@ void caldav_sync(struct tm* date, WINDOW* header, WINDOW* cal, int pad_pos) {
if (cursordate_file == NULL) {
perror("Failed to open cursor date file");
} else {
- fprintf(cursordate_file, remote_desc);
+ for (char* i = rmt_desc; *i != '\0'; i++) {
+ if (rmt_desc[i-rmt_desc] == 0x5C) { // backslash
+ if (*(i+1) == 'n') {
+ fputc('\n', cursordate_file);
+ i++;
+ }
+ } else {
+ fputc(*i, cursordate_file);
+ }
+ }
}
fclose(cursordate_file);
diff --git a/utils.c b/utils.c
@@ -24,24 +24,70 @@ char* extract_json_value(char* json, char* key, bool quoted) {
return tok;
}
-char* extract_ical_field(char* ical, char* key) {
+char* unfold(const char* str) {
+ // work on a copy of the str
+ char* res = (char *) malloc(strlen(str) * sizeof(char));
+ strcpy(res, str);
+
+ res = strtok(res, "\n");
+
+ char* buf = malloc(strlen(res));
+ strcpy(buf, res);
+
+ regex_t re;
+ regmatch_t pm[1];
+
+ if (regcomp(&re, "^[^ \t]", 0) != 0) {
+ perror("Failed to compile regex");
+ return NULL;
+ }
+
+ while (res != NULL) {
+ res = strtok(NULL, "\n");
+
+ if (regexec(&re, res, 1, pm, 0) == 0) {
+ // Stop unfolding if line does not start with white space/tab:
+ // https://datatracker.ietf.org/doc/html/rfc2445#section-4.1
+ break;
+ }
+
+ buf = realloc(buf, strlen(buf) + strlen(res));
+ if (buf != NULL) {
+ strcat(buf, res + 1);
+ } else {
+ perror("realloc failed");
+ return NULL;
+ }
+ }
+
+ regfree(&re);
+ //free(buf);
+ return buf;
+}
+
+char* extract_ical_field(const char* ics, char* key, bool multiline) {
// work on a copy of the ical xml response
- char* field = (char *) malloc(strlen(ical) * sizeof(char));
- strcpy(field, ical);
-
- field = strtok(field, "\n");
- while (field != NULL) {
- if (strstr(field, key) != NULL) {
- fprintf(stderr, "field: %s\n", field);
- field = strstr(field, ":"); // value
- field++; // strip the ":"
+ char* field = (char *) malloc(strlen(ics) * sizeof(char));
+ strcpy(field, ics);
+
+ char* res = strtok(field, "\n");
+
+ while (res != NULL) {
+ if (strstr(res, key) != NULL) {
+ res = strstr(res, ":"); // value
+ res++; // strip the ":"
break;
}
- // key was not in this field, advance field
- field = strtok(NULL, "\n");
+ // key not in this line, advance line
+ res = strtok(NULL, "\n");
+ }
+
+ if (multiline) {
+ res = unfold(ics + (res - field));
}
- return field;
+ free(field);
+ return res;
}
// Return expanded file path
diff --git a/utils.h b/utils.h
@@ -1,6 +1,7 @@
#ifndef DIARY_UTILS_H
#define DIARY_UTILS_H
+#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@@ -21,7 +22,7 @@
#define MAX_MONTH_HEIGHT 6
char* extract_json_value(char* json, char* key, bool quoted);
-char* extract_ical_field(char* ical, char* key);
+char* extract_ical_field(const char* ical, char* key, bool multline);
char* expand_path(char* str);
char* strrstr(char *haystack, char *needle);
void fpath(const char* dir, size_t dir_size, const struct tm* date, char** rpath, size_t rpath_size);