sfeed

Simple RSS and Atom feed parser
git clone https://git.sinitax.com/codemadness/sfeed
Log | Files | Refs | README | LICENSE | Upstream | sfeed.txt

commit fa045e31451f2c73d61d0d7a41b39a925b70f37e
parent 3d1007693d7a9108a93d33b6e173dbec0ea214ae
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Sat,  3 Jan 2015 12:44:32 +0100

time fixes

Diffstat:
Msfeed.1 | 2+-
Msfeed.c | 30++++++++++++++++++------------
Msfeed_frames.c | 18++++++++++--------
Msfeed_html.c | 9+++------
Msfeed_plain.c | 9+++------
Msfeed_stats.c | 13+++++--------
Mutil.c | 16++++++++++++++++
7 files changed, 56 insertions(+), 41 deletions(-)

diff --git a/sfeed.1 b/sfeed.1 @@ -27,7 +27,7 @@ The order and format of the fields are: .It Ar item timestamp string, UNIX timestamp in GMT+0 .It Ar item timestamp -string, date and time in the format: YYYY-mm-dd HH:MM:SS tzname[+-]HHMM +string, date and time in the format: YYYY-mm-dd HH:MM:SS tzname[[+-][HHMM]] .It Ar item title string .It Ar item link diff --git a/sfeed.c b/sfeed.c @@ -83,7 +83,7 @@ static int gettimetz(const char *, char *, size_t); static int isattr(const char *, size_t, const char *, size_t); static int istag(const char *, size_t, const char *, size_t); static size_t namedentitytostr(const char *, char *, size_t); -static time_t parsetime(const char *, char *, size_t); +static int parsetime(const char *, char *, size_t, time_t *); static void string_append(String *, const char *, size_t); static void string_buffer_init(String *, size_t); static int string_buffer_realloc(String *, size_t); @@ -345,10 +345,10 @@ gettimetz(const char *s, char *buf, size_t bufsiz) return (tzhour * 3600) + (tzmin * 60) * (c == '-' ? -1 : 1); } -static time_t -parsetime(const char *s, char *buf, size_t bufsiz) +static int +parsetime(const char *s, char *buf, size_t bufsiz, time_t *tp) { - time_t t = -1; /* can't parse */ + time_t t; char tz[64] = ""; struct tm tm; const char *formats[] = { @@ -360,23 +360,23 @@ parsetime(const char *s, char *buf, size_t bufsiz) char *p; unsigned int i; - if(buf && bufsiz > 0) - buf[0] = '\0'; memset(&tm, 0, sizeof(tm)); for(i = 0; formats[i]; i++) { if((p = strptime(s, formats[i], &tm))) { tm.tm_isdst = -1; /* don't use DST */ if((t = mktime(&tm)) == -1) /* error */ - return t; + return -1; t -= gettimetz(p, tz, sizeof(tz)); if(buf) - snprintf(buf, bufsiz, "%04d-%02d-%02d %02d:%02d:%02d %-.16s", + snprintf(buf, bufsiz, "%04d-%02d-%02d %02d:%02d:%02d %s", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tz); - break; + if(tp) + *tp = t; + return 0; } } - return t; + return -1; } /* print text, escape tabs, newline and carriage return etc */ @@ -633,6 +633,7 @@ static void xml_handler_end_element(XMLParser *p, const char *name, size_t namelen, int isshort) { char timebuf[64]; + time_t t; int tagid; if(ctx.iscontent) { @@ -670,8 +671,13 @@ xml_handler_end_element(XMLParser *p, const char *name, size_t namelen, int issh (ctx.item.feedtype == FeedTypeRSS && istag(name, namelen, STRP("item")))) /* RSS */ { - printf("%ld", (long)parsetime((&ctx.item.timestamp)->data, - timebuf, sizeof(timebuf))); + /* parse time, timestamp and formatted timestamp field is empty + * if the parsed time is invalid */ + timebuf[0] = '\0'; + if(parsetime((&ctx.item.timestamp)->data, timebuf, + sizeof(timebuf), &t) != -1) + printf("%ld", (long)t); + putchar(FieldSeparator); fputs(timebuf, stdout); putchar(FieldSeparator); diff --git a/sfeed_frames.c b/sfeed_frames.c @@ -37,6 +37,7 @@ cleanup(void) fpcontent = NULL; } +/* same as err() but first call cleanup() function */ static void xerr(int eval, const char *fmt, ...) { @@ -113,6 +114,7 @@ main(int argc, char *argv[]) size_t linesize = 0, namelen, basepathlen; struct stat st; struct utimbuf contenttime; + int r; memset(&contenttime, 0, sizeof(contenttime)); @@ -221,16 +223,16 @@ main(int argc, char *argv[]) } /* write item. */ - errno = 0; - parsedtime = (time_t)strtol(fields[FieldUnixTimestamp], NULL, 10); - if(errno != 0) - parsedtime = 0; + r = strtotime(fields[FieldUnixTimestamp], &parsedtime); + /* set modified and access time of file to time of item. */ - contenttime.actime = parsedtime; - contenttime.modtime = parsedtime; - utime(filepath, &contenttime); + if(r != -1) { + contenttime.actime = parsedtime; + contenttime.modtime = parsedtime; + utime(filepath, &contenttime); + } - isnew = (parsedtime >= comparetime) ? 1 : 0; + isnew = (r != -1 && parsedtime >= comparetime) ? 1 : 0; totalnew += isnew; fcur->totalnew += isnew; fcur->total++; diff --git a/sfeed_html.c b/sfeed_html.c @@ -1,6 +1,5 @@ #include <ctype.h> #include <err.h> -#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -21,6 +20,7 @@ main(void) struct feed *f, *fcur = NULL; time_t parsedtime, comparetime; size_t size = 0; + int r; comparetime = time(NULL) - (3600 * 24); /* 1 day is old news */ fputs( @@ -38,11 +38,8 @@ main(void) feeds = fcur; while(parseline(&line, &size, fields, FieldLast, '\t', stdin) > 0) { - errno = 0; - parsedtime = (time_t)strtol(fields[FieldUnixTimestamp], NULL, 10); - if(errno != 0) - parsedtime = 0; - isnew = (parsedtime >= comparetime) ? 1 : 0; + r = strtotime(fields[FieldUnixTimestamp], &parsedtime); + isnew = (r != -1 && parsedtime >= comparetime) ? 1 : 0; islink = (fields[FieldLink][0] != '\0') ? 1 : 0; /* first of feed section or new feed section. */ if(!totalfeeds || (fcur && strcmp(fcur->name, fields[FieldFeedName]))) { diff --git a/sfeed_plain.c b/sfeed_plain.c @@ -1,4 +1,3 @@ -#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -12,14 +11,12 @@ main(void) char *line = NULL, *fields[FieldLast]; time_t parsedtime, comparetime; size_t size = 0; + int r; comparetime = time(NULL) - (3600 * 24); /* 1 day is old news */ while(parseline(&line, &size, fields, FieldLast, '\t', stdin) > 0) { - errno = 0; - parsedtime = (time_t)strtol(fields[FieldUnixTimestamp], NULL, 10); - if(errno != 0) - parsedtime = 0; - if(parsedtime >= comparetime) + r = strtotime(fields[FieldUnixTimestamp], &parsedtime); + if(r != -1 && parsedtime >= comparetime) fputs(" N ", stdout); else fputs(" ", stdout); diff --git a/sfeed_stats.c b/sfeed_stats.c @@ -1,6 +1,5 @@ #include <ctype.h> #include <err.h> -#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -20,6 +19,7 @@ main(void) struct feed *f, *fcur = NULL; time_t parsedtime, comparetime, timenewest = 0; size_t size = 0; + int r; comparetime = time(NULL) - (3600 * 24); /* 1 day is old news */ @@ -28,11 +28,8 @@ main(void) feeds = fcur; while(parseline(&line, &size, fields, FieldLast, '\t', stdin) > 0) { - errno = 0; - parsedtime = (time_t)strtol(fields[FieldUnixTimestamp], NULL, 10); - if(errno != 0) - parsedtime = 0; - isnew = (parsedtime >= comparetime) ? 1 : 0; + r = strtotime(fields[FieldUnixTimestamp], &parsedtime); + isnew = (r != -1 && parsedtime >= comparetime) ? 1 : 0; /* first of feed section or new feed section. */ if(!totalfeeds || (fcur && strcmp(fcur->name, fields[FieldFeedName]))) { if(!(f = calloc(1, sizeof(struct feed)))) @@ -44,12 +41,12 @@ main(void) fcur = f; feeds = fcur; /* first item. */ } - if(parsedtime > timenewest) { + if(r != -1 && parsedtime > timenewest) { timenewest = parsedtime; strlcpy(timenewestformat, fields[FieldTimeFormatted], sizeof(timenewestformat)); } - if(parsedtime > fcur->timenewest) { + if(r != -1 && parsedtime > fcur->timenewest) { fcur->timenewest = parsedtime; strlcpy(fcur->timenewestformat, fields[FieldTimeFormatted], sizeof(fcur->timenewestformat)); diff --git a/util.c b/util.c @@ -1,4 +1,6 @@ #include <ctype.h> +#include <errno.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -141,3 +143,17 @@ printutf8pad(FILE *fp, const char *s, size_t len, int pad) for(; n < len; n++) putc(pad, fp); } + +int +strtotime(const char *s, time_t *t) +{ + long l; + + errno = 0; + l = strtol(s, NULL, 10); + if(errno != 0) + return -1; + *t = (time_t)l; + + return 0; +}