| 3967 | |
| 3968 | #ifdef CPPHTTPLIB_NO_EXCEPTIONS |
| 3969 | inline bool parse_range_header(const std::string &s, Ranges &ranges) { |
| 3970 | #else |
| 3971 | inline bool parse_range_header(const std::string &s, Ranges &ranges) try { |
| 3972 | #endif |
| 3973 | static auto re_first_range = std::regex(R"(bytes=(\d*-\d*(?:,\s*\d*-\d*)*))"); |
| 3974 | std::smatch m; |
| 3975 | if (std::regex_match(s, m, re_first_range)) { |
| 3976 | auto pos = static_cast<size_t>(m.position(1)); |
| 3977 | auto len = static_cast<size_t>(m.length(1)); |
| 3978 | bool all_valid_ranges = true; |
| 3979 | split(&s[pos], &s[pos + len], ',', [&](const char *b, const char *e) { |
| 3980 | if (!all_valid_ranges) return; |
| 3981 | static auto re_another_range = std::regex(R"(\s*(\d*)-(\d*))"); |
| 3982 | std::cmatch cm; |
| 3983 | if (std::regex_match(b, e, cm, re_another_range)) { |
| 3984 | ssize_t first = -1; |
| 3985 | if (!cm.str(1).empty()) { |
| 3986 | first = static_cast<ssize_t>(std::stoll(cm.str(1))); |
| 3987 | } |
| 3988 | |
| 3989 | ssize_t last = -1; |
| 3990 | if (!cm.str(2).empty()) { |
| 3991 | last = static_cast<ssize_t>(std::stoll(cm.str(2))); |
| 3992 | } |
| 3993 | |
| 3994 | if (first != -1 && last != -1 && first > last) { |
| 3995 | all_valid_ranges = false; |
| 3996 | return; |
| 3997 | } |
| 3998 | ranges.emplace_back(std::make_pair(first, last)); |
| 3999 | } |
| 4000 | }); |
| 4001 | return all_valid_ranges; |
| 4002 | } |
| 4003 | return false; |
| 4004 | #ifdef CPPHTTPLIB_NO_EXCEPTIONS |
| 4005 | } |
| 4006 | #else |
| 4007 | } catch (...) { return false; } |
| 4008 | #endif |
| 4009 | |
| 4010 | class MultipartFormDataParser { |
| 4011 | public: |
| 4012 | MultipartFormDataParser() = default; |
| 4013 | |
| 4014 | void set_boundary(std::string &&boundary) { |
| 4015 | boundary_ = boundary; |
| 4016 | dash_boundary_crlf_ = dash_ + boundary_ + crlf_; |
| 4017 | crlf_dash_boundary_ = crlf_ + dash_ + boundary_; |
| 4018 | } |
| 4019 | |
| 4020 | bool is_valid() const { return is_valid_; } |
| 4021 | |
| 4022 | bool parse(const char *buf, size_t n, const ContentReceiver &content_callback, |
| 4023 | const MultipartContentHeader &header_callback) { |
| 4024 | |
| 4025 | // TODO: support 'filename*' |
| 4026 | static const std::regex re_content_disposition( |
no test coverage detected