lunch-poll-legacy

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

http.c (2465B)


      1 /**
      2  * Lunch Poll Legacy
      3  * Copyright 2024 - 2026 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 static void decode_param_value(char* param)
     90 {
     91   /* we expected the decoded string to be shorter than the encoded string! */
     92   if (param != NULL) {
     93     char *value = strchr(param, '=') + 1;
     94     size_t sz = strlen(value) + 1;
     95     char *value_tmp = calloc(sz, sizeof (char));
     96     urldecode(value, value_tmp);
     97     strlcpy(value, value_tmp, sz * sizeof (char));
     98     free(value_tmp);
     99   }
    100 }
    101 
    102 /*
    103  * Uses strtok(3), x_www_form_urlencoded will be changed!
    104  */
    105 void split_and_decode_form_params(char* x_www_form_urlencoded, char** params)
    106 {
    107   int idx = 0;
    108   params[idx] = strtok(x_www_form_urlencoded, "&");
    109   while (params[idx] != NULL) {
    110     decode_param_value(params[idx]);
    111 
    112     if (++idx >= MAX_PARAMS_COUNT) {
    113       fprintf(stderr, "error: too many params (>= %d)\n", MAX_PARAMS_COUNT);
    114       err_exit("error: too many params");
    115     }
    116     params[idx] = strtok(NULL, "&");
    117 
    118   }
    119 }