field.ipp 14 KB

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