summaryrefslogtreecommitdiff
path: root/pith
diff options
context:
space:
mode:
authorEduardo Chappa <chappa@washington.edu>2017-12-22 22:31:48 -0700
committerEduardo Chappa <chappa@washington.edu>2017-12-22 22:31:48 -0700
commit29798bd68fc0b892fce0fe49ec8859485e3b531b (patch)
tree5f2d8f28fbaf5bc76a3fc01f9d589aad729ed0ee /pith
parent1c6f750f40551447f0ea214c993845238fd729cd (diff)
downloadalpine-29798bd68fc0b892fce0fe49ec8859485e3b531b.tar.xz
* Fix parsing of date for DTSTART and DTEND. The parser only recognized
DATE-TIME format, now it recognizes DATE format. Reported by Holger Trapp. * Add escape parser to event location (switch "\," to "," etc.) * Start work to support reply of invitations, but then I realize that I need to start work in sending event invitations before I do that, so I will.
Diffstat (limited to 'pith')
-rw-r--r--pith/Makefile35
-rw-r--r--pith/ical.c136
-rw-r--r--pith/ical.h1
-rw-r--r--pith/mailview.c16
-rw-r--r--pith/pine.hlp2
5 files changed, 152 insertions, 38 deletions
diff --git a/pith/Makefile b/pith/Makefile
index 166f5117..d9f3594a 100644
--- a/pith/Makefile
+++ b/pith/Makefile
@@ -121,21 +121,22 @@ libpith_a_AR = $(AR) $(ARFLAGS)
libpith_a_LIBADD =
am_libpith_a_OBJECTS = ablookup.$(OBJEXT) abdlc.$(OBJEXT) \
addrbook.$(OBJEXT) addrstring.$(OBJEXT) adrbklib.$(OBJEXT) \
- bldaddr.$(OBJEXT) charset.$(OBJEXT) color.$(OBJEXT) \
- conf.$(OBJEXT) context.$(OBJEXT) copyaddr.$(OBJEXT) \
- detoken.$(OBJEXT) detach.$(OBJEXT) editorial.$(OBJEXT) \
- escapes.$(OBJEXT) filter.$(OBJEXT) flag.$(OBJEXT) \
- folder.$(OBJEXT) handle.$(OBJEXT) help.$(OBJEXT) \
- helpindx.$(OBJEXT) hist.$(OBJEXT) icache.$(OBJEXT) \
- imap.$(OBJEXT) init.$(OBJEXT) keyword.$(OBJEXT) ldap.$(OBJEXT) \
- list.$(OBJEXT) mailcap.$(OBJEXT) mailcmd.$(OBJEXT) \
- mailindx.$(OBJEXT) maillist.$(OBJEXT) mailview.$(OBJEXT) \
- margin.$(OBJEXT) mimedesc.$(OBJEXT) mimetype.$(OBJEXT) \
- msgno.$(OBJEXT) newmail.$(OBJEXT) news.$(OBJEXT) \
- pattern.$(OBJEXT) pipe.$(OBJEXT) readfile.$(OBJEXT) \
- remote.$(OBJEXT) reply.$(OBJEXT) rfc2231.$(OBJEXT) \
- save.$(OBJEXT) search.$(OBJEXT) sequence.$(OBJEXT) \
- send.$(OBJEXT) sort.$(OBJEXT) state.$(OBJEXT) status.$(OBJEXT) \
+ bldaddr.$(OBJEXT) body.$(OBJEXT) charset.$(OBJEXT) \
+ color.$(OBJEXT) conf.$(OBJEXT) context.$(OBJEXT) \
+ copyaddr.$(OBJEXT) detoken.$(OBJEXT) detach.$(OBJEXT) \
+ editorial.$(OBJEXT) escapes.$(OBJEXT) filter.$(OBJEXT) \
+ flag.$(OBJEXT) folder.$(OBJEXT) handle.$(OBJEXT) \
+ help.$(OBJEXT) helpindx.$(OBJEXT) hist.$(OBJEXT) \
+ icache.$(OBJEXT) ical.$(OBJEXT) imap.$(OBJEXT) init.$(OBJEXT) \
+ keyword.$(OBJEXT) ldap.$(OBJEXT) list.$(OBJEXT) \
+ mailcap.$(OBJEXT) mailcmd.$(OBJEXT) mailindx.$(OBJEXT) \
+ maillist.$(OBJEXT) mailview.$(OBJEXT) margin.$(OBJEXT) \
+ mimedesc.$(OBJEXT) mimetype.$(OBJEXT) msgno.$(OBJEXT) \
+ newmail.$(OBJEXT) news.$(OBJEXT) pattern.$(OBJEXT) \
+ pipe.$(OBJEXT) readfile.$(OBJEXT) remote.$(OBJEXT) \
+ reply.$(OBJEXT) rfc2231.$(OBJEXT) save.$(OBJEXT) \
+ search.$(OBJEXT) sequence.$(OBJEXT) send.$(OBJEXT) \
+ sort.$(OBJEXT) state.$(OBJEXT) status.$(OBJEXT) \
store.$(OBJEXT) stream.$(OBJEXT) string.$(OBJEXT) \
strlst.$(OBJEXT) takeaddr.$(OBJEXT) tempfile.$(OBJEXT) \
text.$(OBJEXT) thread.$(OBJEXT) adjtime.$(OBJEXT) \
@@ -431,9 +432,9 @@ top_srcdir = ..
SUBDIRS = osdep charconv
noinst_LIBRARIES = libpith.a
BUILT_SOURCES = helptext.h helptext.c
-libpith_a_SOURCES = ablookup.c abdlc.c addrbook.c addrstring.c adrbklib.c bldaddr.c charset.c \
+libpith_a_SOURCES = ablookup.c abdlc.c addrbook.c addrstring.c adrbklib.c bldaddr.c body.c charset.c \
color.c conf.c context.c copyaddr.c detoken.c detach.c editorial.c escapes.c \
- filter.c flag.c folder.c handle.c help.c helpindx.c hist.c icache.c imap.c init.c \
+ filter.c flag.c folder.c handle.c help.c helpindx.c hist.c icache.c ical.c imap.c init.c \
keyword.c ldap.c list.c mailcap.c mailcmd.c mailindx.c maillist.c mailview.c \
margin.c mimedesc.c mimetype.c msgno.c newmail.c news.c pattern.c pipe.c \
readfile.c remote.c reply.c rfc2231.c save.c search.c sequence.c send.c sort.c \
diff --git a/pith/ical.c b/pith/ical.c
index 8364d384..b3fe67e2 100644
--- a/pith/ical.c
+++ b/pith/ical.c
@@ -231,6 +231,57 @@ ICAL_PROP_S alarm_prop[] = {
/* Finally, here begins the code. */
+/* Return code:
+ 0 - if no errors
+ -1 - if an error occured
+ Args: a pointer to the text. If there is an error, the text is not modified.
+ */
+int
+ical_remove_escapes(char **textp)
+{
+ char *text, *s, *t;
+ int rv = 0;
+ int escaped;
+
+ if(textp == NULL) return 0;
+
+ t = cpystr(*textp); /* work on a copy of the text */
+ /* the variable text below points to the beginning of the filtered text */
+ for (text = s = t, escaped = 0; rv == 0 && *s != '\0'; s++){
+ if(*s == '\\' && escaped == 0){
+ escaped = 1;
+ continue;
+ }
+ if(escaped){
+ switch(*s){
+ case '\\':
+ case ',':
+ case ';':
+ *t++ = *s;
+ break;
+
+ case 'n':
+ case 'N':
+ *t++ = '\n';
+ break;
+ default: rv = -1;
+ break;
+ }
+ escaped = 0;
+ }
+ else *t++ = *s;
+ }
+ *t = '\0'; /* tie off filtered text */
+ t = text; /* reset t to the beginning */
+ if(rv == -1)
+ fs_give((void **) &t);
+ else{
+ strncpy(*textp, t, strlen(t)); /* overwrite given text with filtered text */
+ (*textp)[strlen(t)] = '\0';
+ }
+ return rv;
+}
+
void ical_debug(char *fcn, char *text)
{
char piece[50];
@@ -1602,31 +1653,43 @@ ical_parse_duration(char *value, ICAL_DURATION_S *ic_d)
return rv;
}
-/* return -1 if any error, 0 if no error */
+/* return -1 if any error,
+ 0 if value has the DATE-TIME form
+ 1 if value has the DATE form only
+ */
int
ical_parse_date(char *value, struct tm *t)
{
- int i;
+ int i, rv;
struct tm Tm;
- if(t == NULL) return -1;
+ rv = -1;
+ if(t == NULL) return rv;
memset((void *)&Tm, 0, sizeof(struct tm));
- if(value == NULL) return -1;
+ if(value == NULL) return rv;
+ rv = 0; /* assume DATE-TIME format */
/* a simple check for the format of the string */
for(i = 0; isdigit(value[i]); i++);
- if (i != 8 || value[i++] != 'T') return -1;
- for(; isdigit(value[i]); i++);
- if(i != 15 || (value[i] != '\0' && (value[i] != 'Z' || value[i+1] != '\0')))
- return -1;
+ if (i == 8 && value[i] == '\0')
+ rv = 1;
+ else
+ if (i != 8 || value[i++] != 'T') return -1;
+ if(rv == 0) {
+ for(; isdigit(value[i]); i++);
+ if(i != 15 || (value[i] != '\0' && (value[i] != 'Z' || value[i+1] != '\0')))
+ return -1;
+ }
Tm.tm_year = ical_get_number_value(value, 0, 4) - 1900;
Tm.tm_mon = ical_get_number_value(value, 4, 6) - 1;
Tm.tm_mday = ical_get_number_value(value, 6, 8);
- Tm.tm_hour = ical_get_number_value(value, 9, 11);
- Tm.tm_min = ical_get_number_value(value, 11, 13);
- Tm.tm_sec = ical_get_number_value(value, 13, 15);
+ if(rv == 0){
+ Tm.tm_hour = ical_get_number_value(value, 9, 11);
+ Tm.tm_min = ical_get_number_value(value, 11, 13);
+ Tm.tm_sec = ical_get_number_value(value, 13, 15);
+ }
*t = Tm;
return (t->tm_mon > 11 || t->tm_mon < 0
@@ -1634,7 +1697,7 @@ ical_parse_date(char *value, struct tm *t)
|| t->tm_hour > 23 || t->tm_hour < 0
|| t->tm_min > 59 || t->tm_min < 0
|| t->tm_sec > 60 || t->tm_sec < 0)
- ? - 1 : 0;
+ ? - 1 : rv;
}
void
@@ -1962,10 +2025,27 @@ ical_vevent_summary(VCALENDAR_S *vcal)
if((icl = (ICLINE_S *) vevent->prop[EvDtstart]) != NULL){
struct tm ic_date;
char tmp[200];
+ int icd; /* ical date return value */
+
memset((void *)&ic_date, 0, sizeof(struct tm));
- ical_parse_date(icl->value, &ic_date);
- ic_date.tm_wday = ical_day_of_week(ic_date);
- our_strftime(tmp, sizeof(tmp), "%a %x %I:%M %p", &ic_date);
+ icd = ical_parse_date(icl->value, &ic_date);
+ if(icd >= 0){
+ ic_date.tm_wday = ical_day_of_week(ic_date);
+ switch(icd){
+ case 0: /* DATE-TIME */
+ our_strftime(tmp, sizeof(tmp), "%a %x %I:%M %p", &ic_date);
+ break;
+ case 1: /* DATE */
+ our_strftime(tmp, sizeof(tmp), "%a %x", &ic_date);
+ break;
+ default: alpine_panic("Unhandled ical date format");
+ break;
+ }
+ }
+ else{
+ strncpy(tmp, _("Error while parsing event date"), sizeof(tmp));
+ tmp[sizeof(tmp) - 1] = '\0';
+ }
rv->evstart = cpystr(icl->value ? tmp : _("Unknown Start Date"));
} /* end of if dtstart */
@@ -2012,11 +2092,27 @@ ical_vevent_summary(VCALENDAR_S *vcal)
else if((icl = (ICLINE_S *) vevent->prop[EvDtend]) != NULL){
struct tm ic_date;
char tmp[200];
+ int icd;
memset((void *)&ic_date, 0, sizeof(struct tm));
- ical_parse_date(icl->value, &ic_date);
- ic_date.tm_wday = ical_day_of_week(ic_date);
- our_strftime(tmp, sizeof(tmp), "%a %x %I:%M %p", &ic_date);
+ icd = ical_parse_date(icl->value, &ic_date);
+ if(icd >= 0){
+ ic_date.tm_wday = ical_day_of_week(ic_date);
+ switch(icd){
+ case 0: /* DATE-TIME */
+ our_strftime(tmp, sizeof(tmp), "%a %x %I:%M %p", &ic_date);
+ break;
+ case 1: /* DATE */
+ our_strftime(tmp, sizeof(tmp), "%a %x", &ic_date);
+ break;
+ default: alpine_panic("Unhandled ical date format");
+ break;
+ }
+ }
+ else{
+ strncpy(tmp, _("Error while parsing event date"), sizeof(tmp));
+ tmp[sizeof(tmp) - 1] = '\0';
+ }
rv->evend = cpystr(icl->value ? tmp : _("Unknown End Date"));
} /* end of if dtend */
@@ -2095,7 +2191,7 @@ ical_vevent_summary(VCALENDAR_S *vcal)
v = cpystr(icl->value); /* process a copy of icl->value */
for(i = 1, escaped = 0, s = v; s && *s; s++){
- if(*s == '\\'){ escaped = 1; continue; }
+ if(*s == '\\' && escaped == 0){ escaped = 1; continue; }
if(escaped){
if(!(*s == '\\' || *s == ',' || *s == 'n' || *s == 'N' || *s == ';')){
free_vevent_summary(&rv);
@@ -2111,7 +2207,7 @@ ical_vevent_summary(VCALENDAR_S *vcal)
rv->description = fs_get((i+1)*sizeof(char *));
i = 0;
for (s = t = u = v, escaped = 0; *t != '\0'; t++){
- if(*t == '\\'){ escaped = 1; continue; }
+ if(*t == '\\' && escaped == 0){ escaped = 1; continue; }
if(escaped){
switch(*t){
case '\\':
diff --git a/pith/ical.h b/pith/ical.h
index 04d0cc08..7ff5865a 100644
--- a/pith/ical.h
+++ b/pith/ical.h
@@ -9,6 +9,7 @@ int ical_first_of_month(int, int); /* args: month, year - in that order */
int ical_day_of_week(struct tm); /* args: a time structure */
int ical_parse_date(char *, struct tm *);
int ical_parse_duration(char *, ICAL_DURATION_S *);
+int ical_remove_escapes(char **);
VEVENT_SUMMARY_S *ical_vevent_summary(VCALENDAR_S *);
void free_vevent_summary(VEVENT_SUMMARY_S **);
diff --git a/pith/mailview.c b/pith/mailview.c
index 1d71e7a0..dcdd183d 100644
--- a/pith/mailview.c
+++ b/pith/mailview.c
@@ -312,6 +312,7 @@ format_calendar_vevent(VCALENDAR_S *vcal, ATTACH_S *a, HANDLE_S **handlesp, int
} /* end of if(organizer) */
if(vesy->location){
+ ical_remove_escapes(&vesy->location);
utf8_snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s%s%s",
padding, _("Location: "), vesy->location);
gf_puts(tmp_20k_buf, pc);
@@ -483,10 +484,25 @@ format_calendar(long int msgno, BODY *body, HANDLE_S **handlesp, int flgs, int w
for(a = ps_global->atmts; a->description != NULL; a++){
if(MIME_VCALENDAR(a->body->type, a->body->subtype)){
b = mail_body (ps_global->mail_stream, msgno, a->number);
+ if(b == NULL){
+ gf_puts(_("Error fetching calendar body part"), pc);
+ gf_puts(NEWLINE, pc);
+ continue;
+ }
if(b->sparep == NULL){
b64text = mail_fetch_body(ps_global->mail_stream, msgno, a->number, &callen, 0);
+ if(b64text == NULL){
+ gf_puts(_("Error fetching calendar text"), pc);
+ gf_puts(NEWLINE, pc);
+ continue;
+ }
b64text[callen] = '\0'; /* chop off cookie */
caltext = rfc822_base64(b64text, strlen(b64text), &callen);
+ if(caltext == NULL){
+ gf_puts(_("Error in calendar base64 encoding"), pc);
+ gf_puts(NEWLINE, pc);
+ continue;
+ }
vcal = ical_parse_text(caltext);
b->sparep = create_body_sparep(iCalType, (void *) vcal);
}
diff --git a/pith/pine.hlp b/pith/pine.hlp
index 0fa01415..ef58c44d 100644
--- a/pith/pine.hlp
+++ b/pith/pine.hlp
@@ -140,7 +140,7 @@ with help text for the config screen and the composer that didn't have any
reasonable place to be called from.
Dummy change to get revision in pine.hlp
============= h_revision =================
-Alpine Commit 240 2017-12-09 16:20:34
+Alpine Commit 243 2017-12-22 22:31:03
============= h_news =================
<HTML>
<HEAD>