]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/HttpStatus.cc
Bug 5428: Warn if pkg-config is not found (#1902)
[thirdparty/squid.git] / src / acl / HttpStatus.cc
1 /*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 28 Access Control */
10
11 #include "squid.h"
12 #include "acl/FilledChecklist.h"
13 #include "acl/HttpStatus.h"
14 #include "acl/SplayInserter.h"
15 #include "debug/Stream.h"
16 #include "HttpReply.h"
17
18 #include <algorithm>
19 #include <climits>
20
21 static void aclParseHTTPStatusList(Splay<acl_httpstatus_data *> **curlist);
22 static int aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b);
23 static int aclMatchHTTPStatus(Splay<acl_httpstatus_data*> **dataptr, Http::StatusCode status);
24
25 acl_httpstatus_data::acl_httpstatus_data(int x) : status1(x), status2(x) { ; }
26
27 acl_httpstatus_data::acl_httpstatus_data(int x, int y) : status1(x), status2(y) { ; }
28
29 SBuf
30 acl_httpstatus_data::toStr() const
31 {
32 SBuf rv;
33 if (status2 == INT_MAX)
34 rv.Printf("%d-", status1);
35 else if (status1 == status2)
36 rv.Printf("%d", status1);
37 else
38 rv.Printf("%d-%d", status1, status2);
39 return rv;
40 }
41
42 template <>
43 int
44 Acl::SplayInserter<acl_httpstatus_data*>::Compare(const Value &a, const Value &b)
45 {
46 return aclHTTPStatusCompare(a, b);
47 }
48
49 template <>
50 bool
51 Acl::SplayInserter<acl_httpstatus_data*>::IsSubset(const Value &a, const Value &b)
52 {
53 return b->status1 <= a->status1 && a->status2 <= b->status2;
54 }
55
56 template <>
57 Acl::SplayInserter<acl_httpstatus_data*>::Value
58 Acl::SplayInserter<acl_httpstatus_data*>::MakeCombinedValue(const Value &a, const Value &b)
59 {
60 const auto minLeft = std::min(a->status1, b->status1);
61 const auto maxRight = std::max(a->status2, b->status2);
62 return new acl_httpstatus_data(minLeft, maxRight);
63 }
64
65 /// reports acl_httpstatus_data using squid.conf http_status ACL value format
66 static std::ostream &
67 operator <<(std::ostream &os, const acl_httpstatus_data *status)
68 {
69 if (status)
70 os << status->toStr();
71 return os;
72 }
73
74 ACLHTTPStatus::ACLHTTPStatus (char const *theClass) : data(nullptr), class_ (theClass)
75 {}
76
77 ACLHTTPStatus::~ACLHTTPStatus()
78 {
79 if (data) {
80 data->destroy();
81 delete data;
82 }
83 }
84
85 char const *
86 ACLHTTPStatus::typeString() const
87 {
88 return class_;
89 }
90
91 bool
92 ACLHTTPStatus::empty () const
93 {
94 return data->empty();
95 }
96
97 static acl_httpstatus_data*
98 aclParseHTTPStatusData(const char *t)
99 {
100 int status;
101 status = atoi(t);
102 t = strchr(t, '-');
103
104 if (!t)
105 return new acl_httpstatus_data(status);
106
107 if (*(++t))
108 return new acl_httpstatus_data(status, atoi(t));
109
110 return new acl_httpstatus_data(status, INT_MAX);
111 }
112
113 void
114 ACLHTTPStatus::parse()
115 {
116 if (!data)
117 data = new Splay<acl_httpstatus_data*>();
118
119 aclParseHTTPStatusList (&data);
120 }
121
122 void
123 aclParseHTTPStatusList(Splay<acl_httpstatus_data *> **curlist)
124 {
125 while (char *t = ConfigParser::strtokFile()) {
126 if (acl_httpstatus_data *q = aclParseHTTPStatusData(t))
127 Acl::SplayInserter<acl_httpstatus_data*>::Merge(**curlist, std::move(q));
128 }
129 }
130
131 int
132 ACLHTTPStatus::match(ACLChecklist *checklist)
133 {
134 return aclMatchHTTPStatus(&data, Filled(checklist)->reply().sline.status());
135 }
136
137 int
138 aclMatchHTTPStatus(Splay<acl_httpstatus_data*> **dataptr, const Http::StatusCode status)
139 {
140 acl_httpstatus_data X(status);
141 const acl_httpstatus_data * const * result = (*dataptr)->find(&X, aclHTTPStatusCompare);
142
143 debugs(28, 3, "aclMatchHTTPStatus: '" << status << "' " << (result ? "found" : "NOT found"));
144 return (result != nullptr);
145 }
146
147 static int
148 aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b)
149 {
150 if (a->status2 < b->status1)
151 return 1; // the entire range a is to the left of range b
152
153 if (a->status1 > b->status2)
154 return -1; // the entire range a is to the right of range b
155
156 return 0; // equal or partially overlapping ranges
157 }
158
159 struct HttpStatusAclDumpVisitor {
160 SBufList contents;
161 void operator() (const acl_httpstatus_data * node) {
162 contents.push_back(node->toStr());
163 }
164 };
165
166 SBufList
167 ACLHTTPStatus::dump() const
168 {
169 HttpStatusAclDumpVisitor visitor;
170 data->visit(visitor);
171 return visitor.contents;
172 }
173