sfeed

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

sfeed_web.c (raw) (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 }