sfeed_atom.c - sfeed - RSS and Atom parser
 (HTM) git clone git://git.codemadness.org/sfeed
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       sfeed_atom.c (4200B)
       ---
            1 #include <stdio.h>
            2 #include <string.h>
            3 #include <time.h>
            4 
            5 #include "util.h"
            6 
            7 static struct tm tmnow;
            8 static time_t now;
            9 static char *line;
           10 static size_t linesize;
           11 
           12 static void
           13 printcontent(const char *s)
           14 {
           15         for (; *s; ++s) {
           16                 switch (*s) {
           17                 case '<':  fputs("&lt;",   stdout); break;
           18                 case '>':  fputs("&gt;",   stdout); break;
           19                 case '\'': fputs("&#39;",  stdout); break;
           20                 case '&':  fputs("&amp;",  stdout); break;
           21                 case '"':  fputs("&quot;", stdout); break;
           22                 case '\\':
           23                         if (*(s + 1) == '\0')
           24                                 break;
           25                         s++;
           26                         switch (*s) {
           27                         case 'n':  putchar('\n'); break;
           28                         case '\\': putchar('\\'); break;
           29                         case 't':  putchar('\t'); break;
           30                         }
           31                         break;
           32                 default:  putchar(*s);
           33                 }
           34         }
           35 }
           36 
           37 static void
           38 printfeed(FILE *fp, const char *feedname)
           39 {
           40         char *fields[FieldLast], *p, *tmp;
           41         struct tm parsedtm, *tm;
           42         time_t parsedtime;
           43         ssize_t linelen;
           44         int c;
           45 
           46         while ((linelen = getline(&line, &linesize, fp)) > 0 &&
           47                !ferror(stdout)) {
           48                 if (line[linelen - 1] == '\n')
           49                         line[--linelen] = '\0';
           50                 parseline(line, fields);
           51 
           52                 fputs("<entry>\n\t<title>", stdout);
           53                 if (feedname[0]) {
           54                         fputs("[", stdout);
           55                         xmlencode(feedname, stdout);
           56                         fputs("] ", stdout);
           57                 }
           58                 xmlencode(fields[FieldTitle], stdout);
           59                 fputs("</title>\n", stdout);
           60                 if (fields[FieldLink][0]) {
           61                         fputs("\t<link rel=\"alternate\" href=\"", stdout);
           62                         xmlencode(fields[FieldLink], stdout);
           63                         fputs("\" />\n", stdout);
           64                 }
           65                 /* prefer link over id for Atom <id>. */
           66                 fputs("\t<id>", stdout);
           67                 if (fields[FieldLink][0])
           68                         xmlencode(fields[FieldLink], stdout);
           69                 else if (fields[FieldId][0])
           70                         xmlencode(fields[FieldId], stdout);
           71                 fputs("</id>\n", stdout);
           72                 if (fields[FieldEnclosure][0]) {
           73                         fputs("\t<link rel=\"enclosure\" href=\"", stdout);
           74                         xmlencode(fields[FieldEnclosure], stdout);
           75                         fputs("\" />\n", stdout);
           76                 }
           77 
           78                 parsedtime = 0;
           79                 if (strtotime(fields[FieldUnixTimestamp], &parsedtime) ||
           80                     !(tm = gmtime_r(&parsedtime, &parsedtm)))
           81                         tm = &tmnow;
           82                 fprintf(stdout, "\t<updated>%04d-%02d-%02dT%02d:%02d:%02dZ</updated>\n",
           83                         tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
           84                         tm->tm_hour, tm->tm_min, tm->tm_sec);
           85 
           86                 if (fields[FieldAuthor][0]) {
           87                         fputs("\t<author><name>", stdout);
           88                         xmlencode(fields[FieldAuthor], stdout);
           89                         fputs("</name></author>\n", stdout);
           90                 }
           91                 if (fields[FieldContent][0]) {
           92                         if (!strcmp(fields[FieldContentType], "html")) {
           93                                 fputs("\t<content type=\"html\">", stdout);
           94                         } else {
           95                                 /* NOTE: an RSS/Atom viewer may or may not format
           96                                  * whitespace such as newlines.
           97                                  * Workaround: type="html" and <![CDATA[<pre></pre>]]> */
           98                                 fputs("\t<content>", stdout);
           99                         }
          100                         printcontent(fields[FieldContent]);
          101                         fputs("</content>\n", stdout);
          102                 }
          103                 for (p = fields[FieldCategory]; (tmp = strchr(p, '|')); p = tmp + 1) {
          104                         c = *tmp;
          105                         *tmp = '\0'; /* temporary NUL-terminate */
          106                         if (*p) {
          107                                 fputs("\t<category term=\"", stdout);
          108                                 xmlencode(p, stdout);
          109                                 fputs("\" />\n", stdout);
          110                         }
          111                         *tmp = c; /* restore */
          112                 }
          113                 fputs("</entry>\n", stdout);
          114         }
          115 }
          116 
          117 int
          118 main(int argc, char *argv[])
          119 {
          120         struct tm *tm;
          121         FILE *fp;
          122         char *name;
          123         int i;
          124 
          125         if (pledge(argc <= 1 ? "stdio" : "stdio rpath", NULL) == -1)
          126                 err(1, "pledge");
          127 
          128         if ((now = time(NULL)) == (time_t)-1)
          129                 errx(1, "time");
          130         if (!(tm = gmtime_r(&now, &tmnow)))
          131                 err(1, "gmtime_r: can't get current time");
          132 
          133         fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
          134               "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n"
          135               "\t<title>Newsfeed</title>\n", stdout);
          136         printf("\t<id>urn:newsfeed:%lld</id>\n"
          137                "\t<updated>%04d-%02d-%02dT%02d:%02d:%02dZ</updated>\n",
          138                (long long)now,
          139                tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
          140                tm->tm_hour, tm->tm_min, tm->tm_sec);
          141 
          142         if (argc <= 1) {
          143                 printfeed(stdin, "");
          144                 checkfileerror(stdin, "<stdin>", 'r');
          145         } else {
          146                 for (i = 1; i < argc; i++) {
          147                         if (!(fp = fopen(argv[i], "r")))
          148                                 err(1, "fopen: %s", argv[i]);
          149                         name = ((name = strrchr(argv[i], '/'))) ? name + 1 : argv[i];
          150                         printfeed(fp, name);
          151                         checkfileerror(fp, argv[i], 'r');
          152                         checkfileerror(stdout, "<stdout>", 'w');
          153                         fclose(fp);
          154                 }
          155         }
          156 
          157         fputs("</feed>\n", stdout);
          158 
          159         checkfileerror(stdout, "<stdout>", 'w');
          160 
          161         return 0;
          162 }