/** @file * @brief HTTP compression handling functions * * Helper functions to handle compression formats */ /* * Copyright (c) 2025 Endress+Hauser * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #include #include "headers/server_internal.h" static int http_compression_match(enum http_compression *compression, const char *text, enum http_compression expected); void http_compression_parse_accept_encoding(const char *accept_encoding, size_t len, uint8_t *supported_compression) { enum http_compression detected_compression; char strbuf[HTTP_COMPRESSION_MAX_STRING_LEN + 1] = {0}; const char *start = accept_encoding; const char *end = NULL; bool priority_string = false; *supported_compression = HTTP_NONE; for (size_t i = 0; i < len; i++) { if (accept_encoding[i] == 0) { break; } else if (accept_encoding[i] == ' ') { start = &accept_encoding[i + 1]; continue; } else if (accept_encoding[i] == ';') { end = &accept_encoding[i]; priority_string = true; } else if (accept_encoding[i] == ',') { if (!priority_string) { end = &accept_encoding[i]; } priority_string = false; } else if (i + 1 == len) { end = &accept_encoding[i + 1]; } if (end == NULL) { continue; } if (end - start > HTTP_COMPRESSION_MAX_STRING_LEN) { end = NULL; start = end + 1; continue; } memcpy(strbuf, start, end - start); strbuf[end - start] = 0; if (http_compression_from_text(&detected_compression, strbuf) == 0) { WRITE_BIT(*supported_compression, detected_compression, true); } end = NULL; start = end + 1; } } const char *http_compression_text(enum http_compression compression) { switch (compression) { case HTTP_NONE: return ""; case HTTP_GZIP: return "gzip"; case HTTP_COMPRESS: return "compress"; case HTTP_DEFLATE: return "deflate"; case HTTP_BR: return "br"; case HTTP_ZSTD: return "zstd"; } return ""; } int http_compression_from_text(enum http_compression *compression, const char *text) { __ASSERT_NO_MSG(compression); __ASSERT_NO_MSG(text); for (enum http_compression i = 0; compression_value_is_valid(i); ++i) { if (http_compression_match(compression, text, i) == 0) { return 0; } } return 1; } bool compression_value_is_valid(enum http_compression compression) { switch (compression) { case HTTP_NONE: case HTTP_GZIP: case HTTP_COMPRESS: case HTTP_DEFLATE: case HTTP_BR: case HTTP_ZSTD: return true; } return false; } static int http_compression_match(enum http_compression *compression, const char *text, enum http_compression expected) { __ASSERT_NO_MSG(compression); __ASSERT_NO_MSG(text); if (strcasecmp(http_compression_text(expected), text) == 0) { *compression = expected; return 0; } else { return 1; } }