pubsubhubbubblub.c - randomcrap - random crap programs of varying quality
(HTM) git clone git://git.codemadness.org/randomcrap
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
pubsubhubbubblub.c (2897B)
---
1 /*
2 Small stupid minimal base PubSubHubBub implementation as a CGI program.
3 Reference: https://pubsubhubbub.github.io/PubSubHubbub/pubsubhubbub-core-0.4.html
4
5 Things that could be added: checking the secret, handling POST requests directly.
6 */
7
8 #include <ctype.h>
9 #include <err.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14
15 int
16 hexdigit(int c)
17 {
18 if (c >= '0' && c <= '9')
19 return c - '0';
20 else if (c >= 'A' && c <= 'F')
21 return c - 'A' + 10;
22 else if (c >= 'a' && c <= 'f')
23 return c - 'a' + 10;
24
25 return 0;
26 }
27
28 /* decode until NUL separator or end of "key". */
29 int
30 decodeparam(char *buf, size_t bufsiz, const char *s)
31 {
32 size_t i;
33
34 if (!bufsiz)
35 return -1;
36
37 for (i = 0; *s && *s != '&'; s++) {
38 switch (*s) {
39 case '%':
40 if (i + 3 >= bufsiz)
41 return -1;
42 if (!isxdigit((unsigned char)*(s+1)) ||
43 !isxdigit((unsigned char)*(s+2)))
44 return -1;
45 buf[i++] = hexdigit(*(s+1)) * 16 + hexdigit(*(s+2));
46 s += 2;
47 break;
48 case '+':
49 if (i + 1 >= bufsiz)
50 return -1;
51 buf[i++] = ' ';
52 break;
53 default:
54 if (i + 1 >= bufsiz)
55 return -1;
56 buf[i++] = *s;
57 break;
58 }
59 }
60 buf[i] = '\0';
61
62 return i;
63 }
64
65 char *
66 getparam(const char *query, const char *s)
67 {
68 const char *p, *last = NULL;
69 size_t len;
70
71 len = strlen(s);
72 for (p = query; (p = strstr(p, s)); p += len) {
73 if (p[len] == '=' && (p == query || p[-1] == '&' || p[-1] == '?'))
74 last = p + len + 1;
75 }
76
77 return (char *)last;
78 }
79
80 void
81 badrequest(const char *s)
82 {
83 fputs("Status: 400 Bad Request\r\n", stdout);
84 fputs("Content-Type: text/plain; charset=utf-8\r\n", stdout);
85 fputs("\r\n", stdout);
86 printf("400 Bad Request: %s\r\n", s);
87 exit(0);
88 }
89
90 int
91 main(void)
92 {
93 char challenge[256], lease_seconds[64], mode[32], topic[4096];
94 char *query, *p;
95
96 #ifdef __OpenBSD__
97 if (pledge("stdio", NULL) == -1)
98 err(1, "pledge");
99 #endif
100
101 if (!(query = getenv("QUERY_STRING")))
102 query = "";
103
104 if ((p = getparam(query, "hub.topic"))) {
105 if (decodeparam(topic, sizeof(topic), p) == -1)
106 badrequest("hub.topic");
107 }
108 if ((p = getparam(query, "hub.challenge"))) {
109 if (decodeparam(challenge, sizeof(challenge), p) == -1)
110 badrequest("hub.challenge");
111 }
112 if ((p = getparam(query, "hub.mode"))) {
113 if (decodeparam(mode, sizeof(mode), p) == -1)
114 badrequest("hub.mode");
115 }
116 if ((p = getparam(query, "hub.lease_seconds"))) {
117 if (decodeparam(lease_seconds, sizeof(lease_seconds), p) == -1)
118 badrequest("hub.lease_seconds");
119 }
120
121 if (challenge[0]) {
122 fputs("Status: 202 Accepted\r\n", stdout);
123 fputs("Content-Type: text/plain; charset=utf-8\r\n", stdout);
124 fputs("\r\n", stdout);
125 printf("%s\r\n", challenge);
126 } else {
127 fputs("Status: 200 OK\r\n", stdout);
128 fputs("Content-Type: text/plain; charset=utf-8\r\n", stdout);
129 fputs("\r\n", stdout);
130 printf("pubsubhubbubblub 0.1 running perfectly and flapping graciously in the wind.\r\n");
131 }
132
133 return 0;
134 }