2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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.
9 /* DEBUG: section 28 Access Control */
12 #include "acl/FilledChecklist.h"
13 #include "acl/HttpStatus.h"
14 #include "acl/SplayInserter.h"
15 #include "debug/Stream.h"
16 #include "HttpReply.h"
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
);
25 acl_httpstatus_data::acl_httpstatus_data(int x
) : status1(x
), status2(x
) { ; }
27 acl_httpstatus_data::acl_httpstatus_data(int x
, int y
) : status1(x
), status2(y
) { ; }
30 acl_httpstatus_data::toStr() const
33 if (status2
== INT_MAX
)
34 rv
.Printf("%d-", status1
);
35 else if (status1
== status2
)
36 rv
.Printf("%d", status1
);
38 rv
.Printf("%d-%d", status1
, status2
);
44 Acl::SplayInserter
<acl_httpstatus_data
*>::Compare(const Value
&a
, const Value
&b
)
46 return aclHTTPStatusCompare(a
, b
);
51 Acl::SplayInserter
<acl_httpstatus_data
*>::IsSubset(const Value
&a
, const Value
&b
)
53 return b
->status1
<= a
->status1
&& a
->status2
<= b
->status2
;
57 Acl::SplayInserter
<acl_httpstatus_data
*>::Value
58 Acl::SplayInserter
<acl_httpstatus_data
*>::MakeCombinedValue(const Value
&a
, const Value
&b
)
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
);
65 /// reports acl_httpstatus_data using squid.conf http_status ACL value format
67 operator <<(std::ostream
&os
, const acl_httpstatus_data
*status
)
70 os
<< status
->toStr();
74 ACLHTTPStatus::ACLHTTPStatus (char const *theClass
) : data(nullptr), class_ (theClass
)
77 ACLHTTPStatus::~ACLHTTPStatus()
86 ACLHTTPStatus::typeString() const
92 ACLHTTPStatus::empty () const
97 static acl_httpstatus_data
*
98 aclParseHTTPStatusData(const char *t
)
105 return new acl_httpstatus_data(status
);
108 return new acl_httpstatus_data(status
, atoi(t
));
110 return new acl_httpstatus_data(status
, INT_MAX
);
114 ACLHTTPStatus::parse()
117 data
= new Splay
<acl_httpstatus_data
*>();
119 aclParseHTTPStatusList (&data
);
123 aclParseHTTPStatusList(Splay
<acl_httpstatus_data
*> **curlist
)
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
));
132 ACLHTTPStatus::match(ACLChecklist
*checklist
)
134 return aclMatchHTTPStatus(&data
, Filled(checklist
)->reply().sline
.status());
138 aclMatchHTTPStatus(Splay
<acl_httpstatus_data
*> **dataptr
, const Http::StatusCode status
)
140 acl_httpstatus_data
X(status
);
141 const acl_httpstatus_data
* const * result
= (*dataptr
)->find(&X
, aclHTTPStatusCompare
);
143 debugs(28, 3, "aclMatchHTTPStatus: '" << status
<< "' " << (result
? "found" : "NOT found"));
144 return (result
!= nullptr);
148 aclHTTPStatusCompare(acl_httpstatus_data
* const &a
, acl_httpstatus_data
* const &b
)
150 if (a
->status2
< b
->status1
)
151 return 1; // the entire range a is to the left of range b
153 if (a
->status1
> b
->status2
)
154 return -1; // the entire range a is to the right of range b
156 return 0; // equal or partially overlapping ranges
159 struct HttpStatusAclDumpVisitor
{
161 void operator() (const acl_httpstatus_data
* node
) {
162 contents
.push_back(node
->toStr());
167 ACLHTTPStatus::dump() const
169 HttpStatusAclDumpVisitor visitor
;
170 data
->visit(visitor
);
171 return visitor
.contents
;