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 }