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 }