sfeed

simple feed reader - forked from git.codemadness.org/sfeed
git clone git://src.gearsix.net/sfeed
Log | Files | Refs | Atom | README | LICENSE

sfeed_web.c (3106B)


      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 
     10 static XMLParser parser;
     11 static int isbasetag, islinktag, ishrefattr, istypeattr;
     12 static char linkhref[4096], linktype[256], basehref[4096];
     13 
     14 static void
     15 printvalue(const char *s)
     16 {
     17 	for (; *s; s++)
     18 		if (!ISCNTRL((unsigned char)*s))
     19 			putchar(*s);
     20 }
     21 
     22 static void
     23 xmltagstart(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 
     36 static void
     37 xmltagstartparsed(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 
     68 static void
     69 xmlattrstart(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 
     88 static void
     89 xmlattr(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 
    102 static void
    103 xmlattrentity(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[16];
    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 
    120 int
    121 main(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 }