From 04860567f7c6eae186e5c611d33e1707847af477 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 29 Jun 2025 11:10:29 -0500 Subject: [PATCH] fixes --- .../web_server_idf/multipart_parser.cpp | 46 +++++-------------- .../web_server_idf/multipart_parser.h | 1 + .../web_server_idf/multipart_parser_utils.h | 19 ++++++++ 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/esphome/components/web_server_idf/multipart_parser.cpp b/esphome/components/web_server_idf/multipart_parser.cpp index 5d6cd6f1ad..e01ef458ed 100644 --- a/esphome/components/web_server_idf/multipart_parser.cpp +++ b/esphome/components/web_server_idf/multipart_parser.cpp @@ -147,43 +147,21 @@ bool MultipartParser::parse_headers() { return true; } - // Parse Content-Disposition header (case-insensitive) - if (str_startswith_case_insensitive(line, "content-disposition:")) { - // Extract name parameter - std::string name = extract_header_param(line, "name"); - if (!name.empty()) { - current_name_ = name; - } - - // Extract filename parameter if present - std::string filename = extract_header_param(line, "filename"); - if (!filename.empty()) { - current_filename_ = filename; - } - } - // Parse Content-Type header (case-insensitive) - else if (str_startswith_case_insensitive(line, "content-type:")) { - // Find the colon and skip it - size_t colon_pos = line.find(':'); - if (colon_pos != std::string::npos) { - current_content_type_ = line.substr(colon_pos + 1); - // Trim leading whitespace - size_t start = current_content_type_.find_first_not_of(" \t"); - if (start != std::string::npos) { - current_content_type_ = current_content_type_.substr(start); - } else { - current_content_type_.clear(); - } - // Trim trailing whitespace - size_t end = current_content_type_.find_last_not_of(" \t\r\n"); - if (end != std::string::npos) { - current_content_type_ = current_content_type_.substr(0, end + 1); - } - } - } + process_header_line(line); } } +void MultipartParser::process_header_line(const std::string &line) { + if (str_startswith_case_insensitive(line, "content-disposition:")) { + // Extract name and filename parameters + current_name_ = extract_header_param(line, "name"); + current_filename_ = extract_header_param(line, "filename"); + } else if (str_startswith_case_insensitive(line, "content-type:")) { + current_content_type_ = extract_header_value(line); + } + // RFC 7578: Ignore any other Content-* headers +} + bool MultipartParser::extract_content() { // Look for next boundary std::string search_boundary = CRLF_STR + boundary_; diff --git a/esphome/components/web_server_idf/multipart_parser.h b/esphome/components/web_server_idf/multipart_parser.h index 878c54be05..cc9b82dbb2 100644 --- a/esphome/components/web_server_idf/multipart_parser.h +++ b/esphome/components/web_server_idf/multipart_parser.h @@ -52,6 +52,7 @@ class MultipartParser { private: bool find_boundary(); bool parse_headers(); + void process_header_line(const std::string &line); bool extract_content(); std::string read_line(); diff --git a/esphome/components/web_server_idf/multipart_parser_utils.h b/esphome/components/web_server_idf/multipart_parser_utils.h index a644a392ad..d938674efb 100644 --- a/esphome/components/web_server_idf/multipart_parser_utils.h +++ b/esphome/components/web_server_idf/multipart_parser_utils.h @@ -207,6 +207,25 @@ inline bool is_form_urlencoded(const char *content_type) { return stristr(content_type, "application/x-www-form-urlencoded") != nullptr; } +// Trim whitespace from both ends of a string +inline std::string str_trim(const std::string &str) { + size_t start = str.find_first_not_of(" \t\r\n"); + if (start == std::string::npos) { + return ""; + } + size_t end = str.find_last_not_of(" \t\r\n"); + return str.substr(start, end - start + 1); +} + +// Extract header value (everything after the colon) +inline std::string extract_header_value(const std::string &header) { + size_t colon_pos = header.find(':'); + if (colon_pos == std::string::npos) { + return ""; + } + return str_trim(header.substr(colon_pos + 1)); +} + } // namespace web_server_idf } // namespace esphome #endif // USE_WEBSERVER_OTA