]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/HttpStatus.cc
Merged from trunk
[thirdparty/squid.git] / src / acl / HttpStatus.cc
1 /*
2 * DEBUG: section 28 Access Control
3 * AUTHOR: Duane Wessels
4 *
5 * SQUID Web Proxy Cache http://www.squid-cache.org/
6 * ----------------------------------------------------------
7 *
8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
30 *
31 *
32 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
33 */
34
35 #include "squid.h"
36 #include "acl/FilledChecklist.h"
37 #include "acl/HttpStatus.h"
38 #include "cache_cf.h"
39 #include "Debug.h"
40 #include "HttpReply.h"
41
42 #include <climits>
43
44 static void aclParseHTTPStatusList(SplayNode<acl_httpstatus_data *> **curlist);
45 static int aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b);
46 static int aclMatchHTTPStatus(SplayNode<acl_httpstatus_data*> **dataptr, Http::StatusCode status);
47
48 acl_httpstatus_data::acl_httpstatus_data(int x) : status1(x), status2(x) { ; }
49
50 acl_httpstatus_data::acl_httpstatus_data(int x, int y) : status1(x), status2(y) { ; }
51
52 SBuf
53 acl_httpstatus_data::toStr() const
54 {
55 SBuf rv;
56 if (status2 == INT_MAX)
57 rv.Printf("%d-", status1);
58 else if (status1 == status2)
59 rv.Printf("%d", status1);
60 else
61 rv.Printf("%d-%d", status1, status2);
62 return rv;
63 }
64
65 int acl_httpstatus_data::compare(acl_httpstatus_data* const& a, acl_httpstatus_data* const& b)
66 {
67 int ret;
68 ret = aclHTTPStatusCompare(b, a);
69
70 if (ret != 0)
71 ret = aclHTTPStatusCompare(a, b);
72
73 if (ret == 0) {
74 const SBuf sa = a->toStr();
75 const SBuf sb = b->toStr();
76 debugs(28, DBG_CRITICAL, "WARNING: '" << sa << "' is a subrange of '" << sb << "'");
77 debugs(28, DBG_CRITICAL, "WARNING: because of this '" << sa << "' is ignored to keep splay tree searching predictable");
78 debugs(28, DBG_CRITICAL, "WARNING: You should probably remove '" << sb << "' from the ACL named '" << AclMatchedName << "'");
79 }
80
81 return ret;
82 }
83
84 ACL *
85 ACLHTTPStatus::clone() const
86 {
87 return new ACLHTTPStatus(*this);
88 }
89
90 ACLHTTPStatus::ACLHTTPStatus (char const *theClass) : data(NULL), class_ (theClass)
91 {}
92
93 ACLHTTPStatus::ACLHTTPStatus (ACLHTTPStatus const & old) : data(NULL), class_ (old.class_)
94 {
95 /* we don't have copy constructors for the data yet */
96 assert(!old.data);
97 }
98
99 ACLHTTPStatus::~ACLHTTPStatus()
100 {
101 if (data)
102 data->destroy(SplayNode<acl_httpstatus_data*>::DefaultFree);
103 }
104
105 char const *
106 ACLHTTPStatus::typeString() const
107 {
108 return class_;
109 }
110
111 bool
112 ACLHTTPStatus::empty () const
113 {
114 return data->empty();
115 }
116
117 acl_httpstatus_data*
118 aclParseHTTPStatusData(const char *t)
119 {
120 int status;
121 status = atoi(t);
122 t = strchr(t, '-');
123
124 if (!t)
125 return new acl_httpstatus_data(status);
126
127 if (*(++t))
128 return new acl_httpstatus_data(status, atoi(t));
129
130 return new acl_httpstatus_data(status, INT_MAX);
131 }
132
133 void
134 ACLHTTPStatus::parse()
135 {
136 aclParseHTTPStatusList (&data);
137 }
138
139 void
140 aclParseHTTPStatusList(SplayNode<acl_httpstatus_data *> **curlist)
141 {
142 char *t = NULL;
143 SplayNode<acl_httpstatus_data*> **Top = curlist;
144 acl_httpstatus_data *q = NULL;
145
146 while ((t = strtokFile())) {
147 if ((q = aclParseHTTPStatusData(t)) == NULL)
148 continue;
149
150 *Top = (*Top)->insert(q, acl_httpstatus_data::compare);
151 }
152 }
153
154 int
155 ACLHTTPStatus::match(ACLChecklist *checklist)
156 {
157 return aclMatchHTTPStatus(&data, Filled(checklist)->reply->sline.status());
158 }
159
160 int
161 aclMatchHTTPStatus(SplayNode<acl_httpstatus_data*> **dataptr, const Http::StatusCode status)
162 {
163
164 acl_httpstatus_data X(status);
165 SplayNode<acl_httpstatus_data*> **Top = dataptr;
166 *Top = Top[0]->splay(&X, aclHTTPStatusCompare);
167
168 debugs(28, 3, "aclMatchHTTPStatus: '" << status << "' " << (splayLastResult ? "NOT found" : "found"));
169 return (0 == splayLastResult);
170 }
171
172 static int
173 aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b)
174 {
175 if (a->status1 < b->status1)
176 return 1;
177
178 if (a->status1 > b->status2)
179 return -1;
180
181 return 0;
182 }
183
184 static void
185 aclDumpHTTPStatusListWalkee(acl_httpstatus_data * const &node, void *state)
186 {
187 // state is a SBufList*
188 static_cast<SBufList *>(state)->push_back(node->toStr());
189 }
190
191 SBufList
192 ACLHTTPStatus::dump() const
193 {
194 SBufList w;
195 data->walk(aclDumpHTTPStatusListWalkee, &w);
196 return w;
197 }
198