mirror of
https://github.com/esphome/esphome.git
synced 2025-08-07 02:47:47 +00:00
fixes
This commit is contained in:
parent
9047b02c92
commit
614a2f66a3
@ -1,6 +1,7 @@
|
||||
#ifdef USE_ESP_IDF
|
||||
#ifdef USE_WEBSERVER_OTA
|
||||
#include "multipart_parser.h"
|
||||
#include "multipart_parser_utils.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
@ -141,35 +142,38 @@ bool MultipartParser::parse_headers() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse Content-Disposition header
|
||||
if (line.find("Content-Disposition:") == 0) {
|
||||
// Extract name
|
||||
size_t name_pos = line.find("name=\"");
|
||||
if (name_pos != std::string::npos) {
|
||||
name_pos += 6;
|
||||
size_t name_end = line.find("\"", name_pos);
|
||||
if (name_end != std::string::npos) {
|
||||
current_name_ = line.substr(name_pos, name_end - name_pos);
|
||||
}
|
||||
// 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 if present
|
||||
size_t filename_pos = line.find("filename=\"");
|
||||
if (filename_pos != std::string::npos) {
|
||||
filename_pos += 10;
|
||||
size_t filename_end = line.find("\"", filename_pos);
|
||||
if (filename_end != std::string::npos) {
|
||||
current_filename_ = line.substr(filename_pos, filename_end - filename_pos);
|
||||
}
|
||||
// Extract filename parameter if present
|
||||
std::string filename = extract_header_param(line, "filename");
|
||||
if (!filename.empty()) {
|
||||
current_filename_ = filename;
|
||||
}
|
||||
}
|
||||
// Parse Content-Type header
|
||||
else if (line.find("Content-Type:") == 0) {
|
||||
current_content_type_ = line.substr(14);
|
||||
// Trim 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);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
128
esphome/components/web_server_idf/multipart_parser_utils.h
Normal file
128
esphome/components/web_server_idf/multipart_parser_utils.h
Normal file
@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
#ifdef USE_ESP_IDF
|
||||
#ifdef USE_WEBSERVER_OTA
|
||||
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
|
||||
namespace esphome {
|
||||
namespace web_server_idf {
|
||||
|
||||
// Case-insensitive string comparison
|
||||
inline bool str_equals_case_insensitive(const std::string &a, const std::string &b) {
|
||||
if (a.length() != b.length()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < a.length(); i++) {
|
||||
if (tolower(a[i]) != tolower(b[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Case-insensitive string prefix check
|
||||
inline bool str_startswith_case_insensitive(const std::string &str, const std::string &prefix) {
|
||||
if (str.length() < prefix.length()) {
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < prefix.length(); i++) {
|
||||
if (tolower(str[i]) != tolower(prefix[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Find a substring case-insensitively
|
||||
inline size_t str_find_case_insensitive(const std::string &haystack, const std::string &needle, size_t pos = 0) {
|
||||
if (needle.empty() || pos >= haystack.length()) {
|
||||
return std::string::npos;
|
||||
}
|
||||
|
||||
for (size_t i = pos; i <= haystack.length() - needle.length(); i++) {
|
||||
bool match = true;
|
||||
for (size_t j = 0; j < needle.length(); j++) {
|
||||
if (tolower(haystack[i + j]) != tolower(needle[j])) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return std::string::npos;
|
||||
}
|
||||
|
||||
// Extract a parameter value from a header line
|
||||
// Handles both quoted and unquoted values
|
||||
inline std::string extract_header_param(const std::string &header, const std::string ¶m) {
|
||||
size_t search_pos = 0;
|
||||
|
||||
while (search_pos < header.length()) {
|
||||
// Look for param name
|
||||
size_t pos = str_find_case_insensitive(header, param, search_pos);
|
||||
if (pos == std::string::npos) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Check if this is a word boundary (not part of another parameter)
|
||||
if (pos > 0 && header[pos - 1] != ' ' && header[pos - 1] != ';' && header[pos - 1] != '\t') {
|
||||
search_pos = pos + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Move past param name
|
||||
pos += param.length();
|
||||
|
||||
// Skip whitespace and find '='
|
||||
while (pos < header.length() && (header[pos] == ' ' || header[pos] == '\t')) {
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (pos >= header.length() || header[pos] != '=') {
|
||||
search_pos = pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
pos++; // Skip '='
|
||||
|
||||
// Skip whitespace after '='
|
||||
while (pos < header.length() && (header[pos] == ' ' || header[pos] == '\t')) {
|
||||
pos++;
|
||||
}
|
||||
|
||||
if (pos >= header.length()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Check if value is quoted
|
||||
if (header[pos] == '"') {
|
||||
pos++;
|
||||
size_t end = header.find('"', pos);
|
||||
if (end != std::string::npos) {
|
||||
return header.substr(pos, end - pos);
|
||||
}
|
||||
// Malformed - no closing quote
|
||||
return "";
|
||||
}
|
||||
|
||||
// Unquoted value - find the end (semicolon, comma, or end of string)
|
||||
size_t end = pos;
|
||||
while (end < header.length() && header[end] != ';' && header[end] != ',' && header[end] != ' ' &&
|
||||
header[end] != '\t') {
|
||||
end++;
|
||||
}
|
||||
|
||||
return header.substr(pos, end - pos);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace web_server_idf
|
||||
} // namespace esphome
|
||||
#endif // USE_WEBSERVER_OTA
|
||||
#endif // USE_ESP_IDF
|
Loading…
x
Reference in New Issue
Block a user