lunch-poll-legacy

Lunch Poll Legacy -- poll colleagues where to have lunch
Log | Files | Refs | README | LICENSE

http.c (2408B)


      1 /**
      2  * Lunch Poll Legacy
      3  * Copyright 2024, 2025 Matthias Balk
      4  */
      5 
      6 #include <ctype.h>
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <string.h>
     10 
     11 #include "http.h"
     12 
     13 static StatusCode status_codes[] = {
     14   { 200, "OK" },
     15   { 204, "No Content" },
     16   { 302, "Found" },
     17   { 303, "See Other" },
     18   { 400, "Bad Request" },
     19   { 404, "Not Found" },
     20   { 405, "Method Not Allowed" },
     21   { 415, "Unsupported Media Type" },
     22   { 500, "Internal Server Error" },
     23 };
     24 
     25 
     26 void header_status(int code)
     27 {
     28   StatusCode *sc;
     29   for (sc = status_codes; sc < status_codes + LEN(status_codes); sc++) {
     30     if (code == sc->code) {
     31       printf("Status: %d %s\r\n", sc->code, sc->name);
     32       return;
     33     }
     34   }
     35 
     36   if (code != 500) {
     37     header_status(500);
     38   }
     39 }
     40 
     41 void header(const char *key, const char *value)
     42 {
     43   printf("%s: %s\r\n", key, value);
     44 }
     45 
     46 void err_exit(const char *msg)
     47 {
     48   header_status(500);
     49   header_end();
     50   perror(msg);
     51   exit(EXIT_FAILURE);
     52 }
     53 
     54 /* https://stackoverflow.com/a/14530993 */
     55 void urldecode(const char *src, char *dst /*, size_t dst_size TODO*/)
     56 {
     57   char a, b;
     58   while (*src) {
     59     if ((*src == '%') &&
     60         ((a = src[1]) && (b = src[2])) &&
     61         (isxdigit(a) && isxdigit(b))) {
     62       if (a >= 'a')
     63         a -= 'a' - 'A';
     64       if (a >= 'A')
     65         a -= 'A' - 10;
     66       else
     67         a -= '0';
     68       if (b >= 'a')
     69         b -= 'a' - 'A';
     70       if (b >= 'A')
     71         b -= 'A' - 10;
     72       else
     73         b -= '0';
     74 
     75       *dst++ = 16*a+b;
     76       src+=3;
     77     }
     78     else if (*src == '+') {
     79       *dst++ = ' ';
     80       src++;
     81     }
     82     else {
     83       *dst++ = *src++;
     84     }
     85   }
     86   *dst++ = '\0';
     87 }
     88 
     89 
     90 /*
     91  * Uses strtok(3), x_www_form_urlencoded will be changed!
     92  */
     93 void split_and_decode_form_params(char* x_www_form_urlencoded, char** params)
     94 {
     95   int idx = 0;
     96   params[idx] = strtok(x_www_form_urlencoded, "&");
     97   while (params[idx++] != NULL) {
     98     if (idx >= MAX_PARAMS_COUNT) {
     99       fprintf(stderr, "error: too many params (>= %d)\n", MAX_PARAMS_COUNT);
    100       err_exit("error: too many params");
    101     }
    102     params[idx] = strtok(NULL, "&");
    103 
    104     /* we expected the decoded string to be shorter than the encoded string! */
    105     if (params[idx] != NULL) {
    106       char *value = strchr(params[idx], '=') + 1;
    107       size_t sz = strlen(value) + 1;
    108       char *value_tmp = calloc(sz, sizeof (char));
    109       urldecode(value, value_tmp);
    110       strlcpy(value, value_tmp, sz * sizeof (char));
    111       free(value_tmp);
    112     }
    113   }
    114 }