]>
Commit | Line | Data |
---|---|---|
a0ec9f68 | 1 | /* |
bde978a6 | 2 | * Copyright (C) 1996-2015 The Squid Software Foundation and contributors |
a0ec9f68 | 3 | * |
bbc27441 AJ |
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. | |
a0ec9f68 | 7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 28 Access Control */ |
10 | ||
f7f3304a | 11 | #include "squid.h" |
c0941a6a | 12 | #include "acl/FilledChecklist.h" |
602d9612 | 13 | #include "acl/HttpStatus.h" |
06390e4b | 14 | #include "cache_cf.h" |
582c2af2 | 15 | #include "Debug.h" |
a0ec9f68 | 16 | #include "HttpReply.h" |
17 | ||
074d6a40 | 18 | #include <climits> |
582c2af2 | 19 | |
4ac36eab | 20 | static void aclParseHTTPStatusList(Splay<acl_httpstatus_data *> **curlist); |
a0ec9f68 | 21 | static int aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b); |
4ac36eab | 22 | static int aclMatchHTTPStatus(Splay<acl_httpstatus_data*> **dataptr, Http::StatusCode status); |
a0ec9f68 | 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 | ||
8966008b | 28 | SBuf |
2cb8d372 | 29 | acl_httpstatus_data::toStr() const |
a0ec9f68 | 30 | { |
8966008b | 31 | SBuf rv; |
a0ec9f68 | 32 | if (status2 == INT_MAX) |
8966008b | 33 | rv.Printf("%d-", status1); |
a0ec9f68 | 34 | else if (status1 == status2) |
8966008b | 35 | rv.Printf("%d", status1); |
a0ec9f68 | 36 | else |
8966008b FC |
37 | rv.Printf("%d-%d", status1, status2); |
38 | return rv; | |
a0ec9f68 | 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) { | |
2cb8d372 FC |
50 | const SBuf sa = a->toStr(); |
51 | const SBuf sb = b->toStr(); | |
8966008b FC |
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 << "'"); | |
a0ec9f68 | 55 | } |
56 | ||
57 | return ret; | |
58 | } | |
59 | ||
a0ec9f68 | 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 | { | |
f5dc4237 | 77 | if (data) { |
4ac36eab | 78 | data->destroy(); |
f5dc4237 FC |
79 | delete data; |
80 | } | |
a0ec9f68 | 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 | ||
a0ec9f68 | 111 | void |
112 | ACLHTTPStatus::parse() | |
113 | { | |
5bc2be30 FC |
114 | if (!data) |
115 | data = new Splay<acl_httpstatus_data*>(); | |
116 | ||
a0ec9f68 | 117 | aclParseHTTPStatusList (&data); |
118 | } | |
119 | ||
120 | void | |
4ac36eab | 121 | aclParseHTTPStatusList(Splay<acl_httpstatus_data *> **curlist) |
a0ec9f68 | 122 | { |
123 | char *t = NULL; | |
a0ec9f68 | 124 | acl_httpstatus_data *q = NULL; |
125 | ||
126 | while ((t = strtokFile())) { | |
127 | if ((q = aclParseHTTPStatusData(t)) == NULL) | |
128 | continue; | |
129 | ||
4ac36eab | 130 | (*curlist)->insert(q, acl_httpstatus_data::compare); |
a0ec9f68 | 131 | } |
132 | } | |
133 | ||
134 | int | |
135 | ACLHTTPStatus::match(ACLChecklist *checklist) | |
136 | { | |
9b769c67 | 137 | return aclMatchHTTPStatus(&data, Filled(checklist)->reply->sline.status()); |
a0ec9f68 | 138 | } |
139 | ||
140 | int | |
4ac36eab | 141 | aclMatchHTTPStatus(Splay<acl_httpstatus_data*> **dataptr, const Http::StatusCode status) |
a0ec9f68 | 142 | { |
a0ec9f68 | 143 | acl_httpstatus_data X(status); |
4ac36eab | 144 | const acl_httpstatus_data * const * result = (*dataptr)->find(&X, aclHTTPStatusCompare); |
a0ec9f68 | 145 | |
4ac36eab FC |
146 | debugs(28, 3, "aclMatchHTTPStatus: '" << status << "' " << (result ? "found" : "NOT found")); |
147 | return (result != NULL); | |
a0ec9f68 | 148 | } |
149 | ||
150 | static int | |
151 | aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b) | |
152 | { | |
153 | if (a->status1 < b->status1) | |
154 | return 1; | |
155 | ||
156 | if (a->status1 > b->status2) | |
157 | return -1; | |
158 | ||
159 | return 0; | |
160 | } | |
161 | ||
4ac36eab FC |
162 | struct HttpStatusAclDumpVisitor { |
163 | SBufList contents; | |
164 | void operator() (const acl_httpstatus_data * node) { | |
165 | contents.push_back(node->toStr()); | |
166 | } | |
167 | }; | |
a0ec9f68 | 168 | |
8966008b | 169 | SBufList |
a0ec9f68 | 170 | ACLHTTPStatus::dump() const |
171 | { | |
4ac36eab FC |
172 | HttpStatusAclDumpVisitor visitor; |
173 | data->visit(visitor); | |
174 | return visitor.contents; | |
a0ec9f68 | 175 | } |
176 |