X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/33ee48487aba4989607d930e341032005de02004..63621a81d16ab743de6b57d47578a9a2c670ad22:/uip/mhical.c diff --git a/uip/mhical.c b/uip/mhical.c index 8ab305aa..d62fce95 100644 --- a/uip/mhical.c +++ b/uip/mhical.c @@ -1,5 +1,4 @@ -/* - * mhical.c -- operate on an iCalendar request +/* mhical.c -- operate on an iCalendar request * * This code is Copyright (c) 2014, by the authors of nmh. * See the COPYRIGHT file in the root directory of the nmh @@ -30,7 +29,7 @@ static void convert_common (contentline *, act); static void dump_unfolded (FILE *, contentline *); static void output (FILE *, contentline *, int); static void display (FILE *, contentline *, char *); -static const char *identity (const contentline *); +static const char *identity (const contentline *) PURE; static char *format_params (char *, param_list *); static char *fold (char *, int); @@ -57,6 +56,7 @@ DEFINE_SWITCH_ARRAY(MHICAL, switches); #undef X vevent vevents = { NULL, NULL, NULL}; +int parser_status = 0; int main (int argc, char *argv[]) { @@ -76,7 +76,7 @@ main (int argc, char *argv[]) { icaldebug = 0; /* Global provided by bison (with name-prefix "ical"). */ - if (nmh_init(argv[0], 1)) { return 1; } + if (nmh_init(argv[0], 2)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; @@ -140,12 +140,12 @@ main (int argc, char *argv[]) { case INFILESW: if (! (cp = *argp++) || (*cp == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); - infile = *cp == '-' ? add (cp, NULL) : path (cp, TFILE); + infile = *cp == '-' ? mh_xstrdup(cp) : path (cp, TFILE); continue; case OUTFILESW: if (! (cp = *argp++) || (*cp == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); - outfile = *cp == '-' ? add (cp, NULL) : path (cp, TFILE); + outfile = *cp == '-' ? mh_xstrdup(cp) : path (cp, TFILE); continue; case CONTENTTYPESW: @@ -237,7 +237,7 @@ main (int argc, char *argv[]) { free (outfile); } - return 0; + return parser_status; } /* @@ -332,10 +332,10 @@ convert_to_reply (contentline *clines, act action) { (node = find_contentline (clines, "BEGIN", "VEVENT"))) { contentline *new_node = add_contentline (node, "ATTENDEE"); - add_param_name (new_node, strdup ("PARTSTAT")); - add_param_value (new_node, strdup (partstat)); - add_param_name (new_node, strdup ("CN")); - add_param_value (new_node, strdup (getfullname ())); + add_param_name (new_node, mh_xstrdup ("PARTSTAT")); + add_param_value (new_node, mh_xstrdup (partstat)); + add_param_name (new_node, mh_xstrdup ("CN")); + add_param_value (new_node, mh_xstrdup (getfullname ())); new_node->value = concat ("MAILTO:", getlocalmbox (), NULL); } } @@ -369,7 +369,7 @@ convert_to_cancellation (contentline *clines) { if ((node = find_contentline (clines, "STATUS", 0)) && ! strcasecmp (node->value, "CONFIRMED")) { free (node->value); - node->value = strdup ("CANCELLED"); + node->value = mh_xstrdup ("CANCELLED"); } if ((node = find_contentline (clines, "SEQUENCE", 0))) { @@ -378,7 +378,7 @@ convert_to_cancellation (contentline *clines) { (void) snprintf (buf, sizeof buf, "%d", sequence + 1); free (node->value); - node->value = strdup (buf); + node->value = mh_xstrdup (buf); } } @@ -389,24 +389,25 @@ convert_common (contentline *clines, act action) { if ((node = find_contentline (clines, "METHOD", 0))) { free (node->value); - node->value = strdup (action == ACT_CANCEL ? "CANCEL" : "REPLY"); + node->value = mh_xstrdup (action == ACT_CANCEL ? "CANCEL" : "REPLY"); } if ((node = find_contentline (clines, "PRODID", 0))) { free (node->value); - node->value = strdup ("nmh mhical v0.1"); + node->value = mh_xstrdup ("nmh mhical v0.1"); } if ((node = find_contentline (clines, "VERSION", 0))) { if (! node->value) { - admonish (NULL, "Version property is missing value, assume 2.0"); - node->value = strdup ("2.0"); + inform("Version property is missing value, assume 2.0, continuing..."); + node->value = mh_xstrdup ("2.0"); } if (strcmp (node->value, "2.0")) { - admonish (NULL, "supports the Version 2.0 specified by RFC 5545 " - "but iCalendar object has Version %s", node->value); - node->value = strdup ("2.0"); + inform("supports the Version 2.0 specified by RFC 5545 " + "but iCalendar object has Version %s, continuing...", + node->value); + node->value = mh_xstrdup ("2.0"); } } @@ -458,12 +459,12 @@ convert_common (contentline *clines, act action) { if (strftime (buf, sizeof buf, "%Y%m%dT%H%M%SZ", &now_tm)) { free (node->value); - node->value = strdup (buf); + node->value = mh_xstrdup (buf); } else { - admonish (NULL, "strftime unable to format current time"); + inform("strftime unable to format current time, continuing..."); } } else { - admonish (NULL, "gmtime_r failed on current time"); + inform("gmtime_r failed on current time, continuing..."); } } @@ -523,7 +524,7 @@ output (FILE *file, contentline *clines, int contenttype) { char *line = NULL; size_t len; - line = strdup (node->name); + line = mh_xstrdup (node->name); line = format_params (line, node->params); len = strlen (line); @@ -534,11 +535,10 @@ output (FILE *file, contentline *clines, int contenttype) { line = fold (add (node->value, line), clines->cr_before_lf == CR_BEFORE_LF); - if (clines->cr_before_lf == LF_ONLY) { - fprintf (file, "%s\n", line); - } else { - fprintf (file, "%s\r\n", line); - } + fputs(line, file); + if (clines->cr_before_lf != LF_ONLY) + putc('\r', file); + putc('\n', file); free (line); } } @@ -576,20 +576,20 @@ display (FILE *file, contentline *clines, char *nfs) { if ((c = fmt_findcomp ("method"))) { if ((node = find_contentline (clines, "METHOD", 0)) && node->value) { - c->c_text = strdup (node->value); + c->c_text = mh_xstrdup (node->value); } } if ((c = fmt_findcomp ("organizer"))) { if ((node = find_contentline (clines, "ORGANIZER", 0)) && node->value) { - c->c_text = strdup (identity (node)); + c->c_text = mh_xstrdup (identity (node)); } } if ((c = fmt_findcomp ("summary"))) { if ((node = find_contentline (clines, "SUMMARY", 0)) && node->value) { - c->c_text = strdup (node->value); + c->c_text = mh_xstrdup (node->value); } } @@ -601,7 +601,7 @@ display (FILE *file, contentline *clines, char *nfs) { if (node->name && node->value && ! in_valarm && ! strcasecmp ("DESCRIPTION", node->name) && strcasecmp (node->value, "\\n\\n")) { - c->c_text = strdup (node->value); + c->c_text = mh_xstrdup (node->value); } else if (in_valarm) { if (! strcasecmp ("END", node->name) && ! strcasecmp ("VALARM", node->value)) { @@ -619,7 +619,7 @@ display (FILE *file, contentline *clines, char *nfs) { if ((c = fmt_findcomp ("location"))) { if ((node = find_contentline (clines, "LOCATION", 0)) && node->value) { - c->c_text = strdup (node->value); + c->c_text = mh_xstrdup (node->value); } } @@ -642,7 +642,7 @@ display (FILE *file, contentline *clines, char *nfs) { } else if (! strcasecmp ("DTSTART", node->name)) { /* Got it: DTSTART outside of a VTIMEZONE section. */ char *datetime = format_datetime (timezones, node); - c->c_text = datetime ? datetime : strdup(node->value); + c->c_text = datetime ? datetime : mh_xstrdup(node->value); } } } @@ -652,6 +652,25 @@ display (FILE *file, contentline *clines, char *nfs) { if ((node = find_contentline (clines, "DTEND", 0)) && node->value) { char *datetime = format_datetime (timezones, node); c->c_text = datetime ? datetime : strdup(node->value); + } else if ((node = find_contentline (clines, "DTSTART", 0)) && + node->value) { + /* There is no DTEND. If there's a DTSTART, use it. If it + doesn't have a time, assume that the event is for the + entire day and append 23:59:59 to it so that it signifies + the end of the day. And assume local timezone. */ + if (strchr(node->value, 'T')) { + char * datetime = format_datetime (timezones, node); + c->c_text = datetime ? datetime : strdup(node->value); + } else { + char *datetime; + contentline node_copy; + + node_copy = *node; + node_copy.value = concat(node_copy.value, "T235959", NULL); + datetime = format_datetime (timezones, &node_copy); + c->c_text = datetime ? datetime : strdup(node_copy.value); + free(node_copy.value); + } } } @@ -694,7 +713,7 @@ display (FILE *file, contentline *clines, char *nfs) { } /* Don't call on the END:VCALENDAR line. */ - if (clines->next) { + if (clines && clines->next) { (void) fmt_scan (fmt, buffer, INT_MAX, dat, NULL); fputs (charstring_buffer (buffer), file); fmt_free (fmt, 1); @@ -790,7 +809,7 @@ fold (char *line, int uses_cr) { #endif charstring_push_back_chars (folded_line, cp, char_len, 1); - remaining -= char_len > 0 ? char_len : 1; + remaining -= max(char_len, 1); /* remaining must be > 0 to pass the loop condition above, so if it's not > 1, it is == 1. */ @@ -805,7 +824,7 @@ fold (char *line, int uses_cr) { } } - cp += char_len > 0 ? char_len : 1; + cp += max(char_len, 1); } free (line);