sfeed_atom.c (4200B)
1#include <stdio.h> 2#include <string.h> 3#include <time.h> 4 5#include "util.h" 6 7static struct tm tmnow; 8static time_t now; 9static char *line; 10static size_t linesize; 11 12static void 13printcontent(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 37static void 38printfeed(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 117int 118main(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}