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