]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/HttpStatus.cc
Merge 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 #include "wordlist.h"
42
43 #if HAVE_LIMITS_H
44 #include <limits.h>
45 #endif
46
47 static void aclParseHTTPStatusList(SplayNode<acl_httpstatus_data *> **curlist);
48 static int aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b);
49 static int aclMatchHTTPStatus(SplayNode<acl_httpstatus_data*> **dataptr, Http::StatusCode status);
50
51 acl_httpstatus_data::acl_httpstatus_data(int x) : status1(x), status2(x) { ; }
52
53 acl_httpstatus_data::acl_httpstatus_data(int x, int y) : status1(x), status2(y) { ; }
54
55 void acl_httpstatus_data::toStr(char* buf, int len) const
56 {
57 if (status2 == INT_MAX)
58 snprintf(buf, len, "%d-", status1);
59 else if (status1 == status2)
60 snprintf(buf, len, "%d", status1);
61 else
62 snprintf(buf, len, "%d-%d", status1, status2);
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 char bufa[8];
75 char bufb[8];
76 a->toStr(bufa, sizeof(bufa));
77 b->toStr(bufb, sizeof(bufb));
78 debugs(28, DBG_CRITICAL, "WARNING: '" << bufa << "' is a subrange of '" << bufb << "'");
79 debugs(28, DBG_CRITICAL, "WARNING: because of this '" << bufa << "' is ignored to keep splay tree searching predictable");
80 debugs(28, DBG_CRITICAL, "WARNING: You should probably remove '" << bufb << "' from the ACL named '" << AclMatchedName << "'");
81 }
82
83 return ret;
84 }
85
86 ACL *
87 ACLHTTPStatus::clone() const
88 {
89 return new ACLHTTPStatus(*this);
90 }
91
92 ACLHTTPStatus::ACLHTTPStatus (char const *theClass) : data(NULL), class_ (theClass)
93 {}
94
95 ACLHTTPStatus::ACLHTTPStatus (ACLHTTPStatus const & old) : data(NULL), class_ (old.class_)
96 {
97 /* we don't have copy constructors for the data yet */
98 assert(!old.data);
99 }
100
101 ACLHTTPStatus::~ACLHTTPStatus()
102 {
103 if (data)
104 data->destroy(SplayNode<acl_httpstatus_data*>::DefaultFree);
105 }
106
107 char const *
108 ACLHTTPStatus::typeString() const
109 {
110 return class_;
111 }
112
113 bool
114 ACLHTTPStatus::empty () const
115 {
116 return data->empty();
117 }
118
119 acl_httpstatus_data*
120 aclParseHTTPStatusData(const char *t)
121 {
122 int status;
123 status = atoi(t);
124 t = strchr(t, '-');
125
126 if (!t)
127 return new acl_httpstatus_data(status);
128
129 if (*(++t))
130 return new acl_httpstatus_data(status, atoi(t));
131
132 return new acl_httpstatus_data(status, INT_MAX);
133 }
134
135 void
136 ACLHTTPStatus::parse()
137 {
138 aclParseHTTPStatusList (&data);
139 }
140
141 void
142 aclParseHTTPStatusList(SplayNode<acl_httpstatus_data *> **curlist)
143 {
144 char *t = NULL;
145 SplayNode<acl_httpstatus_data*> **Top = curlist;
146 acl_httpstatus_data *q = NULL;
147
148 while ((t = strtokFile())) {
149 if ((q = aclParseHTTPStatusData(t)) == NULL)
150 continue;
151
152 *Top = (*Top)->insert(q, acl_httpstatus_data::compare);
153 }
154 }
155
156 int
157 ACLHTTPStatus::match(ACLChecklist *checklist)
158 {
159 return aclMatchHTTPStatus(&data, Filled(checklist)->reply->sline.status());
160 }
161
162 int
163 aclMatchHTTPStatus(SplayNode<acl_httpstatus_data*> **dataptr, const Http::StatusCode status)
164 {
165
166 acl_httpstatus_data X(status);
167 SplayNode<acl_httpstatus_data*> **Top = dataptr;
168 *Top = Top[0]->splay(&X, aclHTTPStatusCompare);
169
170 debugs(28, 3, "aclMatchHTTPStatus: '" << status << "' " << (splayLastResult ? "NOT found" : "found"));
171 return (0 == splayLastResult);
172 }
173
174 static int
175 aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b)
176 {
177 if (a->status1 < b->status1)
178 return 1;
179
180 if (a->status1 > b->status2)
181 return -1;
182
183 return 0;
184 }
185
186 static void
187 aclDumpHTTPStatusListWalkee(acl_httpstatus_data * const &node, void *state)
188 {
189 static char buf[8];
190 node->toStr(buf, sizeof(buf));
191 wordlistAdd((wordlist **)state, buf);
192 }
193
194 wordlist *
195 ACLHTTPStatus::dump() const
196 {
197 wordlist *w = NULL;
198 data->walk(aclDumpHTTPStatusListWalkee, &w);
199 return w;
200 }
201