// MIT License, Copyright (c) 2020 Marvin Borner #include #include #include #include #include #include #include #include #include char *http_data(char *r) { char *h = NULL; for (u32 i = 0; i < strlen(r); ++i) { if (r[i] == '\r' && r[i + 1] == '\n' && r[i + 2] == '\r' && r[i + 3] == '\n') { h = &r[i + 4]; break; } } return h; } char *http_header_key(char *r, const char *key) { char *res = NULL; for (char *p = r; *p; p++) { /* printf("'%c%c%c' vs '%c%c%c'\n", p[0], p[1], p[2], key[0], key[1], key[2]); */ if (strlen(p) >= strlen(key) && !memcmp(p, key, strlen(key))) { char *start = p + strlen(key) + 2; char *end = start; for (; *end != '\n'; end++) ; res = malloc(end - start); memcpy(res, start, end - start - 1); res[end - start] = '\0'; break; } } return res; } u32 http_content_length(char *r) { char *value = http_header_key(r, "Content-Length"); int length = value ? atoi(value) : 0; free(value); return length; } char *http_code(char *r) { char *code = malloc(4); char tmp = r[12]; r[12] = '\0'; memcpy(code, r + 9, 3); code[3] = '\0'; r[12] = tmp; return code; } u32 http_response(const char *http_code, u32 content_length, const char *data, char *resp) { char buf[16] = { 0 }; resp[0] = '\0'; strcat(resp, "HTTP/1.1 "); strcat(resp, buf); strcat(resp, http_code); strcat(resp, "\r\n"); strcat(resp, "Content-Length: "); strcat(resp, conv_base(content_length, buf, 10, 0)); strcat(resp, "\r\n"); strcat(resp, "Server: Melvix\r\n"); strcat(resp, "Content-Type: text/html\r\n"); strcat(resp, "Connection: close\r\n\r\n"); u32 len = strlen(resp); memcpy(&resp[len], data, content_length); return len + content_length; } char *http_query_get(const char *url, const char *path) { char *query = malloc(27 + strlen(url)); // TODO: Dynamic http length etc query[0] = '\0'; strcat(query, "GET "); if (path[0] != '/') strcat(query, "/"); strcat(query, path); strcat(query, " HTTP/1.1\r\nHost: "); strcat(query, url); strcat(query, "\r\n\r\n"); return query; } char *http_query_path(const char *query, char *path) { u8 b = 0; u32 s = 0; u32 e = 0; while (1) { if (!b && query[e] == ' ' && query[++e]) { s = e; b = 1; } else if (b && query[e] == ' ') { strncat(path, &query[s], e - s); break; } else if (query[e] == '\0') { return NULL; } e++; } return path; } char *http_receive(struct socket *socket) { char buf[4096] = { 0 }; if (!net_receive(socket, buf, 4096, NET_TIMEOUT)) return NULL; u32 length = http_content_length(buf); char *data = malloc(strlen(buf) + length); memcpy(data, buf, strlen(buf)); while (strlen(http_data(data)) != length) { if (!net_receive(socket, data, length, NET_TIMEOUT)) break; } return data; }