]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/HttpStatus.cc
Docs: Copyright updates for 2018 (#114)
[thirdparty/squid.git] / src / acl / HttpStatus.cc
1 /*
2 * Copyright (C) 1996-2018 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 "Debug.h"
15 #include "HttpReply.h"
16
17 #include <climits>
18
19 static void aclParseHTTPStatusList(Splay<acl_httpstatus_data *> **curlist);
20 static int aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b);
21 static int aclMatchHTTPStatus(Splay<acl_httpstatus_data*> **dataptr, Http::StatusCode status);
22
23 acl_httpstatus_data::acl_httpstatus_data(int x) : status1(x), status2(x) { ; }
24
25 acl_httpstatus_data::acl_httpstatus_data(int x, int y) : status1(x), status2(y) { ; }
26
27 SBuf
28 acl_httpstatus_data::toStr() const
29 {
30 SBuf rv;
31 if (status2 == INT_MAX)
32 rv.Printf("%d-", status1);
33 else if (status1 == status2)
34 rv.Printf("%d", status1);
35 else
36 rv.Printf("%d-%d", status1, status2);
37 return rv;
38 }
39
40 int acl_httpstatus_data::compare(acl_httpstatus_data* const& a, acl_httpstatus_data* const& b)
41 {
42 int ret;
43 ret = aclHTTPStatusCompare(b, a);
44
45 if (ret != 0)
46 ret = aclHTTPStatusCompare(a, b);
47
48 if (ret == 0) {
49 const SBuf sa = a->toStr();
50 const SBuf sb = b->toStr();
51 debugs(28, DBG_CRITICAL, "WARNING: '" << sa << "' is a subrange of '" << sb << "'");
52 debugs(28, DBG_CRITICAL, "WARNING: because of this '" << sa << "' is ignored to keep splay tree searching predictable");
53 debugs(28, DBG_CRITICAL, "WARNING: You should probably remove '" << sb << "' from the ACL named '" << AclMatchedName << "'");
54 }
55
56 return ret;
57 }
58
59 ACL *
60 ACLHTTPStatus::clone() const
61 {
62 return new ACLHTTPStatus(*this);
63 }
64
65 ACLHTTPStatus::ACLHTTPStatus (char const *theClass) : data(NULL), class_ (theClass)
66 {}
67
68 ACLHTTPStatus::ACLHTTPStatus (ACLHTTPStatus const & old) : data(NULL), class_ (old.class_)
69 {
70 /* we don't have copy constructors for the data yet */
71 assert(!old.data);
72 }
73
74 ACLHTTPStatus::~ACLHTTPStatus()
75 {
76 if (data) {
77 data->destroy();
78 delete data;
79 }
80 }
81
82 char const *
83 ACLHTTPStatus::typeString() const
84 {
85 return class_;
86 }
87
88 bool
89 ACLHTTPStatus::empty () const
90 {
91 return data->empty();
92 }
93
94 acl_httpstatus_data*
95 aclParseHTTPStatusData(const char *t)
96 {
97 int status;
98 status = atoi(t);
99 t = strchr(t, '-');
100
101 if (!t)
102 return new acl_httpstatus_data(status);
103
104 if (*(++t))
105 return new acl_httpstatus_data(status, atoi(t));
106
107 return new acl_httpstatus_data(status, INT_MAX);
108 }
109
110 void
111 ACLHTTPStatus::parse()
112 {
113 if (!data)
114 data = new Splay<acl_httpstatus_data*>();
115
116 aclParseHTTPStatusList (&data);
117 }
118
119 void
120 aclParseHTTPStatusList(Splay<acl_httpstatus_data *> **curlist)
121 {
122 while (char *t = ConfigParser::strtokFile()) {
123 if (acl_httpstatus_data *q = aclParseHTTPStatusData(t))
124 (*curlist)->insert(q, acl_httpstatus_data::compare);
125 }
126 }
127
128 int
129 ACLHTTPStatus::match(ACLChecklist *checklist)
130 {
131 return aclMatchHTTPStatus(&data, Filled(checklist)->reply->sline.status());
132 }
133
134 int
135 aclMatchHTTPStatus(Splay<acl_httpstatus_data*> **dataptr, const Http::StatusCode status)
136 {
137 acl_httpstatus_data X(status);
138 const acl_httpstatus_data * const * result = (*dataptr)->find(&X, aclHTTPStatusCompare);
139
140 debugs(28, 3, "aclMatchHTTPStatus: '" << status << "' " << (result ? "found" : "NOT found"));
141 return (result != NULL);
142 }
143
144 static int
145 aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b)
146 {
147 if (a->status1 < b->status1)
148 return 1;
149
150 if (a->status1 > b->status2)
151 return -1;
152
153 return 0;
154 }
155
156 struct HttpStatusAclDumpVisitor {
157 SBufList contents;
158 void operator() (const acl_httpstatus_data * node) {
159 contents.push_back(node->toStr());
160 }
161 };
162
163 SBufList
164 ACLHTTPStatus::dump() const
165 {
166 HttpStatusAclDumpVisitor visitor;
167 data->visit(visitor);
168 return visitor.contents;
169 }
170