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