pubsub_gethub.c - pubsubhubbubblub - pubsubhubbub client implementation | |
git clone git://git.codemadness.org/pubsubhubbubblub | |
Log | |
Files | |
Refs | |
README | |
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… | |
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, siz… | |
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 } |