summaryrefslogtreecommitdiff
path: root/sfeed_web.c
blob: 676e211e718838c42c5a5f34cb2275243faeb519 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <sys/types.h>

#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <time.h>

#include "util.h"
#include "xml.h"

/* string and size */
#define STRP(s) s,sizeof(s)-1

static XMLParser parser;
static unsigned int isbase, islink, isfeedlink, found;
static char abslink[4096], feedlink[4096], basehref[4096], feedtype[256];

static void
printfeedtype(const char *s, FILE *fp)
{
	for (; *s; s++)
		if (!isspace((unsigned char)*s))
			fputc(*s, fp);
}

static void
xmltagstart(XMLParser *p, const char *t, size_t tl)
{
	isbase = islink = isfeedlink = 0;
	if (tl != 4) /* optimization */
		return;

	if (!strcasecmp(t, "base"))
		isbase = 1;
	else if (!strcasecmp(t, "link"))
		islink = 1;
}

static void
xmltagstartparsed(XMLParser *p, const char *t, size_t tl, int isshort)
{
	if (!isfeedlink)
		return;

	if (absuri(abslink, sizeof(abslink), feedlink, basehref) != -1)
		fputs(abslink, stdout);
	else
		fputs(feedlink, stdout);
	putchar('\t');
	printfeedtype(feedtype, stdout);
	putchar('\n');
	found++;
}

static void
xmlattr(XMLParser *p, const char *t, size_t tl, const char *n, size_t nl,
	const char *v, size_t vl)
{
	if (nl != 4) /* optimization */
		return;

	if (isbase) {
		if (!strcasecmp(n, "href"))
			strlcpy(basehref, v, sizeof(basehref));
	} else if (islink) {
		if (!strcasecmp(n, "type")) {
			if (!strncasecmp(v, STRP("application/atom")) ||
			    !strncasecmp(v, STRP("application/xml"))  ||
			    !strncasecmp(v, STRP("application/rss"))) {
				isfeedlink = 1;
				strlcpy(feedtype, v, sizeof(feedtype));
			}
		} else if (!strcasecmp(n, "href")) {
			strlcpy(feedlink, v, sizeof(feedlink));
		}
	}
}

int
main(int argc, char *argv[])
{
	if (pledge("stdio", NULL) == -1)
		err(1, "pledge");

	if (argc > 1)
		strlcpy(basehref, argv[1], sizeof(basehref));

	parser.xmlattr = xmlattr;
	parser.xmltagstart = xmltagstart;
	parser.xmltagstartparsed = xmltagstartparsed;

	/* NOTE: getnext is defined in xml.h for inline optimization */
	xml_parse(&parser);

	return found > 0 ? 0 : 1;
}