field.ipp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_HTTP_IMPL_FIELD_IPP
  10. #define BOOST_BEAST_HTTP_IMPL_FIELD_IPP
  11. #include <boost/beast/http/field.hpp>
  12. #include <boost/assert.hpp>
  13. #include <algorithm>
  14. #include <array>
  15. #include <cstring>
  16. #include <ostream>
  17. namespace boost {
  18. namespace beast {
  19. namespace http {
  20. namespace detail {
  21. struct field_table
  22. {
  23. static
  24. std::uint32_t
  25. get_chars(
  26. unsigned char const* p) noexcept
  27. {
  28. // VFALCO memcpy is endian-dependent
  29. //std::memcpy(&v, p, 4);
  30. // Compiler should be smart enough to
  31. // optimize this down to one instruction.
  32. return
  33. p[0] |
  34. (p[1] << 8) |
  35. (p[2] << 16) |
  36. (p[3] << 24);
  37. }
  38. using array_type =
  39. std::array<string_view, 357>;
  40. // Strings are converted to lowercase
  41. static
  42. std::uint32_t
  43. digest(string_view s)
  44. {
  45. std::uint32_t r = 0;
  46. std::size_t n = s.size();
  47. auto p = reinterpret_cast<
  48. unsigned char const*>(s.data());
  49. // consume N characters at a time
  50. // VFALCO Can we do 8 on 64-bit systems?
  51. while(n >= 4)
  52. {
  53. auto const v = get_chars(p);
  54. r = (r * 5 + (
  55. v | 0x20202020 )); // convert to lower
  56. p += 4;
  57. n -= 4;
  58. }
  59. // handle remaining characters
  60. while( n > 0 )
  61. {
  62. r = r * 5 + ( *p | 0x20 );
  63. ++p;
  64. --n;
  65. }
  66. return r;
  67. }
  68. // This comparison is case-insensitive, and the
  69. // strings must contain only valid http field characters.
  70. static
  71. bool
  72. equals(string_view lhs, string_view rhs)
  73. {
  74. using Int = std::uint32_t; // VFALCO std::size_t?
  75. auto n = lhs.size();
  76. if(n != rhs.size())
  77. return false;
  78. auto p1 = reinterpret_cast<
  79. unsigned char const*>(lhs.data());
  80. auto p2 = reinterpret_cast<
  81. unsigned char const*>(rhs.data());
  82. auto constexpr S = sizeof(Int);
  83. auto constexpr Mask = static_cast<Int>(
  84. 0xDFDFDFDFDFDFDFDF & ~Int{0});
  85. for(; n >= S; p1 += S, p2 += S, n -= S)
  86. {
  87. Int const v1 = get_chars(p1);
  88. Int const v2 = get_chars(p2);
  89. if((v1 ^ v2) & Mask)
  90. return false;
  91. }
  92. for(; n; ++p1, ++p2, --n)
  93. if(( *p1 ^ *p2) & 0xDF)
  94. return false;
  95. return true;
  96. }
  97. array_type by_name_;
  98. enum { N = 5155 };
  99. unsigned char map_[ N ][ 2 ] = {};
  100. /*
  101. From:
  102. https://www.iana.org/assignments/message-headers/message-headers.xhtml
  103. */
  104. field_table()
  105. : by_name_({{
  106. // string constants
  107. "<unknown-field>",
  108. "A-IM",
  109. "Accept",
  110. "Accept-Additions",
  111. "Accept-Charset",
  112. "Accept-Datetime",
  113. "Accept-Encoding",
  114. "Accept-Features",
  115. "Accept-Language",
  116. "Accept-Patch",
  117. "Accept-Post",
  118. "Accept-Ranges",
  119. "Access-Control",
  120. "Access-Control-Allow-Credentials",
  121. "Access-Control-Allow-Headers",
  122. "Access-Control-Allow-Methods",
  123. "Access-Control-Allow-Origin",
  124. "Access-Control-Expose-Headers",
  125. "Access-Control-Max-Age",
  126. "Access-Control-Request-Headers",
  127. "Access-Control-Request-Method",
  128. "Age",
  129. "Allow",
  130. "ALPN",
  131. "Also-Control",
  132. "Alt-Svc",
  133. "Alt-Used",
  134. "Alternate-Recipient",
  135. "Alternates",
  136. "Apparently-To",
  137. "Apply-To-Redirect-Ref",
  138. "Approved",
  139. "Archive",
  140. "Archived-At",
  141. "Article-Names",
  142. "Article-Updates",
  143. "Authentication-Control",
  144. "Authentication-Info",
  145. "Authentication-Results",
  146. "Authorization",
  147. "Auto-Submitted",
  148. "Autoforwarded",
  149. "Autosubmitted",
  150. "Base",
  151. "Bcc",
  152. "Body",
  153. "C-Ext",
  154. "C-Man",
  155. "C-Opt",
  156. "C-PEP",
  157. "C-PEP-Info",
  158. "Cache-Control",
  159. "CalDAV-Timezones",
  160. "Cancel-Key",
  161. "Cancel-Lock",
  162. "Cc",
  163. "Close",
  164. "Comments",
  165. "Compliance",
  166. "Connection",
  167. "Content-Alternative",
  168. "Content-Base",
  169. "Content-Description",
  170. "Content-Disposition",
  171. "Content-Duration",
  172. "Content-Encoding",
  173. "Content-features",
  174. "Content-ID",
  175. "Content-Identifier",
  176. "Content-Language",
  177. "Content-Length",
  178. "Content-Location",
  179. "Content-MD5",
  180. "Content-Range",
  181. "Content-Return",
  182. "Content-Script-Type",
  183. "Content-Style-Type",
  184. "Content-Transfer-Encoding",
  185. "Content-Type",
  186. "Content-Version",
  187. "Control",
  188. "Conversion",
  189. "Conversion-With-Loss",
  190. "Cookie",
  191. "Cookie2",
  192. "Cost",
  193. "DASL",
  194. "Date",
  195. "Date-Received",
  196. "DAV",
  197. "Default-Style",
  198. "Deferred-Delivery",
  199. "Delivery-Date",
  200. "Delta-Base",
  201. "Depth",
  202. "Derived-From",
  203. "Destination",
  204. "Differential-ID",
  205. "Digest",
  206. "Discarded-X400-IPMS-Extensions",
  207. "Discarded-X400-MTS-Extensions",
  208. "Disclose-Recipients",
  209. "Disposition-Notification-Options",
  210. "Disposition-Notification-To",
  211. "Distribution",
  212. "DKIM-Signature",
  213. "DL-Expansion-History",
  214. "Downgraded-Bcc",
  215. "Downgraded-Cc",
  216. "Downgraded-Disposition-Notification-To",
  217. "Downgraded-Final-Recipient",
  218. "Downgraded-From",
  219. "Downgraded-In-Reply-To",
  220. "Downgraded-Mail-From",
  221. "Downgraded-Message-Id",
  222. "Downgraded-Original-Recipient",
  223. "Downgraded-Rcpt-To",
  224. "Downgraded-References",
  225. "Downgraded-Reply-To",
  226. "Downgraded-Resent-Bcc",
  227. "Downgraded-Resent-Cc",
  228. "Downgraded-Resent-From",
  229. "Downgraded-Resent-Reply-To",
  230. "Downgraded-Resent-Sender",
  231. "Downgraded-Resent-To",
  232. "Downgraded-Return-Path",
  233. "Downgraded-Sender",
  234. "Downgraded-To",
  235. "EDIINT-Features",
  236. "Eesst-Version",
  237. "Encoding",
  238. "Encrypted",
  239. "Errors-To",
  240. "ETag",
  241. "Expect",
  242. "Expires",
  243. "Expiry-Date",
  244. "Ext",
  245. "Followup-To",
  246. "Forwarded",
  247. "From",
  248. "Generate-Delivery-Report",
  249. "GetProfile",
  250. "Hobareg",
  251. "Host",
  252. "HTTP2-Settings",
  253. "If",
  254. "If-Match",
  255. "If-Modified-Since",
  256. "If-None-Match",
  257. "If-Range",
  258. "If-Schedule-Tag-Match",
  259. "If-Unmodified-Since",
  260. "IM",
  261. "Importance",
  262. "In-Reply-To",
  263. "Incomplete-Copy",
  264. "Injection-Date",
  265. "Injection-Info",
  266. "Jabber-ID",
  267. "Keep-Alive",
  268. "Keywords",
  269. "Label",
  270. "Language",
  271. "Last-Modified",
  272. "Latest-Delivery-Time",
  273. "Lines",
  274. "Link",
  275. "List-Archive",
  276. "List-Help",
  277. "List-ID",
  278. "List-Owner",
  279. "List-Post",
  280. "List-Subscribe",
  281. "List-Unsubscribe",
  282. "List-Unsubscribe-Post",
  283. "Location",
  284. "Lock-Token",
  285. "Man",
  286. "Max-Forwards",
  287. "Memento-Datetime",
  288. "Message-Context",
  289. "Message-ID",
  290. "Message-Type",
  291. "Meter",
  292. "Method-Check",
  293. "Method-Check-Expires",
  294. "MIME-Version",
  295. "MMHS-Acp127-Message-Identifier",
  296. "MMHS-Authorizing-Users",
  297. "MMHS-Codress-Message-Indicator",
  298. "MMHS-Copy-Precedence",
  299. "MMHS-Exempted-Address",
  300. "MMHS-Extended-Authorisation-Info",
  301. "MMHS-Handling-Instructions",
  302. "MMHS-Message-Instructions",
  303. "MMHS-Message-Type",
  304. "MMHS-Originator-PLAD",
  305. "MMHS-Originator-Reference",
  306. "MMHS-Other-Recipients-Indicator-CC",
  307. "MMHS-Other-Recipients-Indicator-To",
  308. "MMHS-Primary-Precedence",
  309. "MMHS-Subject-Indicator-Codes",
  310. "MT-Priority",
  311. "Negotiate",
  312. "Newsgroups",
  313. "NNTP-Posting-Date",
  314. "NNTP-Posting-Host",
  315. "Non-Compliance",
  316. "Obsoletes",
  317. "Opt",
  318. "Optional",
  319. "Optional-WWW-Authenticate",
  320. "Ordering-Type",
  321. "Organization",
  322. "Origin",
  323. "Original-Encoded-Information-Types",
  324. "Original-From",
  325. "Original-Message-ID",
  326. "Original-Recipient",
  327. "Original-Sender",
  328. "Original-Subject",
  329. "Originator-Return-Address",
  330. "Overwrite",
  331. "P3P",
  332. "Path",
  333. "PEP",
  334. "Pep-Info",
  335. "PICS-Label",
  336. "Position",
  337. "Posting-Version",
  338. "Pragma",
  339. "Prefer",
  340. "Preference-Applied",
  341. "Prevent-NonDelivery-Report",
  342. "Priority",
  343. "Privicon",
  344. "ProfileObject",
  345. "Protocol",
  346. "Protocol-Info",
  347. "Protocol-Query",
  348. "Protocol-Request",
  349. "Proxy-Authenticate",
  350. "Proxy-Authentication-Info",
  351. "Proxy-Authorization",
  352. "Proxy-Connection",
  353. "Proxy-Features",
  354. "Proxy-Instruction",
  355. "Public",
  356. "Public-Key-Pins",
  357. "Public-Key-Pins-Report-Only",
  358. "Range",
  359. "Received",
  360. "Received-SPF",
  361. "Redirect-Ref",
  362. "References",
  363. "Referer",
  364. "Referer-Root",
  365. "Relay-Version",
  366. "Reply-By",
  367. "Reply-To",
  368. "Require-Recipient-Valid-Since",
  369. "Resent-Bcc",
  370. "Resent-Cc",
  371. "Resent-Date",
  372. "Resent-From",
  373. "Resent-Message-ID",
  374. "Resent-Reply-To",
  375. "Resent-Sender",
  376. "Resent-To",
  377. "Resolution-Hint",
  378. "Resolver-Location",
  379. "Retry-After",
  380. "Return-Path",
  381. "Safe",
  382. "Schedule-Reply",
  383. "Schedule-Tag",
  384. "Sec-Fetch-Dest",
  385. "Sec-Fetch-Mode",
  386. "Sec-Fetch-Site",
  387. "Sec-Fetch-User",
  388. "Sec-WebSocket-Accept",
  389. "Sec-WebSocket-Extensions",
  390. "Sec-WebSocket-Key",
  391. "Sec-WebSocket-Protocol",
  392. "Sec-WebSocket-Version",
  393. "Security-Scheme",
  394. "See-Also",
  395. "Sender",
  396. "Sensitivity",
  397. "Server",
  398. "Set-Cookie",
  399. "Set-Cookie2",
  400. "SetProfile",
  401. "SIO-Label",
  402. "SIO-Label-History",
  403. "SLUG",
  404. "SoapAction",
  405. "Solicitation",
  406. "Status-URI",
  407. "Strict-Transport-Security",
  408. "Subject",
  409. "SubOK",
  410. "Subst",
  411. "Summary",
  412. "Supersedes",
  413. "Surrogate-Capability",
  414. "Surrogate-Control",
  415. "TCN",
  416. "TE",
  417. "Timeout",
  418. "Title",
  419. "To",
  420. "Topic",
  421. "Trailer",
  422. "Transfer-Encoding",
  423. "TTL",
  424. "UA-Color",
  425. "UA-Media",
  426. "UA-Pixels",
  427. "UA-Resolution",
  428. "UA-Windowpixels",
  429. "Upgrade",
  430. "Urgency",
  431. "URI",
  432. "User-Agent",
  433. "Variant-Vary",
  434. "Vary",
  435. "VBR-Info",
  436. "Version",
  437. "Via",
  438. "Want-Digest",
  439. "Warning",
  440. "WWW-Authenticate",
  441. "X-Archived-At",
  442. "X-Device-Accept",
  443. "X-Device-Accept-Charset",
  444. "X-Device-Accept-Encoding",
  445. "X-Device-Accept-Language",
  446. "X-Device-User-Agent",
  447. "X-Frame-Options",
  448. "X-Mittente",
  449. "X-PGP-Sig",
  450. "X-Ricevuta",
  451. "X-Riferimento-Message-ID",
  452. "X-TipoRicevuta",
  453. "X-Trasporto",
  454. "X-VerificaSicurezza",
  455. "X400-Content-Identifier",
  456. "X400-Content-Return",
  457. "X400-Content-Type",
  458. "X400-MTS-Identifier",
  459. "X400-Originator",
  460. "X400-Received",
  461. "X400-Recipients",
  462. "X400-Trace",
  463. "Xref"
  464. }})
  465. {
  466. for(std::size_t i = 1, n = 256; i < n; ++i)
  467. {
  468. auto sv = by_name_[ i ];
  469. auto h = digest(sv);
  470. auto j = h % N;
  471. BOOST_ASSERT(map_[j][0] == 0);
  472. map_[j][0] = static_cast<unsigned char>(i);
  473. }
  474. for(std::size_t i = 256, n = by_name_.size(); i < n; ++i)
  475. {
  476. auto sv = by_name_[i];
  477. auto h = digest(sv);
  478. auto j = h % N;
  479. BOOST_ASSERT(map_[j][1] == 0);
  480. map_[j][1] = static_cast<unsigned char>(i - 255);
  481. }
  482. }
  483. field
  484. string_to_field(string_view s) const
  485. {
  486. auto h = digest(s);
  487. auto j = h % N;
  488. int i = map_[j][0];
  489. string_view s2 = by_name_[i];
  490. if(i != 0 && equals(s, s2))
  491. return static_cast<field>(i);
  492. i = map_[j][1];
  493. if(i == 0)
  494. return field::unknown;
  495. i += 255;
  496. s2 = by_name_[i];
  497. if(equals(s, s2))
  498. return static_cast<field>(i);
  499. return field::unknown;
  500. }
  501. //
  502. // Deprecated
  503. //
  504. using const_iterator =
  505. array_type::const_iterator;
  506. std::size_t
  507. size() const
  508. {
  509. return by_name_.size();
  510. }
  511. const_iterator
  512. begin() const
  513. {
  514. return by_name_.begin();
  515. }
  516. const_iterator
  517. end() const
  518. {
  519. return by_name_.end();
  520. }
  521. };
  522. BOOST_BEAST_DECL
  523. field_table const&
  524. get_field_table()
  525. {
  526. static field_table const tab;
  527. return tab;
  528. }
  529. BOOST_BEAST_DECL
  530. string_view
  531. to_string(field f)
  532. {
  533. auto const& v = get_field_table();
  534. BOOST_ASSERT(static_cast<unsigned>(f) < v.size());
  535. return v.begin()[static_cast<unsigned>(f)];
  536. }
  537. } // detail
  538. string_view
  539. to_string(field f)
  540. {
  541. return detail::to_string(f);
  542. }
  543. field
  544. string_to_field(string_view s)
  545. {
  546. return detail::get_field_table().string_to_field(s);
  547. }
  548. std::ostream&
  549. operator<<(std::ostream& os, field f)
  550. {
  551. return os << to_string(f);
  552. }
  553. } // http
  554. } // beast
  555. } // boost
  556. #endif