pubsub_gethub.c - pubsubhubbubblub - pubsubhubbub client implementation
HTML git clone git://git.codemadness.org/pubsubhubbubblub
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
pubsub_gethub.c (2944B)
---
1 #include <err.h>
2 #include <stdio.h>
3 #include <strings.h>
4 #include <unistd.h>
5
6 #undef strlcat
7 size_t strlcat(char *, const char *, size_t);
8
9 #include "xml.h"
10
11 #define ISCNTRL(c) ((c) < ' ' || (c) == 0x7f)
12 #define TOLOWER(c) ((((unsigned)c) - 'A' < 26) ? ((c) | 32) : (c))
13
14 /* string and size */
15 #define STRP(s) s,sizeof(s)-1
16
17 static XMLParser parser;
18 static int islinktag, ishrefattr, isrelattr;
19 static char linkhref[4096], linkrel[256];
20
21 /* strcasestr() included for portability */
22 char *
23 strcasestr(const char *h, const char *n)
24 {
25 size_t i;
26
27 if (!n[0])
28 return (char *)h;
29
30 for (; *h; ++h) {
31 for (i = 0; n[i] && TOLOWER((unsigned char)n[i]) ==
32 TOLOWER((unsigned char)h[i]); ++i)
33 ;
34 if (n[i] == '\0')
35 return (char *)h;
36 }
37
38 return NULL;
39 }
40
41 static void
42 printvalue(const char *s)
43 {
44 for (; *s; s++)
45 if (!ISCNTRL((unsigned char)*s))
46 putchar(*s);
47 }
48
49 static void
50 xmltagstart(XMLParser *p, const char *t, size_t tl)
51 {
52 islinktag = 0;
53 char *l;
54
55 if (((l = strcasestr(t, ":link")) && !strcasecmp(l, ":link")) ||
56 !strcasecmp(t, "link")) {
57 islinktag = 1;
58 linkhref[0] = '\0';
59 linkrel[0] = '\0';
60 }
61 }
62
63 static void
64 xmltagstartparsed(XMLParser *p, const char *t, size_t tl, int isshort)
65 {
66 if (!islinktag)
67 return;
68
69 if (strncasecmp(linkrel, STRP("hub")) &&
70 strncasecmp(linkrel, STRP("self")))
71 return;
72
73 printvalue(linkhref);
74 putchar('\t');
75 printvalue(linkrel);
76 putchar('\n');
77 }
78
79 static void
80 xmlattrstart(XMLParser *p, const char *t, size_t tl, const char *a, size_t al)
81 {
82 ishrefattr = isrelattr = 0;
83
84 if (!islinktag)
85 return;
86
87 if (!strcasecmp(a, "href")) {
88 ishrefattr = 1;
89 linkhref[0] = '\0';
90 } else if (!strcasecmp(a, "rel")) {
91 isrelattr = 1;
92 linkrel[0] = '\0';
93 }
94 }
95
96 static void
97 xmlattr(XMLParser *p, const char *t, size_t tl, const char *n, size_t nl,
98 const char *v, size_t vl)
99 {
100 if (islinktag) {
101 if (ishrefattr)
102 strlcat(linkhref, v, sizeof(linkhref));
103 else if (isrelattr)
104 strlcat(linkrel, v, sizeof(linkrel));
105 }
106 }
107
108 static void
109 xmlattrentity(XMLParser *p, const char *t, size_t tl, const char *a, size_t al,
110 const char *v, size_t vl)
111 {
112 char buf[16];
113 int len;
114
115 if (!ishrefattr && !isrelattr)
116 return;
117
118 /* try to translate entity, else just pass as data to
119 * xmlattr handler. */
120 if ((len = xml_entitytostr(v, buf, sizeof(buf))) > 0)
121 xmlattr(p, t, tl, a, al, buf, (size_t)len);
122 else
123 xmlattr(p, t, tl, a, al, v, vl);
124 }
125
126 int
127 main(void)
128 {
129 #ifdef __OpenBSD__
130 if (pledge("stdio", NULL) == -1)
131 err(1, "pledge");
132 #endif
133
134 parser.xmlattr = xmlattr;
135 parser.xmlattrentity = xmlattrentity;
136 parser.xmlattrstart = xmlattrstart;
137 parser.xmltagstart = xmltagstart;
138 parser.xmltagstartparsed = xmltagstartparsed;
139
140 /* NOTE: getnext is defined in xml.h for inline optimization */
141 xml_parse(&parser);
142
143 if (ferror(stdin))
144 fputs("read error: <stdin>\n", stderr);;
145 if (fflush(stdout) || ferror(stdout))
146 fputs("write error: <stdout>\n", stderr);
147
148 return 0;
149 }