]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/HttpStatus.cc
Interim: removed needless spacing and c++ guards, started fixing DelayTagged accessin...
[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 aclParseHTTPStatusList (&data);
115 }
116
117 void
118 aclParseHTTPStatusList(Splay<acl_httpstatus_data *> **curlist)
119 {
120 char *t = NULL;
121 acl_httpstatus_data *q = NULL;
122
123 while ((t = strtokFile())) {
124 if ((q = aclParseHTTPStatusData(t)) == NULL)
125 continue;
126
127 (*curlist)->insert(q, acl_httpstatus_data::compare);
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 != NULL);
145 }
146
147 static int
148 aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b)
149 {
150 if (a->status1 < b->status1)
151 return 1;
152
153 if (a->status1 > b->status2)
154 return -1;
155
156 return 0;
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