sfeed_web.c (3105B)
1#include <stdio.h> 2#include <strings.h> 3 4#include "util.h" 5#include "xml.h" 6 7/* string and size */ 8#define STRP(s) s,sizeof(s)-1 9 10static XMLParser parser; 11static int isbasetag, islinktag, ishrefattr, istypeattr; 12static char linkhref[4096], linktype[256], basehref[4096]; 13 14static void 15printvalue(const char *s) 16{ 17 for (; *s; s++) 18 if (!ISCNTRL((unsigned char)*s)) 19 putchar(*s); 20} 21 22static void 23xmltagstart(XMLParser *p, const char *t, size_t tl) 24{ 25 isbasetag = islinktag = 0; 26 27 if (!strcasecmp(t, "base")) { 28 isbasetag = 1; 29 } else if (!strcasecmp(t, "link")) { 30 islinktag = 1; 31 linkhref[0] = '\0'; 32 linktype[0] = '\0'; 33 } 34} 35 36static void 37xmltagstartparsed(XMLParser *p, const char *t, size_t tl, int isshort) 38{ 39 struct uri baseuri, linkuri, u; 40 char buf[4096]; 41 int r = -1; 42 43 if (!islinktag) 44 return; 45 46 if (strncasecmp(linktype, STRP("application/atom")) && 47 strncasecmp(linktype, STRP("application/xml")) && 48 strncasecmp(linktype, STRP("application/rss"))) 49 return; 50 51 /* parse base URI each time: it can change. */ 52 if (basehref[0] && 53 uri_parse(linkhref, &linkuri) != -1 && !linkuri.proto[0] && 54 uri_parse(basehref, &baseuri) != -1 && 55 uri_makeabs(&u, &linkuri, &baseuri) != -1 && u.proto[0]) 56 r = uri_format(buf, sizeof(buf), &u); 57 58 if (r >= 0 && (size_t)r < sizeof(buf)) 59 printvalue(buf); 60 else 61 printvalue(linkhref); 62 63 putchar('\t'); 64 printvalue(linktype); 65 putchar('\n'); 66} 67 68static void 69xmlattrstart(XMLParser *p, const char *t, size_t tl, const char *a, size_t al) 70{ 71 ishrefattr = istypeattr = 0; 72 73 if (!isbasetag && !islinktag) 74 return; 75 76 if (!strcasecmp(a, "href")) { 77 ishrefattr = 1; 78 if (isbasetag) 79 basehref[0] = '\0'; 80 else if (islinktag) 81 linkhref[0] = '\0'; 82 } else if (!strcasecmp(a, "type") && islinktag) { 83 istypeattr = 1; 84 linktype[0] = '\0'; 85 } 86} 87 88static void 89xmlattr(XMLParser *p, const char *t, size_t tl, const char *n, size_t nl, 90 const char *v, size_t vl) 91{ 92 if (isbasetag && ishrefattr) { 93 strlcat(basehref, v, sizeof(basehref)); 94 } else if (islinktag) { 95 if (ishrefattr) 96 strlcat(linkhref, v, sizeof(linkhref)); 97 else if (istypeattr) 98 strlcat(linktype, v, sizeof(linktype)); 99 } 100} 101 102static void 103xmlattrentity(XMLParser *p, const char *t, size_t tl, const char *a, size_t al, 104 const char *v, size_t vl) 105{ 106 char buf[8]; 107 int len; 108 109 if (!ishrefattr && !istypeattr) 110 return; 111 112 /* try to translate entity, else just pass as data to 113 * xmlattr handler. */ 114 if ((len = xml_entitytostr(v, buf, sizeof(buf))) > 0) 115 xmlattr(p, t, tl, a, al, buf, (size_t)len); 116 else 117 xmlattr(p, t, tl, a, al, v, vl); 118} 119 120int 121main(int argc, char *argv[]) 122{ 123 if (pledge("stdio", NULL) == -1) 124 err(1, "pledge"); 125 126 if (argc > 1) 127 strlcpy(basehref, argv[1], sizeof(basehref)); 128 129 parser.xmlattr = xmlattr; 130 parser.xmlattrentity = xmlattrentity; 131 parser.xmlattrstart = xmlattrstart; 132 parser.xmltagstart = xmltagstart; 133 parser.xmltagstartparsed = xmltagstartparsed; 134 135 /* NOTE: GETNEXT is defined in xml.h for inline optimization */ 136 xml_parse(&parser); 137 138 checkfileerror(stdin, "<stdin>", 'r'); 139 checkfileerror(stdout, "<stdout>", 'w'); 140 141 return 0; 142}