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 }