6#include <private/qoffsetstringarray_p.h>
8#include <QtCore/qcompare.h>
9#include <QtCore/qhash.h>
10#include <QtCore/qloggingcategory.h>
11#include <QtCore/qmap.h>
12#include <QtCore/qset.h>
13#include <QtCore/qttypetraits.h>
15#include <q20algorithm.h>
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
103 "access-control-allow-credentials",
104 "access-control-allow-headers",
105 "access-control-allow-methods",
106 "access-control-allow-origin",
107 "access-control-expose-headers",
108 "access-control-max-age",
109 "access-control-request-headers",
110 "access-control-request-method",
117 "apply-to-redirect-ref",
118 "authentication-control",
119 "authentication-info",
136 "content-disposition",
143 "content-security-policy",
144 "content-security-policy-report-only",
147 "cross-origin-embedder-policy",
148 "cross-origin-embedder-policy-report-only",
149 "cross-origin-opener-policy",
150 "cross-origin-opener-policy-report-only",
151 "cross-origin-resource-policy",
175 "if-schedule-tag-match",
176 "if-unmodified-since",
178 "include-referred-token-binding-id",
196 "optional-www-authenticate",
199 "origin-agent-cluster",
207 "preference-applied",
209 "proxy-authenticate",
210 "proxy-authentication-info",
211 "proxy-authorization",
214 "public-key-pins-report-only",
226 "sec-websocket-accept",
227 "sec-websocket-extensions",
229 "sec-websocket-protocol",
230 "sec-websocket-version",
239 "strict-transport-security",
241 "surrogate-capability",
258 "want-content-digest",
261 "x-content-type-options",
273struct ByIndirectHeaderName
275 constexpr bool operator()(quint8 lhs, quint8 rhs)
const noexcept
277 return (*
this)(map(lhs), map(rhs));
279 constexpr bool operator()(quint8 lhs, QByteArrayView rhs)
const noexcept
281 return (*
this)(map(lhs), rhs);
283 constexpr bool operator()(QByteArrayView lhs, quint8 rhs)
const noexcept
285 return (*
this)(lhs, map(rhs));
287 constexpr bool operator()(QByteArrayView lhs, QByteArrayView rhs)
const noexcept
290 return std::string_view(lhs) < std::string_view(rhs);
293 static constexpr QByteArrayView map(quint8 i)
noexcept
295 return headerNames.viewAt(i);
485static_assert(
std::size(orderedHeaderNameIndexes) == size_t(headerNames.count()));
486#if !defined(Q_CC_GNU_ONLY) || Q_CC_GNU_ONLY >= 1000
487static_assert(
q20::is_sorted(
std::begin(orderedHeaderNameIndexes),
488 std::end(orderedHeaderNameIndexes),
489 ByIndirectHeaderName{}));
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
679 return QByteArray(s.data(), s.size());
684 return QByteArray(s.data(), s.size());
694 return name.visit([](
auto name){
return fieldToByteArray(name); }).toLower();
705 auto nname = normalizedName(name);
706 if (
auto h = HeaderName::toWellKnownHeader(nname))
709 data = std::move(nname);
716 auto indexesBegin =
std::cbegin(orderedHeaderNameIndexes);
717 auto indexesEnd =
std::cend(orderedHeaderNameIndexes);
719 auto result =
std::lower_bound(indexesBegin, indexesEnd, name, ByIndirectHeaderName{});
721 if (result != indexesEnd && name == headerNames[*result])
722 return static_cast<QHttpHeaders::WellKnownHeader>(*result);
728 return std::visit([](
const auto &arg) -> QByteArrayView {
729 using T =
decltype(arg);
730 if constexpr (std::is_same_v<T,
const QByteArray &>)
732 else if constexpr (std::is_same_v<T,
const QHttpHeaders::WellKnownHeader &>)
733 return headerNames.viewAt(qToUnderlying(arg));
735 static_assert(QtPrivate::type_dependent_false<T>());
741 return std::visit([](
const auto &arg) -> QByteArray {
742 using T =
decltype(arg);
743 if constexpr (std::is_same_v<T,
const QByteArray &>) {
745 }
else if constexpr (std::is_same_v<T,
const QHttpHeaders::WellKnownHeader &>) {
746 const auto view = headerNames.viewAt(qToUnderlying(arg));
747 return QByteArray::fromRawData(view.constData(), view.size());
749 static_assert(QtPrivate::type_dependent_false<T>());
756 std::variant<QHttpHeaders::WellKnownHeader, QByteArray> data;
765 return lhs.data == rhs.data;
782 return [&name](
const Header &header) {
return header.name == name; };
803QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QHttpHeadersPrivate)
804template <>
void QExplicitlySharedDataPointer<QHttpHeadersPrivate>::detach()
807 d.reset(
new QHttpHeadersPrivate());
809 }
else if (d->ref.loadRelaxed() != 1) {
818 if (it != d->headers.cend()) {
820 const auto matchOffset = it - d->headers.cbegin();
823 d->headers.erase(
std::remove_if(d->headers.begin() + matchOffset, d->headers.end(),
831 const char* separator =
"";
832 for (
const auto &h : std::as_const(headers)) {
833 if (h.name == name) {
834 result.append(separator);
835 result.append(h.value);
843 for (
const auto &h : std::as_const(headers)) {
845 result.append(h.value);
851 for (
const auto &h : std::as_const(headers)) {
862 if (it != d->headers.end()) {
871 d->headers.append(
Header{name, value});
876
877
883
884
885
886
887
891 h.reserve(headers.size());
892 for (
const auto &header : headers)
893 h.append(header.first, header.second);
898
899
900
901
902
906 h.reserve(headers.size());
907 for (
const auto &[name,value] : headers.asKeyValueRange())
908 h.append(name, value);
913
914
915
916
917
921 h.reserve(headers.size());
922 for (
const auto &[name,value] : headers.asKeyValueRange())
923 h.append(name, value);
928
929
934
935
940
941
946
947
948
949
950
953
954
955
956
957
958
961
962
963
965#ifndef QT_NO_DEBUG_STREAM
967
968
969
970
971
974 const QDebugStateSaver saver(debug);
975 debug.resetFormat().nospace();
977 debug <<
"QHttpHeaders(";
979 debug <<
"headers = ";
980 const char *separator =
"";
981 for (
const auto &h : headers.d->headers) {
982 debug << separator << h.name.asView() <<
':' << h.value;
1001 return ((
'A' <= c && c <=
'Z')
1002 || (
'a' <= c && c <=
'z')
1003 || (
'0' <= c && c <=
'9')
1004 || (
'#' <= c && c <=
'\'')
1005 || (
'^' <= c && c <=
'`')
1006 || c ==
'|' || c ==
'~' || c ==
'!' || c ==
'*' || c ==
'+' || c ==
'-' || c ==
'.');
1019 return headerNameValidImpl(QLatin1StringView(QByteArrayView(name)));
1024 return std::all_of(name.begin(), name.end(), [](QChar c) {
1025 return isValidHttpHeaderNameChar(c.toLatin1());
1031 if (name.isEmpty()) {
1032 qCWarning(lcQHttpHeaders,
"HTTP header name cannot be empty");
1035 const bool valid = name.visit([](
auto name){
return headerNameValidImpl(name); });
1037 qCWarning(lcQHttpHeaders,
"HTTP header name contained illegal character(s)");
1054 || (0x20 <= c && c <= 0x7E)
1074 return std::all_of(value.begin(), value.end(), [](QChar c) {
1075 return isValidHttpHeaderValueChar(c.toLatin1());
1081 const bool valid = value.visit([](
auto value){
return headerValueValidImpl(value); });
1083 qCWarning(lcQHttpHeaders,
"HTTP header value contained illegal character(s)");
1095 return value.visit([](
auto value){
return fieldToByteArray(value); }).trimmed();
1099
1100
1101
1102
1103
1104
1107 if (!isValidHttpHeaderNameField(name) || !isValidHttpHeaderValueField(value))
1111 d->headers.push_back({HeaderName{name}, normalizedValue(value)});
1116
1117
1120 if (!isValidHttpHeaderValueField(value))
1124 d->headers.push_back({HeaderName{name}, normalizedValue(value)});
1129
1130
1131
1132
1133
1134
1135
1139 if (!isValidHttpHeaderNameField(name) || !isValidHttpHeaderValueField(value))
1143 d->headers.insert(i, {HeaderName{name}, normalizedValue(value)});
1148
1149
1153 if (!isValidHttpHeaderValueField(value))
1157 d->headers.insert(i, {HeaderName{name}, normalizedValue(value)});
1162
1163
1164
1165
1166
1167
1168
1169
1173 if (!isValidHttpHeaderNameField(name) || !isValidHttpHeaderValueField(newValue))
1177 d->headers.replace(i, {HeaderName{name}, normalizedValue(newValue)});
1182
1183
1187 if (!isValidHttpHeaderValueField(newValue))
1191 d->headers.replace(i, {HeaderName{name}, normalizedValue(newValue)});
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1212 return append(name, newValue);
1214 if (!isValidHttpHeaderValueField(newValue))
1217 QHttpHeadersPrivate::replaceOrAppend(d, HeaderName{name}, normalizedValue(newValue));
1222
1223
1227 return append(name, newValue);
1229 if (!isValidHttpHeaderNameField(name) || !isValidHttpHeaderValueField(newValue))
1232 QHttpHeadersPrivate::replaceOrAppend(d, HeaderName{name}, normalizedValue(newValue));
1237
1238
1239
1240
1246 return std::any_of(d->headers.cbegin(), d->headers.cend(), headerNameMatches(HeaderName{name}));
1250
1251
1257 return std::any_of(d->headers.cbegin(), d->headers.cend(), headerNameMatches(HeaderName{name}));
1261
1262
1263
1264
1270 return QHttpHeadersPrivate::removeAll(d, HeaderName(name));
1274
1275
1281 return QHttpHeadersPrivate::removeAll(d, HeaderName(name));
1285
1286
1287
1288
1289
1290
1295 d->headers.removeAt(i);
1299
1300
1301
1302
1303
1304QByteArrayView
QHttpHeaders::value(QAnyStringView name, QByteArrayView defaultValue)
const noexcept
1307 return defaultValue;
1309 return d->value(HeaderName{name}, defaultValue);
1313
1314
1315QByteArrayView
QHttpHeaders::value(WellKnownHeader name, QByteArrayView defaultValue)
const noexcept
1318 return defaultValue;
1320 return d->value(HeaderName{name}, defaultValue);
1324
1325
1326
1327
1328
1331 QList<QByteArray> result;
1335 d->values(HeaderName{name}, result);
1340
1341
1344 QList<QByteArray> result;
1348 d->values(HeaderName{name}, result);
1353
1354
1355
1356
1357
1361 return d->headers.at(i).value;
1365
1366
1367
1368
1369
1370
1371
1375 return QLatin1StringView{d->headers.at(i).name.asView()};
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1396 d->combinedValue(HeaderName{name}, result);
1401
1402
1409 d->combinedValue(HeaderName{name}, result);
1414
1415
1420 return d->headers.size();
1424
1425
1426
1427
1428
1429
1433 d->headers.reserve(size);
1437
1438
1439
1440
1441
1442
1445
1446
1447QByteArrayView
QHttpHeaders::wellKnownHeaderName(WellKnownHeader name)
noexcept
1449 return headerNames[qToUnderlying(name)];
1453
1454
1455
1456QList<std::pair<QByteArray, QByteArray>>
QHttpHeaders::toListOfPairs()
const
1458 QList<std::pair<QByteArray, QByteArray>> list;
1461 list.reserve(size());
1462 for (
const auto & h : std::as_const(d->headers))
1463 list.append({h.name.asByteArray(), h.value});
1468
1469
1470
1473 QMultiMap<QByteArray, QByteArray> map;
1476 for (
const auto &h : std::as_const(d->headers))
1477 map.insert(h.name.asByteArray(), h.value);
1482
1483
1484
1487 QMultiHash<QByteArray, QByteArray> hash;
1490 hash.reserve(size());
1491 for (
const auto &h : std::as_const(d->headers))
1492 hash.insert(h.name.asByteArray(), h.value);
1497
1498
1499
1500
Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core")