sfeed

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

commit 493e2e508530aa95d4806e4aca52183794d20ad0
parent eb9e9a957a75069edecbfcc1872930d07e146a1a
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Sat, 20 Apr 2019 16:21:44 +0200

add sfeed_atom: convert one or more feeds from TSV (back to) Atom

Diffstat:
MMakefile | 1+
MREADME | 1+
Asfeed_atom.1 | 37+++++++++++++++++++++++++++++++++++++
Asfeed_atom.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 138 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -7,6 +7,7 @@ VERSION = 0.9.8 BIN = \ sfeed\ + sfeed_atom\ sfeed_frames\ sfeed_gph \ sfeed_html\ diff --git a/README b/README @@ -113,6 +113,7 @@ Files sfeed - Read XML RSS or Atom feed data from stdin. Write feed data in TAB-separated format to stdout. +sfeed_atom - Format feed data (TSV) to an Atom feed. sfeed_frames - Format feed data (TSV) to HTML file(s) with frames. sfeed_gph - Format feed data (TSV) to geomyidae .gph files. sfeed_html - Format feed data (TSV) to HTML. diff --git a/sfeed_atom.1 b/sfeed_atom.1 @@ -0,0 +1,37 @@ +.Dd April 20, 2019 +.Dt SFEED_ATOM 1 +.Os +.Sh NAME +.Nm sfeed_atom +.Nd format feed data to an Atom feed +.Sh SYNOPSIS +.Nm +.Op Ar file... +.Sh DESCRIPTION +.Nm +formats feed data (TSV) from +.Xr sfeed 1 +from stdin or +.Ar file +to stdout as an Atom (XML) feed. +If one or more +.Ar file +are specified, the basename of the +.Ar file +is used as the feed name in the output. +If no +.Ar file +parameters are specified and so the data is read from stdin the feed name +is empty. +.Pp +If +.Nm +is reading from one or more +.Ar file +it will prefix the entry title with the feed name which is the basename of the +input file. +.Sh SEE ALSO +.Xr sfeed 1 , +.Xr sfeed_plain 1 +.Sh AUTHORS +.An Hiltjo Posthuma Aq Mt hiltjo@codemadness.org diff --git a/sfeed_atom.c b/sfeed_atom.c @@ -0,0 +1,99 @@ +#include <sys/types.h> + +#include <ctype.h> +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "util.h" + +static time_t comparetime; +static char *line; +static size_t linesize; + +static void +printfeed(FILE *fp, const char *feedname) +{ + char *fields[FieldLast]; + struct tm *tm; + time_t parsedtime; + ssize_t linelen; + + while ((linelen = getline(&line, &linesize, fp)) > 0) { + if (line[linelen - 1] == '\n') + line[--linelen] = '\0'; + if (!parseline(line, fields)) + break; + + parsedtime = 0; + if (strtotime(fields[FieldUnixTimestamp], &parsedtime)) + continue; + if (!(tm = localtime(&parsedtime))) + err(1, "localtime"); + + fputs("<entry>\n\t<title>", stdout); + if (feedname[0]) { + fputs("[", stdout); + xmlencode(feedname, stdout); + fputs("] ", stdout); + } + xmlencode(fields[FieldTitle], stdout); + fputs("</title>\n\t<link rel=\"alternate\" href=\"", stdout); + xmlencode(fields[FieldLink], stdout); + fputs("\" />\n", stdout); + if (fields[FieldEnclosure][0]) { + fputs("\t<link rel=\"enclosure\" href=\"", stdout); + xmlencode(fields[FieldEnclosure], stdout); + fputs("\" />\n", stdout); + } + fprintf(stdout, "\t<published>%04d-%02d-%02dT%02d:%02d:%02dZ</published>\n", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + if (fields[FieldAuthor][0]) { + fputs("\t<author><name>", stdout); + xmlencode(fields[FieldAuthor], stdout); + fputs("</name></author>\n", stdout); + } + fputs("</entry>\n", stdout); + } +} + +int +main(int argc, char *argv[]) +{ + FILE *fp; + char *name; + int i; + + if (argc == 1) { + if (pledge("stdio", NULL) == -1) + err(1, "pledge"); + } else { + if (pledge("stdio rpath", NULL) == -1) + err(1, "pledge"); + } + + fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<feed xmlns=\"http://www.w3.org/2005/Atom\" xml:lang=\"en\">\n", + stdout); + + if (argc == 1) { + printfeed(stdin, ""); + } else { + for (i = 1; i < argc; i++) { + if (!(fp = fopen(argv[i], "r"))) + err(1, "fopen: %s", argv[i]); + name = ((name = strrchr(argv[i], '/'))) ? name + 1 : argv[i]; + printfeed(fp, name); + if (ferror(fp)) + err(1, "ferror: %s", argv[i]); + fclose(fp); + } + } + + fputs("</feed>\n", stdout); + + return 0; +}