1 /* 2 * Copyright (C) 1996-2021 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 #ifndef SQUID_HTTPHEADERTOOLS_H 10 #define SQUID_HTTPHEADERTOOLS_H 11 12 #include "acl/forward.h" 13 #include "format/Format.h" 14 #include "HttpHeader.h" 15 16 #include <functional> 17 #include <list> 18 #include <map> 19 #include <string> 20 #if HAVE_STRINGS_H 21 #include <strings.h> 22 #endif 23 24 class HeaderWithAcl; 25 class HttpHeader; 26 class HttpRequest; 27 class StoreEntry; 28 class String; 29 30 typedef std::list<HeaderWithAcl> HeaderWithAclList; 31 32 /* Distinguish between Request and Reply (for header mangling) */ 33 typedef enum { 34 ROR_REQUEST, 35 ROR_REPLY 36 } req_or_rep_t; 37 38 // Currently a POD 39 class headerMangler 40 { 41 public: 42 acl_access *access_list; 43 char *replacement; 44 }; 45 46 /// A collection of headerMangler objects for a given message kind. 47 class HeaderManglers 48 { 49 public: 50 HeaderManglers(); 51 ~HeaderManglers(); 52 53 /// returns a header mangler for field e or nil if none was specified 54 const headerMangler *find(const HttpHeaderEntry &e) const; 55 56 /// returns a mangler for the named header (known or custom) 57 headerMangler *track(const char *name); 58 59 /// updates mangler for the named header with a replacement value 60 void setReplacement(const char *name, const char *replacementValue); 61 62 /// report the *_header_access part of the configuration 63 void dumpAccess(StoreEntry *entry, const char *optionName) const; 64 /// report the *_header_replace part of the configuration 65 void dumpReplacement(StoreEntry *entry, const char *optionName) const; 66 67 private: 68 /// Case-insensitive std::string "less than" comparison functor. 69 /// Fast version recommended by Meyers' "Effective STL" for ASCII c-strings. 70 class NoCaseLessThan: public std::binary_function<std::string, std::string, bool> 71 { 72 public: operator()73 bool operator()(const std::string &lhs, const std::string &rhs) const { 74 return strcasecmp(lhs.c_str(), rhs.c_str()) < 0; 75 } 76 }; 77 78 /// a name:mangler map; optimize: use unordered map or some such 79 typedef std::map<std::string, headerMangler, NoCaseLessThan> ManglersByName; 80 81 /// one mangler for each known header 82 headerMangler known[static_cast<int>(Http::HdrType::enumEnd_)]; 83 84 /// one mangler for each custom header 85 ManglersByName custom; 86 87 /// configured if some mangling ACL applies to all header names 88 headerMangler all; 89 90 private: 91 /* not implemented */ 92 HeaderManglers(const HeaderManglers &); 93 HeaderManglers &operator =(const HeaderManglers &); 94 }; 95 96 class HeaderWithAcl 97 { 98 public: HeaderWithAcl()99 HeaderWithAcl() : aclList(NULL), valueFormat(NULL), fieldId(Http::HdrType::BAD_HDR), quoted(false) {} 100 101 /// HTTP header field name 102 std::string fieldName; 103 104 /// HTTP header field value, possibly with macros 105 std::string fieldValue; 106 107 /// when the header field should be added (always if nil) 108 ACLList *aclList; 109 110 /// compiled HTTP header field value (no macros) 111 Format::Format *valueFormat; 112 113 /// internal ID for "known" headers or HDR_OTHER 114 Http::HdrType fieldId; 115 116 /// whether fieldValue may contain macros 117 bool quoted; 118 }; 119 120 /// A strtoll(10) wrapper that checks for strtoll() failures and other problems. 121 /// XXX: This function is not fully compatible with some HTTP syntax rules. 122 /// Just like strtoll(), allows whitespace prefix, a sign, and _any_ suffix. 123 /// Requires at least one digit to be present. 124 /// Sets "off" and "end" arguments if and only if no problems were found. 125 /// \return true if and only if no problems were found. 126 bool httpHeaderParseOffset(const char *start, int64_t *offPtr, char **endPtr = nullptr); 127 128 bool httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive); 129 int httpHeaderParseInt(const char *start, int *val); 130 void httpHeaderPutStrf(HttpHeader * hdr, Http::HdrType id, const char *fmt,...) PRINTF_FORMAT_ARG3; 131 132 const char *getStringPrefix(const char *str, size_t len); 133 134 void httpHdrMangleList(HttpHeader *, HttpRequest *, const AccessLogEntryPointer &al, req_or_rep_t req_or_rep); 135 136 #endif 137 138