// // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_HTTP_IMPL_FIELD_IPP #define BOOST_BEAST_HTTP_IMPL_FIELD_IPP #include #include #include #include #include namespace boost { namespace beast { namespace http { namespace detail { struct field_table { using array_type = std::array; // Strings are converted to lowercase static std::uint32_t digest(string_view s) { std::uint32_t r = 0; std::size_t n = s.size(); unsigned char const* p =reinterpret_cast< unsigned char const*>(s.data()); while(n >= 4) { std::uint32_t v; std::memcpy(&v, p, 4); r = r * 5 + ( v | 0x20202020 ); p += 4; n -= 4; } while( n > 0 ) { r = r * 5 + ( *p | 0x20 ); ++p; --n; } return r; } // This comparison is case-insensitive, and the // strings must contain only valid http field characters. static bool equals(string_view lhs, string_view rhs) { using Int = std::uint32_t; // or std::size_t auto n = lhs.size(); if(n != rhs.size()) return false; auto p1 = lhs.data(); auto p2 = rhs.data(); auto constexpr S = sizeof(Int); auto constexpr Mask = static_cast( 0xDFDFDFDFDFDFDFDF & ~Int{0}); for(; n >= S; p1 += S, p2 += S, n -= S) { Int v1, v2; std::memcpy( &v1, p1, S ); std::memcpy( &v2, p2, S ); if((v1 ^ v2) & Mask) return false; } for(; n; ++p1, ++p2, --n) if(( *p1 ^ *p2) & 0xDF) return false; return true; } array_type by_name_; enum { N = 5155 }; unsigned char map_[ N ][ 2 ] = {}; /* From: https://www.iana.org/assignments/message-headers/message-headers.xhtml */ field_table() : by_name_({{ "", "A-IM", "Accept", "Accept-Additions", "Accept-Charset", "Accept-Datetime", "Accept-Encoding", "Accept-Features", "Accept-Language", "Accept-Patch", "Accept-Post", "Accept-Ranges", "Access-Control", "Access-Control-Allow-Credentials", "Access-Control-Allow-Headers", "Access-Control-Allow-Methods", "Access-Control-Allow-Origin", "Access-Control-Expose-Headers", "Access-Control-Max-Age", "Access-Control-Request-Headers", "Access-Control-Request-Method", "Age", "Allow", "ALPN", "Also-Control", "Alt-Svc", "Alt-Used", "Alternate-Recipient", "Alternates", "Apparently-To", "Apply-To-Redirect-Ref", "Approved", "Archive", "Archived-At", "Article-Names", "Article-Updates", "Authentication-Control", "Authentication-Info", "Authentication-Results", "Authorization", "Auto-Submitted", "Autoforwarded", "Autosubmitted", "Base", "Bcc", "Body", "C-Ext", "C-Man", "C-Opt", "C-PEP", "C-PEP-Info", "Cache-Control", "CalDAV-Timezones", "Cancel-Key", "Cancel-Lock", "Cc", "Close", "Comments", "Compliance", "Connection", "Content-Alternative", "Content-Base", "Content-Description", "Content-Disposition", "Content-Duration", "Content-Encoding", "Content-features", "Content-ID", "Content-Identifier", "Content-Language", "Content-Length", "Content-Location", "Content-MD5", "Content-Range", "Content-Return", "Content-Script-Type", "Content-Style-Type", "Content-Transfer-Encoding", "Content-Type", "Content-Version", "Control", "Conversion", "Conversion-With-Loss", "Cookie", "Cookie2", "Cost", "DASL", "Date", "Date-Received", "DAV", "Default-Style", "Deferred-Delivery", "Delivery-Date", "Delta-Base", "Depth", "Derived-From", "Destination", "Differential-ID", "Digest", "Discarded-X400-IPMS-Extensions", "Discarded-X400-MTS-Extensions", "Disclose-Recipients", "Disposition-Notification-Options", "Disposition-Notification-To", "Distribution", "DKIM-Signature", "DL-Expansion-History", "Downgraded-Bcc", "Downgraded-Cc", "Downgraded-Disposition-Notification-To", "Downgraded-Final-Recipient", "Downgraded-From", "Downgraded-In-Reply-To", "Downgraded-Mail-From", "Downgraded-Message-Id", "Downgraded-Original-Recipient", "Downgraded-Rcpt-To", "Downgraded-References", "Downgraded-Reply-To", "Downgraded-Resent-Bcc", "Downgraded-Resent-Cc", "Downgraded-Resent-From", "Downgraded-Resent-Reply-To", "Downgraded-Resent-Sender", "Downgraded-Resent-To", "Downgraded-Return-Path", "Downgraded-Sender", "Downgraded-To", "EDIINT-Features", "Eesst-Version", "Encoding", "Encrypted", "Errors-To", "ETag", "Expect", "Expires", "Expiry-Date", "Ext", "Followup-To", "Forwarded", "From", "Generate-Delivery-Report", "GetProfile", "Hobareg", "Host", "HTTP2-Settings", "If", "If-Match", "If-Modified-Since", "If-None-Match", "If-Range", "If-Schedule-Tag-Match", "If-Unmodified-Since", "IM", "Importance", "In-Reply-To", "Incomplete-Copy", "Injection-Date", "Injection-Info", "Jabber-ID", "Keep-Alive", "Keywords", "Label", "Language", "Last-Modified", "Latest-Delivery-Time", "Lines", "Link", "List-Archive", "List-Help", "List-ID", "List-Owner", "List-Post", "List-Subscribe", "List-Unsubscribe", "List-Unsubscribe-Post", "Location", "Lock-Token", "Man", "Max-Forwards", "Memento-Datetime", "Message-Context", "Message-ID", "Message-Type", "Meter", "Method-Check", "Method-Check-Expires", "MIME-Version", "MMHS-Acp127-Message-Identifier", "MMHS-Authorizing-Users", "MMHS-Codress-Message-Indicator", "MMHS-Copy-Precedence", "MMHS-Exempted-Address", "MMHS-Extended-Authorisation-Info", "MMHS-Handling-Instructions", "MMHS-Message-Instructions", "MMHS-Message-Type", "MMHS-Originator-PLAD", "MMHS-Originator-Reference", "MMHS-Other-Recipients-Indicator-CC", "MMHS-Other-Recipients-Indicator-To", "MMHS-Primary-Precedence", "MMHS-Subject-Indicator-Codes", "MT-Priority", "Negotiate", "Newsgroups", "NNTP-Posting-Date", "NNTP-Posting-Host", "Non-Compliance", "Obsoletes", "Opt", "Optional", "Optional-WWW-Authenticate", "Ordering-Type", "Organization", "Origin", "Original-Encoded-Information-Types", "Original-From", "Original-Message-ID", "Original-Recipient", "Original-Sender", "Original-Subject", "Originator-Return-Address", "Overwrite", "P3P", "Path", "PEP", "Pep-Info", "PICS-Label", "Position", "Posting-Version", "Pragma", "Prefer", "Preference-Applied", "Prevent-NonDelivery-Report", "Priority", "Privicon", "ProfileObject", "Protocol", "Protocol-Info", "Protocol-Query", "Protocol-Request", "Proxy-Authenticate", "Proxy-Authentication-Info", "Proxy-Authorization", "Proxy-Connection", "Proxy-Features", "Proxy-Instruction", "Public", "Public-Key-Pins", "Public-Key-Pins-Report-Only", "Range", "Received", "Received-SPF", "Redirect-Ref", "References", "Referer", "Referer-Root", "Relay-Version", "Reply-By", "Reply-To", "Require-Recipient-Valid-Since", "Resent-Bcc", "Resent-Cc", "Resent-Date", "Resent-From", "Resent-Message-ID", "Resent-Reply-To", "Resent-Sender", "Resent-To", "Resolution-Hint", "Resolver-Location", "Retry-After", "Return-Path", "Safe", "Schedule-Reply", "Schedule-Tag", "Sec-WebSocket-Accept", "Sec-WebSocket-Extensions", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol", "Sec-WebSocket-Version", "Security-Scheme", "See-Also", "Sender", "Sensitivity", "Server", "Set-Cookie", "Set-Cookie2", "SetProfile", "SIO-Label", "SIO-Label-History", "SLUG", "SoapAction", "Solicitation", "Status-URI", "Strict-Transport-Security", "Subject", "SubOK", "Subst", "Summary", "Supersedes", "Surrogate-Capability", "Surrogate-Control", "TCN", "TE", "Timeout", "Title", "To", "Topic", "Trailer", "Transfer-Encoding", "TTL", "UA-Color", "UA-Media", "UA-Pixels", "UA-Resolution", "UA-Windowpixels", "Upgrade", "Urgency", "URI", "User-Agent", "Variant-Vary", "Vary", "VBR-Info", "Version", "Via", "Want-Digest", "Warning", "WWW-Authenticate", "X-Archived-At", "X-Device-Accept", "X-Device-Accept-Charset", "X-Device-Accept-Encoding", "X-Device-Accept-Language", "X-Device-User-Agent", "X-Frame-Options", "X-Mittente", "X-PGP-Sig", "X-Ricevuta", "X-Riferimento-Message-ID", "X-TipoRicevuta", "X-Trasporto", "X-VerificaSicurezza", "X400-Content-Identifier", "X400-Content-Return", "X400-Content-Type", "X400-MTS-Identifier", "X400-Originator", "X400-Received", "X400-Recipients", "X400-Trace", "Xref" }}) { for(std::size_t i = 1, n = 256; i < n; ++i) { auto sv = by_name_[ i ]; auto h = digest(sv); auto j = h % N; BOOST_ASSERT(map_[j][0] == 0); map_[j][0] = static_cast(i); } for(std::size_t i = 256, n = by_name_.size(); i < n; ++i) { auto sv = by_name_[i]; auto h = digest(sv); auto j = h % N; BOOST_ASSERT(map_[j][1] == 0); map_[j][1] = static_cast(i - 255); } } field string_to_field(string_view s) const { auto h = digest(s); auto j = h % N; int i = map_[j][0]; string_view s2 = by_name_[i]; if(i != 0 && equals(s, s2)) return static_cast(i); i = map_[j][1]; if(i == 0) return field::unknown; i += 255; s2 = by_name_[i]; if(equals(s, s2)) return static_cast(i); return field::unknown; } // // Deprecated // using const_iterator = array_type::const_iterator; std::size_t size() const { return by_name_.size(); } const_iterator begin() const { return by_name_.begin(); } const_iterator end() const { return by_name_.end(); } }; BOOST_BEAST_DECL field_table const& get_field_table() { static field_table const tab; return tab; } BOOST_BEAST_DECL string_view to_string(field f) { auto const& v = get_field_table(); BOOST_ASSERT(static_cast(f) < v.size()); return v.begin()[static_cast(f)]; } } // detail string_view to_string(field f) { return detail::to_string(f); } field string_to_field(string_view s) { return detail::get_field_table().string_to_field(s); } } // http } // beast } // boost #endif