/* * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels * * SQUID Web Proxy Cache http://www.squid-cache.org/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from * the Internet community; see the CONTRIBUTORS file for full * details. Many organizations have provided support for Squid's * development; see the SPONSORS file for full details. Squid is * Copyrighted (C) 2001 by the Regents of the University of * California; see the COPYRIGHT file for full details. Squid * incorporates software developed and/or copyrighted by other * sources; see the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * * * Copyright (c) 2003, Robert Collins */ #include "squid.h" #include "acl/HttpStatus.h" #include "acl/FilledChecklist.h" #include "cache_cf.h" #include "Debug.h" #include "HttpReply.h" #include "wordlist.h" #if HAVE_LIMITS_H #include #endif static void aclParseHTTPStatusList(SplayNode **curlist); static int aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b); static int aclMatchHTTPStatus(SplayNode **dataptr, http_status status); acl_httpstatus_data::acl_httpstatus_data(int x) : status1(x), status2(x) { ; } acl_httpstatus_data::acl_httpstatus_data(int x, int y) : status1(x), status2(y) { ; } void acl_httpstatus_data::toStr(char* buf, int len) const { if (status2 == INT_MAX) snprintf(buf, len, "%d-", status1); else if (status1 == status2) snprintf(buf, len, "%d", status1); else snprintf(buf, len, "%d-%d", status1, status2); } int acl_httpstatus_data::compare(acl_httpstatus_data* const& a, acl_httpstatus_data* const& b) { int ret; ret = aclHTTPStatusCompare(b, a); if (ret != 0) ret = aclHTTPStatusCompare(a, b); if (ret == 0) { char bufa[8]; char bufb[8]; a->toStr(bufa, sizeof(bufa)); b->toStr(bufb, sizeof(bufb)); debugs(28, DBG_CRITICAL, "WARNING: '" << bufa << "' is a subrange of '" << bufb << "'"); debugs(28, DBG_CRITICAL, "WARNING: because of this '" << bufa << "' is ignored to keep splay tree searching predictable"); debugs(28, DBG_CRITICAL, "WARNING: You should probably remove '" << bufb << "' from the ACL named '" << AclMatchedName << "'"); } return ret; } ACL * ACLHTTPStatus::clone() const { return new ACLHTTPStatus(*this); } ACLHTTPStatus::ACLHTTPStatus (char const *theClass) : data(NULL), class_ (theClass) {} ACLHTTPStatus::ACLHTTPStatus (ACLHTTPStatus const & old) : data(NULL), class_ (old.class_) { /* we don't have copy constructors for the data yet */ assert(!old.data); } ACLHTTPStatus::~ACLHTTPStatus() { if (data) data->destroy(SplayNode::DefaultFree); } char const * ACLHTTPStatus::typeString() const { return class_; } bool ACLHTTPStatus::empty () const { return data->empty(); } acl_httpstatus_data* aclParseHTTPStatusData(const char *t) { int status; status = atoi(t); t = strchr(t, '-'); if (!t) return new acl_httpstatus_data(status); if (*(++t)) return new acl_httpstatus_data(status, atoi(t)); return new acl_httpstatus_data(status, INT_MAX); } void ACLHTTPStatus::parse() { aclParseHTTPStatusList (&data); } void aclParseHTTPStatusList(SplayNode **curlist) { char *t = NULL; SplayNode **Top = curlist; acl_httpstatus_data *q = NULL; while ((t = strtokFile())) { if ((q = aclParseHTTPStatusData(t)) == NULL) continue; *Top = (*Top)->insert(q, acl_httpstatus_data::compare); } } int ACLHTTPStatus::match(ACLChecklist *checklist) { return aclMatchHTTPStatus(&data, Filled(checklist)->reply->sline.status); } int aclMatchHTTPStatus(SplayNode **dataptr, http_status status) { acl_httpstatus_data X(status); SplayNode **Top = dataptr; *Top = Top[0]->splay(&X, aclHTTPStatusCompare); debugs(28, 3, "aclMatchHTTPStatus: '" << status << "' " << (splayLastResult ? "NOT found" : "found")); return (0 == splayLastResult); } static int aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b) { if (a->status1 < b->status1) return 1; if (a->status1 > b->status2) return -1; return 0; } static void aclDumpHTTPStatusListWalkee(acl_httpstatus_data * const &node, void *state) { static char buf[8]; node->toStr(buf, sizeof(buf)); wordlistAdd((wordlist **)state, buf); } wordlist * ACLHTTPStatus::dump() const { wordlist *w = NULL; data->walk(aclDumpHTTPStatusListWalkee, &w); return w; }