| 3774 | bool is_valid() const { return is_valid_; } |
| 3775 | |
| 3776 | bool parse(const char *buf, size_t n, const ContentReceiver &content_callback, |
| 3777 | const MultipartContentHeader &header_callback) { |
| 3778 | |
| 3779 | // TODO: support 'filename*' |
| 3780 | static const std::regex re_content_disposition( |
| 3781 | R"~(^Content-Disposition:\s*form-data;\s*name="(.*?)"(?:;\s*filename="(.*?)")?(?:;\s*filename\*=\S+)?\s*$)~", |
| 3782 | std::regex_constants::icase); |
| 3783 | |
| 3784 | static const std::string dash_ = "--"; |
| 3785 | static const std::string crlf_ = "\r\n"; |
| 3786 | |
| 3787 | buf_append(buf, n); |
| 3788 | |
| 3789 | while (buf_size() > 0) { |
| 3790 | switch (state_) { |
| 3791 | case 0: { // Initial boundary |
| 3792 | auto pattern = dash_ + boundary_ + crlf_; |
| 3793 | if (pattern.size() > buf_size()) { return true; } |
| 3794 | if (!buf_start_with(pattern)) { return false; } |
| 3795 | buf_erase(pattern.size()); |
| 3796 | state_ = 1; |
| 3797 | break; |
| 3798 | } |
| 3799 | case 1: { // New entry |
| 3800 | clear_file_info(); |
| 3801 | state_ = 2; |
| 3802 | break; |
| 3803 | } |
| 3804 | case 2: { // Headers |
| 3805 | auto pos = buf_find(crlf_); |
| 3806 | if (pos > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } |
| 3807 | while (pos < buf_size()) { |
| 3808 | // Empty line |
| 3809 | if (pos == 0) { |
| 3810 | if (!header_callback(file_)) { |
| 3811 | is_valid_ = false; |
| 3812 | return false; |
| 3813 | } |
| 3814 | buf_erase(crlf_.size()); |
| 3815 | state_ = 3; |
| 3816 | break; |
| 3817 | } |
| 3818 | |
| 3819 | static const std::string header_name = "content-type:"; |
| 3820 | const auto header = buf_head(pos); |
| 3821 | if (start_with_case_ignore(header, header_name)) { |
| 3822 | file_.content_type = trim_copy(header.substr(header_name.size())); |
| 3823 | } else { |
| 3824 | std::smatch m; |
| 3825 | if (std::regex_match(header, m, re_content_disposition)) { |
| 3826 | file_.name = m[1]; |
| 3827 | file_.filename = m[2]; |
| 3828 | } |
| 3829 | } |
| 3830 | |
| 3831 | buf_erase(pos + crlf_.size()); |
| 3832 | pos = buf_find(crlf_); |
| 3833 | } |
no test coverage detected