diff --git a/include/crow/multipart.h b/include/crow/multipart.h index 24040c962..aed1be407 100644 --- a/include/crow/multipart.h +++ b/include/crow/multipart.h @@ -177,27 +177,63 @@ namespace crow void parse_body(std::string body) { - std::string delimiter = dd + boundary; + std::string normal_delim = dd + boundary; + std::string final_delim = normal_delim + dd; // Create final delimiter to check against + + bool is_final = false; // Create check for if final delimiter has been reached - // TODO(EDev): Exit on error - while (body != (crlf)) + while (!is_final) { - size_t found = body.find(delimiter); - if (found == std::string::npos) + // Find next regular and final delimiter + size_t next_normal = body.find(normal_delim); + size_t next_final = body.find(final_delim); + + // Use the first boundary that appears + size_t found; + + // If first boundary is final boundary, set is_final to true. + // Break ties between final and normal delimiter location by assigning priority to final + // This prevents treating final delim as a normal and then iterating again and producing an error + if (next_final != std::string::npos && (next_normal == std::string::npos || next_final <= next_normal)) + { + found = next_final; + is_final = true; + } + + else if (next_normal != std::string::npos) + { + found = next_normal; + } + else { - // did not find delimiter; probably an ill-formed body; throw to indicate the issue to user throw bad_request("Unable to find delimiter in multipart message. Probably ill-formed body"); } + + // Extract the section before the boundary std::string section = body.substr(0, found); + body.erase(0, found); + + // Remove the matched delimiter + if (is_final) + { + body.erase(0, final_delim.length()); + } + else + { + body.erase(0, normal_delim.length()); + } + + // Strip CRLF if present + if (body.compare(0, 2, crlf) == 0) + { + body.erase(0, 2); + } - // +2 is the CRLF. - // We don't check it and delete it so that the same delimiter can be used for The last delimiter (--delimiter--CRLF). - body.erase(0, found + delimiter.length() + 2); if (!section.empty()) { part parsed_section(parse_section(section)); part_map.emplace( - (get_header_object(parsed_section.headers, "Content-Disposition").params.find("name")->second), + get_header_object(parsed_section.headers, "Content-Disposition").params.at("name"), parsed_section); parts.push_back(std::move(parsed_section)); }