]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/HttpStatus.cc
Boilerplate: update copyright blurbs on src/
[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(SplayNode<acl_httpstatus_data *> **curlist);
21 static int aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b);
22 static int aclMatchHTTPStatus(SplayNode<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(SplayNode<acl_httpstatus_data*>::DefaultFree);
79 }
80
81 char const *
82 ACLHTTPStatus::typeString() const
83 {
84 return class_;
85 }
86
87 bool
88 ACLHTTPStatus::empty () const
89 {
90 return data->empty();
91 }
92
93 acl_httpstatus_data*
94 aclParseHTTPStatusData(const char *t)
95 {
96 int status;
97 status = atoi(t);
98 t = strchr(t, '-');
99
100 if (!t)
101 return new acl_httpstatus_data(status);
102
103 if (*(++t))
104 return new acl_httpstatus_data(status, atoi(t));
105
106 return new acl_httpstatus_data(status, INT_MAX);
107 }
108
109 void
110 ACLHTTPStatus::parse()
111 {
112 aclParseHTTPStatusList (&data);
113 }
114
115 void
116 aclParseHTTPStatusList(SplayNode<acl_httpstatus_data *> **curlist)
117 {
118 char *t = NULL;
119 SplayNode<acl_httpstatus_data*> **Top = curlist;
120 acl_httpstatus_data *q = NULL;
121
122 while ((t = strtokFile())) {
123 if ((q = aclParseHTTPStatusData(t)) == NULL)
124 continue;
125
126 *Top = (*Top)->insert(q, acl_httpstatus_data::compare);
127 }
128 }
129
130 int
131 ACLHTTPStatus::match(ACLChecklist *checklist)
132 {
133 return aclMatchHTTPStatus(&data, Filled(checklist)->reply->sline.status());
134 }
135
136 int
137 aclMatchHTTPStatus(SplayNode<acl_httpstatus_data*> **dataptr, const Http::StatusCode status)
138 {
139
140 acl_httpstatus_data X(status);
141 SplayNode<acl_httpstatus_data*> **Top = dataptr;
142 *Top = Top[0]->splay(&X, aclHTTPStatusCompare);
143
144 debugs(28, 3, "aclMatchHTTPStatus: '" << status << "' " << (splayLastResult ? "NOT found" : "found"));
145 return (0 == splayLastResult);
146 }
147
148 static int
149 aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b)
150 {
151 if (a->status1 < b->status1)
152 return 1;
153
154 if (a->status1 > b->status2)
155 return -1;
156
157 return 0;
158 }
159
160 static void
161 aclDumpHTTPStatusListWalkee(acl_httpstatus_data * const &node, void *state)
162 {
163 // state is a SBufList*
164 static_cast<SBufList *>(state)->push_back(node->toStr());
165 }
166
167 SBufList
168 ACLHTTPStatus::dump() const
169 {
170 SBufList w;
171 data->walk(aclDumpHTTPStatusListWalkee, &w);
172 return w;
173 }
174