]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/HttpHeader.h
SourceFormat Enforcement
[thirdparty/squid.git] / src / HttpHeader.h
index 0fddd3bdd2d5f3cc19eaecfd6af9caa5c3dbe961..b85cdd0f2cfbe7e0945bbbd17335508a3bb9aa08 100644 (file)
@@ -1,39 +1,20 @@
 /*
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
  *
- * 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.
- *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
 #ifndef SQUID_HTTPHEADER_H
 #define SQUID_HTTPHEADER_H
 
+#include "base/LookupTable.h"
+#include "http/RegisteredHeaders.h"
 /* because we pass a spec by value */
 #include "HttpHeaderMask.h"
-#include "MemPool.h"
+#include "mem/forward.h"
+#include "sbuf/forward.h"
 #include "SquidString.h"
 
 #include <vector>
@@ -43,135 +24,7 @@ class HttpHdrCc;
 class HttpHdrContRange;
 class HttpHdrRange;
 class HttpHdrSc;
-class Packer;
-class StoreEntry;
-
-/* constant attributes of http header fields */
-
-/// recognized or "known" header fields; and the RFC which defines them (or not)
-typedef enum {
-    HDR_BAD_HDR = -1,
-    HDR_ACCEPT = 0,                     /**< RFC 2608, 2616 */
-    HDR_ACCEPT_CHARSET,                 /**< RFC 2608, 2616 */
-    HDR_ACCEPT_ENCODING,                /**< RFC 2608, 2616 */
-    /*HDR_ACCEPT_FEATURES,*/            /* experimental RFC 2295 */
-    HDR_ACCEPT_LANGUAGE,                /**< RFC 2608, 2616 */
-    HDR_ACCEPT_RANGES,                  /**< RFC 2608, 2616 */
-    HDR_AGE,                            /**< RFC 2608, 2616 */
-    HDR_ALLOW,                          /**< RFC 2608, 2616 */
-    /*HDR_ALTERNATES,*/                 /* deprecated RFC 2068, 2295 */
-    HDR_AUTHORIZATION,                  /**< RFC 2608, 2616, 4559 */
-    HDR_CACHE_CONTROL,                  /**< RFC 2608, 2616 */
-    HDR_CONNECTION,                     /**< RFC 2608, 2616 */
-    HDR_CONTENT_BASE,                   /**< RFC 2608 */
-    HDR_CONTENT_DISPOSITION,            /**< RFC 2183, 2616 */
-    HDR_CONTENT_ENCODING,               /**< RFC 2608, 2616 */
-    HDR_CONTENT_LANGUAGE,               /**< RFC 2608, 2616 */
-    HDR_CONTENT_LENGTH,                 /**< RFC 2608, 2616 */
-    HDR_CONTENT_LOCATION,               /**< RFC 2608, 2616 */
-    HDR_CONTENT_MD5,                    /**< RFC 2608, 2616 */
-    HDR_CONTENT_RANGE,                  /**< RFC 2608, 2616 */
-    HDR_CONTENT_TYPE,                   /**< RFC 2608, 2616 */
-    /*HDR_CONTENT_VERSION,*/            /* deprecated RFC 2608 header. */
-    HDR_COOKIE,                         /**< de-facto and RFC 2965 header we may need to erase */
-    HDR_COOKIE2,                        /**< obsolete RFC 2965 header we may need to erase */
-    HDR_DATE,                           /**< RFC 2608, 2616 */
-    /*HDR_DAV,*/                        /* RFC 2518 */
-    /*HDR_DEPTH,*/                      /* RFC 2518 */
-    /*HDR_DERIVED_FROM,*/               /* deprecated RFC 2608 */
-    /*HDR_DESTINATION,*/                /* RFC 2518 */
-    HDR_ETAG,                           /**< RFC 2608, 2616 */
-    HDR_EXPECT,                         /**< RFC 2616, 2616 */
-    HDR_EXPIRES,                        /**< RFC 2608, 2616 */
-    HDR_FROM,                           /**< RFC 2608, 2616 */
-    HDR_HOST,                           /**< RFC 2608, 2616 */
-    HDR_HTTP2_SETTINGS,                 /**< HTTP/2.0 upgrade header. see draft-ietf-httpbis-http2-04 */
-    /*HDR_IF,*/                         /* RFC 2518 */
-    HDR_IF_MATCH,                       /**< RFC 2608, 2616 */
-    HDR_IF_MODIFIED_SINCE,              /**< RFC 2608, 2616 */
-    HDR_IF_NONE_MATCH,                  /**< RFC 2608, 2616 */
-    HDR_IF_RANGE,                       /**< RFC 2608, 2616 */
-    /*HDR_IF_UNMODIFIED_SINCE,*/        /**< RFC 2608, 2616 */
-    HDR_KEEP_ALIVE,                     /**< obsolete HTTP/1.0 header we may need to erase */
-    HDR_KEY,                            /**< experimental RFC Draft draft-fielding-http-key-02 */
-    HDR_LAST_MODIFIED,                  /**< RFC 2608, 2616 */
-    HDR_LINK,                           /**< RFC 2068 */
-    HDR_LOCATION,                       /**< RFC 2608, 2616 */
-    /*HDR_LOCK_TOKEN,*/                 /* RFC 2518 */
-    HDR_MAX_FORWARDS,                   /**< RFC 2608, 2616 */
-    HDR_MIME_VERSION,                   /**< RFC 2626 */
-    HDR_NEGOTIATE,                      /**< experimental RFC 2295. Why only this one from 2295? */
-    /*HDR_OVERWRITE,*/                  /* RFC 2518 */
-    HDR_ORIGIN,                         /* CORS Draft specification (see http://www.w3.org/TR/cors/) */
-    HDR_PRAGMA,                         /**< deprecated RFC 2068,2616 header we may need to erase */
-    HDR_PROXY_AUTHENTICATE,             /**< RFC 2608, 2616, 2617 */
-    HDR_PROXY_AUTHENTICATION_INFO,      /**< RFC 2617 */
-    HDR_PROXY_AUTHORIZATION,            /**< RFC 2608, 2616, 2617 */
-    HDR_PROXY_CONNECTION,               /**< obsolete Netscape header we may need to erase. */
-    HDR_PROXY_SUPPORT,                  /**< RFC 4559 */
-    HDR_PUBLIC,                         /**< RFC 2608 */
-    HDR_RANGE,                          /**< RFC 2608, 2616 */
-    HDR_REFERER,                        /**< RFC 2608, 2616 */
-    HDR_REQUEST_RANGE,                  /**< some clients use this, sigh */
-    HDR_RETRY_AFTER,                    /**< RFC 2608, 2616 */
-    HDR_SERVER,                         /**< RFC 2608, 2616 */
-    HDR_SET_COOKIE,                    /**< de-facto standard header we may need to erase */
-    HDR_SET_COOKIE2,                    /**< obsolete RFC 2965 header we may need to erase */
-    /*HDR_STATUS_URI,*/                 /* RFC 2518 */
-    /*HDR_TCN,*/                        /* experimental RFC 2295 */
-    HDR_TE,                             /**< RFC 2616 */
-    /*HDR_TIMEOUT,*/                    /* RFC 2518 */
-    HDR_TITLE,                          /* obsolete draft suggested header */
-    HDR_TRAILER,                        /**< RFC 2616 */
-    HDR_TRANSFER_ENCODING,              /**< RFC 2608, 2616 */
-    HDR_TRANSLATE,                      /**< IIS custom header we may need to erase */
-    HDR_UNLESS_MODIFIED_SINCE,          /**< IIS custom header we may need to erase */
-    HDR_UPGRADE,                        /**< RFC 2608, 2616 */
-    /*HDR_URI,*/                        /* obsolete RFC 2068 header */
-    HDR_USER_AGENT,                     /**< RFC 2608, 2616 */
-    /*HDR_VARIANT_VARY,*/               /* experimental RFC 2295 */
-    HDR_VARY,                           /**< RFC 2608, 2616 */
-    HDR_VIA,                            /**< RFC 2608, 2616 */
-    HDR_WARNING,                        /**< RFC 2608, 2616 */
-    HDR_WWW_AUTHENTICATE,               /**< RFC 2608, 2616, 2617, 4559 */
-    HDR_AUTHENTICATION_INFO,            /**< RFC 2617 */
-    HDR_X_CACHE,                        /**< Squid custom header */
-    HDR_X_CACHE_LOOKUP,                        /**< Squid custom header. temporary hack that became de-facto. TODO remove */
-    HDR_X_FORWARDED_FOR,                /**< Squid custom header */
-    HDR_X_REQUEST_URI,                  /**< Squid custom header appended if ADD_X_REQUEST_URI is defined */
-    HDR_X_SQUID_ERROR,                  /**< Squid custom header on generated error responses */
-#if X_ACCELERATOR_VARY
-    HDR_X_ACCELERATOR_VARY,             /**< obsolete Squid custom header. */
-#endif
-#if USE_ADAPTATION
-    HDR_X_NEXT_SERVICES,                /**< Squid custom ICAP header */
-#endif
-    HDR_SURROGATE_CAPABILITY,           /**< Edge Side Includes (ESI) header */
-    HDR_SURROGATE_CONTROL,              /**< Edge Side Includes (ESI) header */
-    HDR_FRONT_END_HTTPS,                /**< MS Exchange custom header we may have to add */
-    HDR_FTP_COMMAND,                    /**< Internal header for FTP command */
-    HDR_FTP_ARGUMENTS,                  /**< Internal header for FTP command arguments */
-    HDR_FTP_PRE,                        /**< Custom: Contains leading FTP control response lines */
-    HDR_FTP_STATUS,                     /**< Internal header for FTP reply status */
-    HDR_FTP_REASON,                     /**< Internal header for FTP reply reason */
-    HDR_OTHER,                          /**< internal tag value for "unknown" headers */
-    HDR_ENUM_END
-} http_hdr_type;
-
-/** possible types for http header fields */
-typedef enum {
-    ftInvalid = HDR_ENUM_END,  /**< to catch nasty errors with hdr_id<->fld_type clashes */
-    ftInt,
-    ftInt64,
-    ftStr,
-    ftDate_1123,
-    ftETag,
-    ftPCc,
-    ftPContRange,
-    ftPRange,
-    ftPSc,
-    ftDate_1123_or_ETag
-} field_type;
+class Packable;
 
 /** Possible owners of http header */
 typedef enum {
@@ -187,15 +40,6 @@ typedef enum {
     hoEnd
 } http_hdr_owner_type;
 
-// currently a POD
-class HttpHeaderFieldAttrs
-{
-public:
-    const char *name;
-    http_hdr_type id;
-    field_type type;
-};
-
 /** Iteration for headers; use HttpHeaderPos as opaque type, do not interpret */
 typedef ssize_t HttpHeaderPos;
 
@@ -204,23 +48,22 @@ typedef ssize_t HttpHeaderPos;
 
 class HttpHeaderEntry
 {
+    MEMPROXY_CLASS(HttpHeaderEntry);
 
 public:
-    HttpHeaderEntry(http_hdr_type id, const char *name, const char *value);
+    HttpHeaderEntry(Http::HdrType id, const char *name, const char *value);
     ~HttpHeaderEntry();
     static HttpHeaderEntry *parse(const char *field_start, const char *field_end);
     HttpHeaderEntry *clone() const;
-    void packInto(Packer *p) const;
+    void packInto(Packable *p) const;
     int getInt() const;
     int64_t getInt64() const;
-    MEMPROXY_CLASS(HttpHeaderEntry);
-    http_hdr_type id;
+
+    Http::HdrType id;
     String name;
     String value;
 };
 
-MEMPROXY_CLASS_INLINE(HttpHeaderEntry);
-
 class ETag;
 class TimeOrTag;
 
@@ -238,33 +81,42 @@ public:
     /* Interface functions */
     void clean();
     void append(const HttpHeader * src);
-    void update (HttpHeader const *fresh, HttpHeaderMask const *denied_mask);
+    bool update(HttpHeader const *fresh);
     void compact();
-    int reset();
-    int parse(const char *header_start, const char *header_end);
-    void packInto(Packer * p, bool mask_sensitive_info=false) const;
+    int parse(const char *header_start, size_t len);
+    /// Parses headers stored in a buffer.
+    /// \returns 1 and sets hdr_sz on success
+    /// \returns 0 when needs more data
+    /// \returns -1 on error
+    int parse(const char *buf, size_t buf_len, bool atEnd, size_t &hdr_sz);
+    void packInto(Packable * p, bool mask_sensitive_info=false) const;
     HttpHeaderEntry *getEntry(HttpHeaderPos * pos) const;
-    HttpHeaderEntry *findEntry(http_hdr_type id) const;
+    HttpHeaderEntry *findEntry(Http::HdrType id) const;
     int delByName(const char *name);
-    int delById(http_hdr_type id);
+    int delById(Http::HdrType id);
     void delAt(HttpHeaderPos pos, int &headers_deleted);
     void refreshMask();
     void addEntry(HttpHeaderEntry * e);
     void insertEntry(HttpHeaderEntry * e);
-    String getList(http_hdr_type id) const;
-    bool getList(http_hdr_type id, String *s) const;
-    String getStrOrList(http_hdr_type id) const;
+    String getList(Http::HdrType id) const;
+    bool getList(Http::HdrType id, String *s) const;
+    bool conflictingContentLength() const { return conflictingContentLength_; }
+    String getStrOrList(Http::HdrType id) const;
+    String getByName(const SBuf &name) const;
     String getByName(const char *name) const;
+    String getById(Http::HdrType id) const;
+    /// sets value and returns true iff a [possibly empty] field identified by id is there
+    bool getByIdIfPresent(Http::HdrType id, String &result) const;
     /// sets value and returns true iff a [possibly empty] named field is there
-    bool getByNameIfPresent(const char *name, String &value) const;
+    bool getByNameIfPresent(const SBuf &s, String &value) const;
+    bool getByNameIfPresent(const char *name, int namelen, String &value) const;
     String getByNameListMember(const char *name, const char *member, const char separator) const;
-    String getListMember(http_hdr_type id, const char *member, const char separator) const;
-    int has(http_hdr_type id) const;
-    void putInt(http_hdr_type id, int number);
-    void putInt64(http_hdr_type id, int64_t number);
-    void putTime(http_hdr_type id, time_t htime);
-    void insertTime(http_hdr_type id, time_t htime);
-    void putStr(http_hdr_type id, const char *str);
+    String getListMember(Http::HdrType id, const char *member, const char separator) const;
+    int has(Http::HdrType id) const;
+    void putInt(Http::HdrType id, int number);
+    void putInt64(Http::HdrType id, int64_t number);
+    void putTime(Http::HdrType id, time_t htime);
+    void putStr(Http::HdrType id, const char *str);
     void putAuth(const char *auth_scheme, const char *realm);
     void putCc(const HttpHdrCc * cc);
     void putContRange(const HttpHdrContRange * cr);
@@ -272,54 +124,63 @@ public:
     void putSc(HttpHdrSc *sc);
     void putWarning(const int code, const char *const text); ///< add a Warning header
     void putExt(const char *name, const char *value);
-    int getInt(http_hdr_type id) const;
-    int64_t getInt64(http_hdr_type id) const;
-    time_t getTime(http_hdr_type id) const;
-    const char *getStr(http_hdr_type id) const;
-    const char *getLastStr(http_hdr_type id) const;
+    int getInt(Http::HdrType id) const;
+    int64_t getInt64(Http::HdrType id) const;
+    time_t getTime(Http::HdrType id) const;
+    const char *getStr(Http::HdrType id) const;
+    const char *getLastStr(Http::HdrType id) const;
     HttpHdrCc *getCc() const;
     HttpHdrRange *getRange() const;
     HttpHdrSc *getSc() const;
     HttpHdrContRange *getContRange() const;
-    const char *getAuth(http_hdr_type id, const char *auth_scheme) const;
-    ETag getETag(http_hdr_type id) const;
-    TimeOrTag getTimeOrTag(http_hdr_type id) const;
-    int hasListMember(http_hdr_type id, const char *member, const char separator) const;
+    const char *getAuth(Http::HdrType id, const char *auth_scheme) const;
+    ETag getETag(Http::HdrType id) const;
+    TimeOrTag getTimeOrTag(Http::HdrType id) const;
+    int hasListMember(Http::HdrType id, const char *member, const char separator) const;
     int hasByNameListMember(const char *name, const char *member, const char separator) const;
     void removeHopByHopEntries();
     inline bool chunked() const; ///< whether message uses chunked Transfer-Encoding
 
     /* protected, do not use these, use interface functions instead */
-    std::vector<HttpHeaderEntry *> entries;            /**< parsed fields in raw format */
-    HttpHeaderMask mask;       /**< bit set <=> entry present */
-    http_hdr_owner_type owner; /**< request or reply */
-    int len;                   /**< length when packed, not counting terminating null-byte */
+    std::vector<HttpHeaderEntry *> entries;     /**< parsed fields in raw format */
+    HttpHeaderMask mask;    /**< bit set <=> entry present */
+    http_hdr_owner_type owner;  /**< request or reply */
+    int len;            /**< length when packed, not counting terminating null-byte */
 
 protected:
     /** \deprecated Public access replaced by removeHopByHopEntries() */
     void removeConnectionHeaderEntries();
+    /// either finds the end of headers or returns false
+    /// If the end was found:
+    /// *parse_start points to the first character after the header delimiter
+    /// *blk_start points to the first header character (i.e. old parse_start value)
+    /// *blk_end points to the first header delimiter character (CR or LF in CR?LF).
+    /// If block starts where it ends, then there are no fields in the header.
+    static bool Isolate(const char **parse_start, size_t l, const char **blk_start, const char **blk_end);
+    bool needUpdate(const HttpHeader *fresh) const;
+    bool skipUpdateHeader(const Http::HdrType id) const;
+    void updateWarnings();
 
 private:
-    HttpHeaderEntry *findLastEntry(http_hdr_type id) const;
+    HttpHeaderEntry *findLastEntry(Http::HdrType id) const;
+    bool conflictingContentLength_; ///< found different Content-Length fields
 };
 
 int httpHeaderParseQuotedString(const char *start, const int len, String *val);
 
-/// quotes string using RFC 2616 quoted-string rules
-String httpHeaderQuoteString(const char *raw);
+/// quotes string using RFC 7230 quoted-string rules
+SBuf httpHeaderQuoteString(const char *raw);
 
-int httpHeaderHasByNameListMember(const HttpHeader * hdr, const char *name, const char *member, const char separator);
-void httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMask * denied_mask);
-void httpHeaderCalcMask(HttpHeaderMask * mask, http_hdr_type http_hdr_type_enums[], size_t count);
+void httpHeaderCalcMask(HttpHeaderMask * mask, Http::HdrType http_hdr_type_enums[], size_t count);
 
 inline bool
 HttpHeader::chunked() const
 {
-    return has(HDR_TRANSFER_ENCODING) &&
-           hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',');
+    return has(Http::HdrType::TRANSFER_ENCODING) &&
+           hasListMember(Http::HdrType::TRANSFER_ENCODING, "chunked", ',');
 }
 
 void httpHeaderInitModule(void);
-void httpHeaderCleanModule(void);
 
 #endif /* SQUID_HTTPHEADER_H */
+