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