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("<", stdout); break;
18 case '>': fputs(">", stdout); break;
19 case '\'': fputs("'", stdout); break;
20 case '&': fputs("&", stdout); break;
21 case '"': fputs(""", 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 }