LCOV - code coverage report
Current view: top level - snapwebsites - cache_control.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 246 0.4 %
Date: 2019-12-15 17:13:15 Functions: 2 52 3.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Snap Websites Server -- handle Cache-Control settings
       2             : // Copyright (c) 2011-2019  Made to Order Software Corp.  All Rights Reserved
       3             : //
       4             : // This program is free software; you can redistribute it and/or modify
       5             : // it under the terms of the GNU General Public License as published by
       6             : // the Free Software Foundation; either version 2 of the License, or
       7             : // (at your option) any later version.
       8             : //
       9             : // This program is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             : // GNU General Public License for more details.
      13             : //
      14             : // You should have received a copy of the GNU General Public License
      15             : // along with this program; if not, write to the Free Software
      16             : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      17             : 
      18             : // self
      19             : //
      20             : #include "snapwebsites/cache_control.h"
      21             : 
      22             : // snapwebsites lib
      23             : //
      24             : #include "snapwebsites/http_strings.h"
      25             : #include "snapwebsites/log.h"
      26             : 
      27             : // snapdev lib
      28             : //
      29             : #include <snapdev/not_reached.h>
      30             : 
      31             : // boost lib
      32             : //
      33             : #include <boost/algorithm/string.hpp>
      34             : 
      35             : 
      36             : // last include
      37             : //
      38             : #include <snapdev/poison.h>
      39             : 
      40             : 
      41             : namespace snap
      42             : {
      43             : 
      44             : 
      45             : /** \brief Initialize a cache control object with defaults.
      46             :  *
      47             :  * This function initialize this cache control object with the
      48             :  * defaults and returns.
      49             :  *
      50             :  * You may later apply various changes to the cache control data
      51             :  * using the set_...() functions and the set_cache_info() if you
      52             :  * have cache control data in the form of a standard HTTP string.
      53             :  */
      54           0 : cache_control_settings::cache_control_settings()
      55             : {
      56           0 : }
      57             : 
      58             : 
      59             : /** \brief Initializes a cache control object with the specified info.
      60             :  *
      61             :  * This function initialize this cache control object with the defaults
      62             :  * and then applies the \p info parameters to the controls if \p info is
      63             :  * not an empty string.
      64             :  *
      65             :  * \param[in] info  The new cache control information to assign to this object.
      66             :  * \param[in] internal_setup  Whether to allow our special '!' syntax.
      67             :  *
      68             :  * \sa set_cache_info()
      69             :  */
      70           0 : cache_control_settings::cache_control_settings(QString const & info, bool const internal_setup)
      71             : {
      72           0 :     set_cache_info(info, internal_setup);
      73           0 : }
      74             : 
      75             : 
      76             : /** \brief Reset all the cache information to their defaults.
      77             :  *
      78             :  * This function resets all the cache information to their defaults so
      79             :  * the object looks as if it just got initialized.
      80             :  */
      81           0 : void cache_control_settings::reset_cache_info()
      82             : {
      83           0 :     f_max_age = 0;
      84           0 :     f_max_stale = IGNORE_VALUE;
      85           0 :     f_min_fresh = IGNORE_VALUE;
      86           0 :     f_must_revalidate = true;
      87           0 :     f_no_cache = false;
      88           0 :     f_no_store = true;
      89           0 :     f_no_transform = false;
      90           0 :     f_only_if_cached = false;
      91           0 :     f_private = false;
      92           0 :     f_public = false;
      93           0 :     f_s_maxage = IGNORE_VALUE;
      94           0 : }
      95             : 
      96             : 
      97             : /** \brief Set the cache information parsed from the \p info parameter.
      98             :  *
      99             :  * This function parses the \p info string for new cache definitions.
     100             :  * The \p info string may be empty in which case nothing is modified.
     101             :  * It is expected to be the string found in a Cache-Control header
     102             :  * sent by the client.
     103             :  *
     104             :  * If you want to start from scratch, you may call reset_cache_info()
     105             :  * first. You can also use a brand new object and then copy it since
     106             :  * the copy operator is available.
     107             :  *
     108             :  * The 'must-revalidate' and 'no-store' are set by default. Unfortunately
     109             :  * that would mean the page setup capability would not be able to ever
     110             :  * clear those two flags. That would mean you could never use a full
     111             :  * permanent cache definition. Instead we offer an extension to the
     112             :  * flags and allow one to add a '!' in front of the names as in:
     113             :  * '!no-cache'. This way you can force the 'no-cache' flag to false
     114             :  * instead of the default of true.
     115             :  *
     116             :  * \todo
     117             :  * Determine whether any error in the field should be considered fatal and
     118             :  * thus react by ignoring the entire \p info parameter. It seems that the
     119             :  * HTTP specification asks us to do so... (i.e. ignore all when any one
     120             :  * flag is not understood.) However, it seems that most browsers implement
     121             :  * such things the other way around: try to retrieve the maximum amount of
     122             :  * information as possible and use whatever they understand from that.
     123             :  *
     124             :  * \todo
     125             :  * Determine whether we should accept certain parameters only once.
     126             :  * Especially those that include values (i.e. max-age=123) because
     127             :  * the current implementation only takes the last one in account when
     128             :  * we probably should remember the first one (within one \p info string).
     129             :  *
     130             :  * \todo
     131             :  * Add support for private and no-cache parameters (server side only).
     132             :  *
     133             :  * \param[in] info  The new cache control information to assign to this object.
     134             :  * \param[in] internal_setup  Whether to allow our special '!' syntax.
     135             :  */
     136           0 : void cache_control_settings::set_cache_info(QString const & info, bool const internal_setup)
     137             : {
     138             :     // TODO: we want the weighted HTTP strings to understand
     139             :     //       parameters with values assigned and more than the
     140             :     //       q=xxx then we can update this code to better test
     141             :     //       what we are dealing with...
     142             : 
     143             :     // parse the data with the weighted HTTP string implementation
     144             :     //
     145           0 :     http_strings::WeightedHttpString client_cache_control(info);
     146             : 
     147             :     // no go through the list of parts and handle them appropriately
     148             :     //
     149           0 :     http_strings::WeightedHttpString::part_t::vector_t const & cache_control_parts(client_cache_control.get_parts());
     150           0 :     for(auto const & c : cache_control_parts)
     151             :     {
     152             :         // get the part name
     153             :         //
     154           0 :         QString name(c.get_name());
     155             : 
     156           0 :         bool negate(false);
     157           0 :         if(internal_setup)
     158             :         {
     159           0 :             negate = name[0].unicode() == '!';
     160           0 :             if(negate)
     161             :             {
     162             :                 // remove the negate flag
     163             :                 //
     164           0 :                 name = name.mid(1);
     165             :             }
     166             :         }
     167             : 
     168           0 :         if(name.isEmpty())
     169             :         {
     170           0 :             continue;
     171             :         }
     172             : 
     173             :         // TODO: add code to check whether 'negate' (!) was used with
     174             :         //       an item that does not support it
     175             : 
     176             :         // do a switch first to save a tad bit of time
     177           0 :         switch(name[0].unicode())
     178             :         {
     179           0 :         case 'i':
     180           0 :             if(name == "immutable")
     181             :             {
     182           0 :                 set_immutable(!negate);
     183             :             }
     184           0 :             break;
     185             : 
     186           0 :         case 'm':
     187           0 :             if(name == "max-age")
     188             :             {
     189           0 :                 set_max_age(c.get_value());
     190             :             }
     191           0 :             else if(name == "max-stale")
     192             :             {
     193           0 :                 QString const & value(c.get_value());
     194           0 :                 if(value.isEmpty())
     195             :                 {
     196             :                     // any stale data can be returned
     197             :                     //
     198           0 :                     set_max_stale(0);
     199             :                 }
     200             :                 else
     201             :                 {
     202           0 :                     set_max_stale(value);
     203             :                 }
     204             :             }
     205           0 :             else if(name == "min-fresh")
     206             :             {
     207           0 :                 set_min_fresh(c.get_value());
     208             :             }
     209           0 :             else if(name == "must-revalidate")
     210             :             {
     211           0 :                 set_must_revalidate(!negate);
     212             :             }
     213           0 :             break;
     214             : 
     215           0 :         case 'n':
     216           0 :             if(name == "no-cache")
     217             :             {
     218           0 :                 QString const & value(c.get_value());
     219           0 :                 if(value.isEmpty())
     220             :                 {
     221           0 :                     set_no_cache(!negate);
     222             :                 }
     223             :                 else
     224             :                 {
     225             :                     // list of fields that require revalidation
     226             :                     //
     227           0 :                     snap_string_list const list(value.split(","));
     228           0 :                     for(auto const & l : list)
     229             :                     {
     230           0 :                         add_revalidate_field_name(l);
     231             :                     }
     232             :                 }
     233             :             }
     234           0 :             else if(name == "no-store")
     235             :             {
     236           0 :                 set_no_store(!negate);
     237             :             }
     238           0 :             else if(name == "no-transform")
     239             :             {
     240           0 :                 set_no_transform(!negate);
     241             :             }
     242           0 :             break;
     243             : 
     244           0 :         case 'o':
     245           0 :             if(name == "only-if-cached")
     246             :             {
     247           0 :                 set_only_if_cached(!negate);
     248             :             }
     249           0 :             break;
     250             : 
     251           0 :         case 'p':
     252           0 :             if(name == "private")
     253             :             {
     254           0 :                 QString const & value(c.get_value());
     255           0 :                 if(value.isEmpty())
     256             :                 {
     257           0 :                     set_private(!negate);
     258             :                 }
     259             :                 else
     260             :                 {
     261             :                     // list of fields that require revalidation
     262             :                     //
     263           0 :                     snap_string_list list(value.split(","));
     264           0 :                     for(auto l : list)
     265             :                     {
     266           0 :                         add_private_field_name(l);
     267             :                     }
     268             :                 }
     269             :             }
     270           0 :             else if(name == "proxy-revalidate")
     271             :             {
     272           0 :                 set_proxy_revalidate(!negate);
     273             :             }
     274           0 :             else if(name == "public")
     275             :             {
     276           0 :                 set_public(!negate);
     277             :             }
     278           0 :             break;
     279             : 
     280           0 :         case 's':
     281           0 :             if(name == "s-maxage")
     282             :             {
     283           0 :                 set_s_maxage(c.get_value());
     284             :             }
     285           0 :             break;
     286             : 
     287             :         }
     288             :     }
     289           0 : }
     290             : 
     291             : 
     292             : /** \brief Set the must-revalidate to true or false.
     293             :  *
     294             :  * This function should only be called with 'true' to request
     295             :  * that the client revalidate the data each time it wants to
     296             :  * access it.
     297             :  *
     298             :  * However, the flag is set to 'true' by default, so really it
     299             :  * is only useful if you want to set the parameter to 'false'.
     300             :  *
     301             :  * \note
     302             :  * This flag may appear in the server response.
     303             :  *
     304             :  * \param[in] must_revalidate  Whether the client should revalidate that
     305             :  *                             specific content on each page load.
     306             :  *
     307             :  * \sa get_must_revalidate()
     308             :  */
     309           0 : void cache_control_settings::set_must_revalidate(bool const must_revalidate)
     310             : {
     311           0 :     f_must_revalidate = must_revalidate;
     312           0 : }
     313             : 
     314             : 
     315             : /** \brief Get the current value of the must-revalidate flag.
     316             :  *
     317             :  * This function returns the current value of the must-revalidate
     318             :  * flag.
     319             :  *
     320             :  * \note
     321             :  * This flag may appear in the server response.
     322             :  *
     323             :  * \return true if the must-revalidate flag is to be specified in the
     324             :  *         Cache-Control field.
     325             :  *
     326             :  * \sa set_must_revalidate()
     327             :  */
     328           0 : bool cache_control_settings::get_must_revalidate() const
     329             : {
     330           0 :     return f_must_revalidate;
     331             : }
     332             : 
     333             : 
     334             : /** \brief Set the 'private' flag to true or false.
     335             :  *
     336             :  * Any page that is private, and thus should not be saved in a
     337             :  * shared cache (i.e. proxies), must be assigned the private
     338             :  * flag, so this function must be called with true.
     339             :  *
     340             :  * Note that does not encrypt the data in any way. It just adds
     341             :  * the private flag to the Cache-Control header. If you need to
     342             :  * encrypt the data, make sure to enforce HTTPS before returning
     343             :  * a reply with secret data.
     344             :  *
     345             :  * \note
     346             :  * This flag may appear in the server response.
     347             :  *
     348             :  * \param[in] private_cache  Whether intermediate, shared, proxy caches
     349             :  *                           are allowed to cache this data.
     350             :  *
     351             :  * \sa get_private()
     352             :  */
     353           0 : void cache_control_settings::set_private(bool const private_cache)
     354             : {
     355           0 :     f_private = private_cache;
     356           0 : }
     357             : 
     358             : 
     359             : /** \brief Get the current value of the 'private' flag.
     360             :  *
     361             :  * This function returns the current value of the 'private'
     362             :  * flag.
     363             :  *
     364             :  * Note that 'private' has priority over 'public'. So if 'private'
     365             :  * is true, 'public' is ignored. For this reason you should only
     366             :  * set those flags to true and never attempt to reset them to
     367             :  * false. Similarly, the 'no-cache' and 'no-store' have priority
     368             :  * over the 'private' flag.
     369             :  *
     370             :  * \note
     371             :  * This flag may appear in the server response.
     372             :  *
     373             :  * \return true if the 'private' flag is to be specified in the
     374             :  *         Cache-Control field.
     375             :  *
     376             :  * \sa set_private()
     377             :  */
     378           0 : bool cache_control_settings::get_private() const
     379             : {
     380           0 :     return f_private;
     381             : }
     382             : 
     383             : 
     384             : /** \brief Set 'proxy-revalidate' to true or false.
     385             :  *
     386             :  * This function should only be called with 'true' to request
     387             :  * that proxy caches revalidate the data each time a client
     388             :  * asks for the data.
     389             :  *
     390             :  * You may instead want to use the 's-maxage' field.
     391             :  *
     392             :  * \note
     393             :  * This flag may appear in the server response.
     394             :  *
     395             :  * \param[in] proxy_revalidate  Whether proxy caches should revalidate that
     396             :  *                              specific content.
     397             :  *
     398             :  * \sa get_proxy_revalidate()
     399             :  */
     400           0 : void cache_control_settings::set_proxy_revalidate(bool const proxy_revalidate)
     401             : {
     402           0 :     f_proxy_revalidate = proxy_revalidate;
     403           0 : }
     404             : 
     405             : 
     406             : /** \brief Set whether the resource is immutable or not.
     407             :  *
     408             :  * This function sets whether the resource is immutable. Browsers that
     409             :  * understand this flag will never check the server again for that
     410             :  * specific resource as long as they keep it in their caches.
     411             :  *
     412             :  * Immutable means that it will never change. This is true for all
     413             :  * our CSS and JS files because these are versioned and any changes
     414             :  * to those files require a change in their version.
     415             :  *
     416             :  * \param[in] immutable  Whether the file is immutable or not.
     417             :  */
     418           0 : void cache_control_settings::set_immutable(bool const immutable)
     419             : {
     420           0 :     f_immutable = immutable;
     421           0 : }
     422             : 
     423             : 
     424             : /** \brief Get whether the data was marked immutable.
     425             :  *
     426             :  * This function returns true if the data attached to that resource
     427             :  * is considered immutable.
     428             :  *
     429             :  * For example, JS and CSS files are always considered immutable. This
     430             :  * is because we have a version and if you want to modify those files,
     431             :  * you must increase the version accordingly.
     432             :  *
     433             :  * Browsers that support the immutable flag never check the server
     434             :  * again because the file will be saved permanently in their caches.
     435             :  *
     436             :  * \return true if the resource is considered immutable.
     437             :  */
     438           0 : bool cache_control_settings::get_immutable() const
     439             : {
     440           0 :     return f_immutable;
     441             : }
     442             : 
     443             : 
     444             : /** \brief Get the current value of the 'proxy-revalidate' flag.
     445             :  *
     446             :  * This function returns the current value of the 'proxy-revalidate'
     447             :  * flag.
     448             :  *
     449             :  * Note that 'must-revalidate' has priority and if specified, the
     450             :  * 'proxy-revalidate' is ignored since the proxy-cache should
     451             :  * honor the 'must-revalidate' anyway. However, this function
     452             :  * directly returns the value of the 'proxy-revalidate' flag.
     453             :  *
     454             :  * \note
     455             :  * This flag may appear in the server response.
     456             :  *
     457             :  * \return true if the 'proxy-revalidate' flag is to be specified in the
     458             :  *         Cache-Control field.
     459             :  *
     460             :  * \sa set_proxy_revalidate()
     461             :  */
     462           0 : bool cache_control_settings::get_proxy_revalidate() const
     463             : {
     464           0 :     return f_proxy_revalidate;
     465             : }
     466             : 
     467             : 
     468             : /** \brief Set the 'public' flag to true or false.
     469             :  *
     470             :  * Any page that is public, and thus can be saved in a public shared
     471             :  * cache (i.e. proxy caches).
     472             :  *
     473             :  * Snap! detects whether a page is accessible by a visitor, if so
     474             :  * it sets the public flag automatically. So you should not have
     475             :  * to set this flag unless somehow your page is public and the Snap!
     476             :  * test could fail or you know that your pages are always public
     477             :  * and thus you could avoid having to check the permissions.
     478             :  *
     479             :  * Note that if the 'private' flag is set to true, then the 'public'
     480             :  * flag is ignored. Further, if the 'no-cache' or 'no-store' flags
     481             :  * are set, then 'public' and 'private' are ignored.
     482             :  *
     483             :  * \note
     484             :  * This flag may appear in the server response.
     485             :  *
     486             :  * \param[in] public_cache  Whether proxy caches can cache this content.
     487             :  *
     488             :  * \sa get_public()
     489             :  */
     490           0 : void cache_control_settings::set_public(bool const public_cache)
     491             : {
     492           0 :     f_public = public_cache;
     493           0 : }
     494             : 
     495             : 
     496             : /** \brief Get the current value of the 'public' flag.
     497             :  *
     498             :  * This function returns the current value of the 'public'
     499             :  * flag.
     500             :  *
     501             :  * Note that 'private' has priority over 'public'. So if 'private'
     502             :  * is true, 'public' is ignored. Similarly, the 'no-cache' and
     503             :  * 'no-store' have priority over the 'private' flag. However, this
     504             :  * function directly returns the 'public' flag.
     505             :  *
     506             :  * \note
     507             :  * This flag may appear in the server response.
     508             :  *
     509             :  * \return true if the 'public' flag is to be specified in the
     510             :  *         Cache-Control field.
     511             :  *
     512             :  * \sa set_public()
     513             :  */
     514           0 : bool cache_control_settings::get_public() const
     515             : {
     516           0 :     return f_public;
     517             : }
     518             : 
     519             : 
     520             : /** \brief Add a field name that needs to get revalidated by proxy caches.
     521             :  *
     522             :  * The Cache-Control header can include a no-cache parameter that includes
     523             :  * a list of field names that should not be cached and be revalidated
     524             :  * whenever a new client request is received.
     525             :  *
     526             :  * Note that means there are three possibilities with the no-cache parameters:
     527             :  *
     528             :  * \li the parameter is not present, caching may still not be allowed
     529             :  *     (i.e. max-age=0)
     530             :  * \li the parameter is present on its own, absolutely no caching is possible
     531             :  * \li the parameter is set to a list of field names, in which case caching
     532             :  *     is allowed, but the specified fields must be revalidated from the
     533             :  *     server (and should probably not be saved in the cache)
     534             :  *
     535             :  * \note
     536             :  * If the string is empty after left and right trimming the request to
     537             :  * add a field name is ignored.
     538             :  *
     539             :  * References:
     540             :  *
     541             :  * https://tools.ietf.org/html/rfc7234#section-5.2.2
     542             :  *
     543             :  * \param[in] field_name  The name of the HTTP header field which needs to
     544             :  *                        never be cached.
     545             :  *
     546             :  * \sa add_private_field_name()
     547             :  */
     548           0 : void cache_control_settings::add_revalidate_field_name(std::string const & field_name)
     549             : {
     550             :     // we just have to insert, it will be inserted just once
     551             :     //
     552           0 :     std::string name(boost::trim_copy(field_name));
     553           0 :     if(!name.empty())
     554             :     {
     555           0 :         f_revalidate_field_names.insert(name);
     556             :     }
     557           0 : }
     558             : 
     559             : 
     560             : /** \brief Add a field name that needs to never be cached.
     561             :  *
     562             :  * This function is an overload of the add_never_cache_field_name() with
     563             :  * an std::string parameter.
     564             :  *
     565             :  * \param[in] field_name  The name of the HTTP header field which needs to
     566             :  *                        never be cached.
     567             :  */
     568           0 : void cache_control_settings::add_revalidate_field_name(QString const & field_name)
     569             : {
     570           0 :     add_revalidate_field_name(std::string(field_name.toUtf8().data()));
     571           0 : }
     572             : 
     573             : 
     574             : /** \brief Add a field name that needs to never be cached.
     575             :  *
     576             :  * This function is an overload of the add_never_cache_field_name() with
     577             :  * an std::string parameter.
     578             :  *
     579             :  * \note
     580             :  * The function accepts a nullptr and ignores the request in that situation.
     581             :  *
     582             :  * \param[in] field_name  The name of the HTTP header field which needs to
     583             :  *                        never be cached.
     584             :  */
     585           0 : void cache_control_settings::add_revalidate_field_name(char const * field_name)
     586             : {
     587           0 :     if(field_name != nullptr)
     588             :     {
     589           0 :         add_revalidate_field_name(std::string(field_name));
     590             :     }
     591           0 : }
     592             : 
     593             : 
     594             : /** \brief Retrieve the existing list of field names to never cache.
     595             :  *
     596             :  * The Cache-Control field can include a no-cache="<list of field names>".
     597             :  * This is that list.
     598             :  *
     599             :  * By default this list is empty (Contrary to the private list which
     600             :  * includes the "Set-Cookie".)
     601             :  *
     602             :  * For certain pages that require the "Set-Cookie" or some other user
     603             :  * fields, such should be added to this list. That way the cache will
     604             :  * make sure to revalidate the page conditionally.
     605             :  *
     606             :  * Other fields that are specific to a user need to be added to this
     607             :  * list with one of the add_revalidate_field_name() functions.
     608             :  *
     609             :  * \return A list of field names.
     610             :  */
     611           0 : cache_control_settings::tags_t const & cache_control_settings::get_revalidate_field_names() const
     612             : {
     613           0 :     return f_revalidate_field_names;
     614             : }
     615             : 
     616             : 
     617             : /** \brief Add a field name that needs to remain private.
     618             :  *
     619             :  * The Cache-Control header can include a private parameter that includes
     620             :  * a list of field names that need to not be cached, except by private
     621             :  * caches (i.e. client browser).
     622             :  *
     623             :  * Note that means there are three possibilities with the private parameters:
     624             :  *
     625             :  * \li the parameter is not present, the data is considered private anyway
     626             :  * \li the parameter is present on its own, all data is considered private
     627             :  * \li the parameter is set to a list of field names, in which case caching
     628             :  *     is allowed, but the specified fields must be removed from the HTTP
     629             :  *     header before caching the header
     630             :  *
     631             :  * Note that this is different from the no-cache parameter which requires
     632             :  * a hit to the server to revalidate the header. In case of the private
     633             :  * parameter, no revalidation is required. We can simply send the cache
     634             :  * without the private fields (which with Snap! C++ is fine for pretty
     635             :  * much all our attachments.)
     636             :  *
     637             :  * \note
     638             :  * If the string is empty after left and right trimming the request to
     639             :  * add a field name is ignored.
     640             :  *
     641             :  * References:
     642             :  *
     643             :  * https://tools.ietf.org/html/rfc7234#section-5.2.2
     644             :  *
     645             :  * \param[in] field_name  The name of the HTTP header field which needs to
     646             :  *                        never be cached.
     647             :  *
     648             :  * \sa add_revalidate_field_name()
     649             :  */
     650           0 : void cache_control_settings::add_private_field_name(std::string const & field_name)
     651             : {
     652             :     // we just have to insert, it will be inserted just once
     653             :     //
     654           0 :     std::string name(boost::trim_copy(field_name));
     655           0 :     if(!name.empty())
     656             :     {
     657           0 :         f_private_field_names.insert(name);
     658             :     }
     659           0 : }
     660             : 
     661             : 
     662             : /** \brief Add a field name that needs to never be cached.
     663             :  *
     664             :  * This function is an overload of the add_private_field_name() with
     665             :  * an std::string parameter.
     666             :  *
     667             :  * \param[in] field_name  The name of the HTTP header field which needs to
     668             :  *                        never be cached.
     669             :  */
     670           0 : void cache_control_settings::add_private_field_name(QString const & field_name)
     671             : {
     672           0 :     add_private_field_name(std::string(field_name.toUtf8().data()));
     673           0 : }
     674             : 
     675             : 
     676             : /** \brief Add a field name that needs to never be cached.
     677             :  *
     678             :  * This function is an overload of the add_private_field_name() with
     679             :  * an std::string parameter.
     680             :  *
     681             :  * \note
     682             :  * The function accepts a nullptr and ignores the request in that situation.
     683             :  *
     684             :  * \param[in] field_name  The name of the HTTP header field which needs to
     685             :  *                        never be cached.
     686             :  */
     687           0 : void cache_control_settings::add_private_field_name(char const * field_name)
     688             : {
     689           0 :     if(field_name != nullptr)
     690             :     {
     691           0 :         add_private_field_name(std::string(field_name));
     692             :     }
     693           0 : }
     694             : 
     695             : 
     696             : /** \brief Retrieve the existing list of field names to never cache.
     697             :  *
     698             :  * The Cache-Control field can include a private="<list of field names>".
     699             :  * This is that list.
     700             :  *
     701             :  * By default, this list is set to "Set-Cookie" which is more than likely
     702             :  * a field that include many user specific data such as a session
     703             :  * identifier.
     704             :  *
     705             :  * Other fields that are specific to a user need to be added to this
     706             :  * list with one of the add_private_field_name() functions.
     707             :  *
     708             :  * \return A list of field names.
     709             :  */
     710           0 : cache_control_settings::tags_t const & cache_control_settings::get_private_field_names() const
     711             : {
     712           0 :     return f_private_field_names;
     713             : }
     714             : 
     715             : 
     716             : /** \brief Add a tag to the existing list of tags.
     717             :  *
     718             :  * This function adds the specified tag_name parameter to the list of
     719             :  * tags to send to the client. This is used by CDN systems to allow
     720             :  * for segregation of files to be cached.
     721             :  *
     722             :  * Note that a page which cache is turned off (i.e. Cache-Control has
     723             :  * the no-cache parameter set) does not get tagged. These tags will be
     724             :  * ignored in that situation.
     725             :  *
     726             :  * By default we use the "Cache-Tag" HTTP header as defined by CloudFlare.
     727             :  * The name can be changed in the snapserver.conf file. You may also
     728             :  * add multiple names. Drupal uses "X-Drupal-Cache-Tags". Akamai uses
     729             :  * "Edge-Cache-Tag".
     730             :  *
     731             :  * References:
     732             :  *
     733             :  * https://support.cloudflare.com/hc/en-us/articles/206596608-How-to-Purge-Cache-Using-Cache-Tags-Enterprise-only-
     734             :  *
     735             :  * https://www.drupal.org/docs/8/api/cache-api/cache-tags
     736             :  *
     737             :  * https://learn.akamai.com/en-us/webhelp/fast-purge/fast-purge/GUID-9AEF6978-697F-410C-A347-8155FDB535C8.html
     738             :  *
     739             :  * \param[in] tag_name  The name of the tag to add to the list.
     740             :  */
     741           0 : void cache_control_settings::add_tag(std::string const & tag_name)
     742             : {
     743             :     // we just have to insert, it will be inserted just once
     744             :     //
     745           0 :     f_tags.insert(tag_name);
     746           0 : }
     747             : 
     748             : 
     749             : /** \brief Add a tag to the existing list of tags.
     750             :  *
     751             :  * This function adds the specified tag_name parameter to the list
     752             :  * of tags to send to proxy caches.
     753             :  *
     754             :  * This is an overload version of the add_tag() with a std::string.
     755             :  *
     756             :  * \param[in] tag_name  The name of the tag to add to the list.
     757             :  */
     758           0 : void cache_control_settings::add_tag(QString const & tag_name)
     759             : {
     760           0 :     add_tag(std::string(tag_name.toUtf8().data()));
     761           0 : }
     762             : 
     763             : 
     764             : /** \brief Add a tag to the existing list of tags.
     765             :  *
     766             :  * This function adds the specified tag_name parameter to the list
     767             :  * of tags to send to proxy caches.
     768             :  *
     769             :  * This is an overload version of the add_tag() with a std::string.
     770             :  *
     771             :  * \param[in] tag_name  The name of the tag to add to the list.
     772             :  */
     773           0 : void cache_control_settings::add_tag(char const * tag_name)
     774             : {
     775           0 :     add_tag(std::string(tag_name));
     776           0 : }
     777             : 
     778             : 
     779             : /** \brief Retrieve the existing list of cache tags.
     780             :  *
     781             :  * Various CDN systems accept a cache tag. This function returns the
     782             :  * list of tags that will be used with that HTTP header.
     783             :  *
     784             :  * By default, this is expected to be empty and no tag will be added
     785             :  * anywhere.
     786             :  *
     787             :  * \return A list of tag names.
     788             :  */
     789           0 : cache_control_settings::tags_t const & cache_control_settings::get_tags() const
     790             : {
     791           0 :     return f_tags;
     792             : }
     793             : 
     794             : 
     795             : /** \brief Set the maximum number of seconds to cache this data.
     796             :  *
     797             :  * This function requests for the specified data to be cached
     798             :  * for that many seconds.
     799             :  *
     800             :  * By default the value of max-age is set to 0, meaning that the
     801             :  * data will not be cached.
     802             :  *
     803             :  * In order to create a cache on the client's side (and within proxies,)
     804             :  * the value can be set to a number of seconds between 1 and AGE_MAXIMUM.
     805             :  * Any value under 60 is probably not going to be very useful. Any
     806             :  * value larger than AGE_MAXIMUM (which is one year, as per HTTP/1.1)
     807             :  * is clamped to AGE_MAXIMUM.
     808             :  *
     809             :  * You may also set \p max_age to -1 in order for the system to ignore
     810             :  * the 'max-age' cache control parameter.
     811             :  *
     812             :  * \note
     813             :  * This flag may appear in the client request or the server response.
     814             :  *
     815             :  * \param[in] max_age  The maximum age the data can have before checking
     816             :  *                     the data again.
     817             :  *
     818             :  * \sa update_max_age()
     819             :  * \sa get_max_age()
     820             :  */
     821           0 : void cache_control_settings::set_max_age(int64_t const max_age)
     822             : {
     823           0 :     if(max_age >= AGE_MAXIMUM)
     824             :     {
     825             :         // 1 year in seconds
     826           0 :         f_max_age = AGE_MAXIMUM;
     827             :     }
     828           0 :     else if(max_age < 0)
     829             :     {
     830           0 :         f_max_age = IGNORE_VALUE;
     831             :     }
     832             :     else
     833             :     {
     834           0 :         f_max_age = max_age;
     835             :     }
     836           0 : }
     837             : 
     838             : 
     839             : /** \brief Set the 'max-age' field value from a string.
     840             :  *
     841             :  * This function accepts a string as input to setup the 'max-age'
     842             :  * field.
     843             :  *
     844             :  * The value may be set to IGNORE_VALUE if the string does not represent
     845             :  * a valid decimal number (no signs allowed.) It is also clamped to a
     846             :  * maximum of AGE_MAXIMUM.
     847             :  *
     848             :  * \param[in] max_age  The maximum age as a string.
     849             :  *
     850             :  * \sa update_max_age()
     851             :  * \sa get_max_age()
     852             :  */
     853           0 : void cache_control_settings::set_max_age(QString const & max_age)
     854             : {
     855             :     // in this case -1 is what we want in case of an error
     856             :     // and not 1 year in seconds... no other negative values
     857             :     // are possible so we are fine
     858           0 :     f_max_age = string_to_seconds(max_age);
     859           0 : }
     860             : 
     861             : 
     862             : /** \brief Update the maximum number of seconds to cache this data.
     863             :  *
     864             :  * This function keeps the smaller 'max-age' of the existing setup and
     865             :  * the new value specified to this function.
     866             :  *
     867             :  * Note that if the current value is IGNORE_VALUE, then the new maximum
     868             :  * is automatically used, whatever it is.
     869             :  *
     870             :  * Negative values are ignored.
     871             :  *
     872             :  * \param[in] max_age  The maximum age the data can have before the client
     873             :  *                     is expected to check the data again.
     874             :  *
     875             :  * \sa set_max_age()
     876             :  * \sa get_max_age()
     877             :  */
     878           0 : void cache_control_settings::update_max_age(int64_t max_age)
     879             : {
     880           0 :     if(max_age > AGE_MAXIMUM)
     881             :     {
     882             :         // 1 year in seconds
     883             :         //
     884           0 :         max_age = AGE_MAXIMUM;
     885             :     }
     886           0 :     f_max_age = minimum(f_max_age, max_age);
     887           0 : }
     888             : 
     889             : 
     890             : /** \brief Retrieve the current max-age field.
     891             :  *
     892             :  * The Cache-Control can specify how long the data being returned
     893             :  * can be cached for. The 'max-age' field defines that duration
     894             :  * in seconds.
     895             :  *
     896             :  * By default the data is marked as 'do not cache' (i.e. max-age
     897             :  * is set to zero.)
     898             :  *
     899             :  * This function may return IGNORE_VALUE in which case the
     900             :  * 'max-age' field is ignored.
     901             :  *
     902             :  * \note
     903             :  * This flag may appear in the client request or the server response.
     904             :  *
     905             :  * \return The number of seconds to cache the data or IGNORE_VALUE.
     906             :  *
     907             :  * \sa update_max_age()
     908             :  * \sa get_max_age()
     909             :  */
     910           0 : int64_t cache_control_settings::get_max_age() const
     911             : {
     912           0 :     return f_max_age;
     913             : }
     914             : 
     915             : 
     916             : /** \brief Set the 'no-cache' flag to true or false.
     917             :  *
     918             :  * This function should only be called with 'true' to request
     919             :  * that the client and intermediate caches do not cache any
     920             :  * of the data. This does not prevent the client to store
     921             :  * the data.
     922             :  *
     923             :  * When the client sets this field to true, it means that we
     924             :  * should regenerate the specified page data.
     925             :  *
     926             :  * \note
     927             :  * This flag may appear in the client request or the server response.
     928             :  *
     929             :  * \param[in] no_cache  Whether the client and intermediate caches
     930             :  *                      must not cache the data.
     931             :  *
     932             :  * \sa get_no_cache()
     933             :  */
     934           0 : void cache_control_settings::set_no_cache(bool const no_cache)
     935             : {
     936           0 :     f_no_cache = no_cache;
     937           0 : }
     938             : 
     939             : 
     940             : /** \brief Retrieve the 'no-cache' flag.
     941             :  *
     942             :  * This function returns the current value of the 'no-cache' flag.
     943             :  *
     944             :  * The system ignores the 'public' and 'private' flags when the
     945             :  * 'no-cache' flag is true.
     946             :  *
     947             :  * \note
     948             :  * This flag may appear in the client request or the server response.
     949             :  *
     950             :  * \return true if the 'no-cache' flag is to be specified in the
     951             :  *         Cache-Control field.
     952             :  *
     953             :  * \sa set_no_cache()
     954             :  */
     955           0 : bool cache_control_settings::get_no_cache() const
     956             : {
     957           0 :     return f_no_cache;
     958             : }
     959             : 
     960             : 
     961             : /** \brief Set the 'no-store' flag to true or false.
     962             :  *
     963             :  * This function sets the 'no-store' flag to true or false. This
     964             :  * flag means that any of the data in that request needs to be
     965             :  * transferred only and not stored anywhere except in 100%
     966             :  * temporary buffers on the client's machine.
     967             :  *
     968             :  * Further, shared/proxy caches should clear all the data bufferized
     969             :  * to process this request as soon as it is done with it.
     970             :  *
     971             :  * \note
     972             :  * This flag may appear in the client request or the server response.
     973             :  *
     974             :  * \param[in] no_store  Whether the data can be stored or not.
     975             :  *
     976             :  * \sa get_no_store()
     977             :  */
     978           0 : void cache_control_settings::set_no_store(bool const no_store)
     979             : {
     980           0 :     f_no_store = no_store;
     981           0 : }
     982             : 
     983             : 
     984             : /** \brief Retrieve the 'no-store' flag.
     985             :  *
     986             :  * This function returns the current 'no-store' flag status.
     987             :  *
     988             :  * In most cases, this flag is not required. It should be true
     989             :  * only on pages that include extremely secure content such
     990             :  * as a page recording the settings of an electronic payment
     991             :  * (i.e. the e-payment Paypal page allows you to enter your
     992             :  * Paypal identifiers and those should not be stored anywhere.)
     993             :  *
     994             :  * Since most of our HTML pages are already marked as 'no-cache',
     995             :  * the 'no-store' is generally not required.
     996             :  *
     997             :  * \note
     998             :  * This flag may appear in the client request or the server response.
     999             :  *
    1000             :  * \return true if the data in this request should not be stored
    1001             :  *         anywhere.
    1002             :  *
    1003             :  * \sa set_no_store()
    1004             :  */
    1005           0 : bool cache_control_settings::get_no_store() const
    1006             : {
    1007           0 :     return f_no_store;
    1008             : }
    1009             : 
    1010             : 
    1011             : /** \brief Set whether the data can be transformed.
    1012             :  *
    1013             :  * The 'no-transform' flag can be used to make sure that caches do
    1014             :  * not transform the data. This can also appear in the request from
    1015             :  * the client in which case an exact original is required.
    1016             :  *
    1017             :  * This is generally important only for document files that may be
    1018             :  * converted to a lousy format such as images that could be saved
    1019             :  * as JPEG images although we enforce it when the client sends us
    1020             :  * an AJAX request.
    1021             :  *
    1022             :  * \note
    1023             :  * This flag may appear in the client request or the server response.
    1024             :  *
    1025             :  * \param[in] no_transform  Set to true to retrieve the original document as is.
    1026             :  *
    1027             :  * \sa get_no_transform()
    1028             :  */
    1029           0 : void cache_control_settings::set_no_transform(bool const no_transform)
    1030             : {
    1031           0 :     f_no_transform = no_transform;
    1032           0 : }
    1033             : 
    1034             : 
    1035             : /** \brief Retrieve whether the data can be transformed.
    1036             :  *
    1037             :  * Check whether the client or the server are requesting that the data
    1038             :  * not be transformed. If true, then the original data should be
    1039             :  * transferred as is.
    1040             :  *
    1041             :  * \note
    1042             :  * This flag may appear in the client request or the server response.
    1043             :  *
    1044             :  * \return true if the 'no-transform' flag is set.
    1045             :  *
    1046             :  * \sa set_no_transform()
    1047             :  */
    1048           0 : bool cache_control_settings::get_no_transform() const
    1049             : {
    1050           0 :     return f_no_transform;
    1051             : }
    1052             : 
    1053             : 
    1054             : /** \brief Set the number of seconds to cache this data in shared caches.
    1055             :  *
    1056             :  * This function requests for the specified data to be cached
    1057             :  * for that many seconds in any shared caches between the client
    1058             :  * and the server. The client ignores that information.
    1059             :  *
    1060             :  * To use the maximum, call this function with AGE_MAXIMUM.
    1061             :  *
    1062             :  * To ignore this value, call this function with IGNORE_VALUE. This is
    1063             :  * the default value for this field.
    1064             :  *
    1065             :  * \note
    1066             :  * This flag may appear in the client request or the server response.
    1067             :  *
    1068             :  * \param[in] s_maxage  The maximum age the data can have before checking
    1069             :  *                      the source again.
    1070             :  *
    1071             :  * \sa update_s_maxage()
    1072             :  * \sa get_s_maxage()
    1073             :  */
    1074           0 : void cache_control_settings::set_s_maxage(int64_t const s_maxage)
    1075             : {
    1076           0 :     if(s_maxage >= AGE_MAXIMUM)
    1077             :     {
    1078           0 :         f_s_maxage = AGE_MAXIMUM;
    1079             :     }
    1080           0 :     else if(s_maxage < 0)
    1081             :     {
    1082           0 :         f_s_maxage = IGNORE_VALUE;
    1083             :     }
    1084             :     else
    1085             :     {
    1086           0 :         f_s_maxage = s_maxage;
    1087             :     }
    1088           0 : }
    1089             : 
    1090             : 
    1091             : /** \brief Set the 's-maxage' field value from a string.
    1092             :  *
    1093             :  * This function accepts a string as input to setup the 's-maxage'
    1094             :  * field.
    1095             :  *
    1096             :  * The value may be set to -1 if the string does not represent a valid
    1097             :  * decimal number (no signs allowed.) It will be clamped to a maximum
    1098             :  * of AGE_MAXIMUM.
    1099             :  *
    1100             :  * \param[in] s_maxage  The new maximum age defined as a string.
    1101             :  *
    1102             :  * \sa update_s_maxage()
    1103             :  * \sa get_s_maxage()
    1104             :  */
    1105           0 : void cache_control_settings::set_s_maxage(QString const & s_maxage)
    1106             : {
    1107             :     // in this case -1 is what we want in case of an error
    1108             :     // and not 1 year in seconds... no other negative values
    1109             :     // are possible so we are fine
    1110           0 :     f_s_maxage = string_to_seconds(s_maxage);
    1111           0 : }
    1112             : 
    1113             : 
    1114             : /** \brief Update the maximum number of seconds to cache this data on proxies.
    1115             :  *
    1116             :  * This function keeps the smaller maximum of the existing setup and
    1117             :  * the new value specified to this function.
    1118             :  *
    1119             :  * Note that if the current value is IGNORE_VALUE, then the new maximum
    1120             :  * is always used.
    1121             :  *
    1122             :  * Negative values are ignored.
    1123             :  *
    1124             :  * \param[in] s_maxage  The maximum age the data can have before checking
    1125             :  *                      the data again from shared proxy cache.
    1126             :  *
    1127             :  * \sa set_s_maxage()
    1128             :  * \sa get_s_maxage()
    1129             :  */
    1130           0 : void cache_control_settings::update_s_maxage(int64_t s_maxage)
    1131             : {
    1132           0 :     if(s_maxage >= AGE_MAXIMUM)
    1133             :     {
    1134             :         // 1 year in seconds
    1135             :         //
    1136           0 :         s_maxage = AGE_MAXIMUM;
    1137             :     }
    1138           0 :     f_s_maxage = minimum(f_s_maxage, s_maxage);
    1139           0 : }
    1140             : 
    1141             : 
    1142             : /** \brief Retrieve the current 's-maxage' field.
    1143             :  *
    1144             :  * The 'Cache-Control' HTTP header can specify how long the data
    1145             :  * being returned can be cached for in a shared cache. The
    1146             :  * 's-maxage' field defines that duration in seconds.
    1147             :  *
    1148             :  * By default shared caches are expected to use the 'max-age' parameter
    1149             :  * when the 's-maxage' parameter is not defined. So if the value is
    1150             :  * the same, you do not have to specified 's-maxage'.
    1151             :  *
    1152             :  * The value of 0 means that shared caches will not cache anything.
    1153             :  *
    1154             :  * \note
    1155             :  * This field may appear in the client request or the server response.
    1156             :  *
    1157             :  * \return The number of seconds to cache the data or IGNORE_VALUE.
    1158             :  *
    1159             :  * \sa set_s_maxage()
    1160             :  * \sa update_s_maxage()
    1161             :  */
    1162           0 : int64_t cache_control_settings::get_s_maxage() const
    1163             : {
    1164           0 :     return f_s_maxage;
    1165             : }
    1166             : 
    1167             : 
    1168             : /** \brief How long of a 'stale' is accepted by the client.
    1169             :  *
    1170             :  * The client may asks for data that is stale. Assuming that
    1171             :  * a cache may keep data after it became stale, the client may
    1172             :  * retrieve that data if they specified the stale parameter.
    1173             :  *
    1174             :  * A value of zero means that any stale data is acceptable.
    1175             :  * A greater value specifies the number of seconds after the
    1176             :  * normal cache threshold the data can be to be considered
    1177             :  * okay to be returned to the client.
    1178             :  *
    1179             :  * In general, this is for cache systems and not the server
    1180             :  * so our server generally ignores that data.
    1181             :  *
    1182             :  * You may use the AGE_MAXIMUM parameter to set the 'stale'
    1183             :  * parameter to the maximum possible.
    1184             :  *
    1185             :  * You may set the 'stale' parameter to IGNORE_VALUE in which
    1186             :  * case any possible user of the parameter has to ignore the
    1187             :  * value (do as if it was not specified).
    1188             :  *
    1189             :  * \note
    1190             :  * This flag may appear in the client request.
    1191             :  *
    1192             :  * \param[in] max_stale  The maximum number of seconds for the stale
    1193             :  *                       data to be before the request is forwarded
    1194             :  *                       to the server.
    1195             :  *
    1196             :  * \sa get_max_stale()
    1197             :  */
    1198           0 : void cache_control_settings::set_max_stale(int64_t const max_stale)
    1199             : {
    1200           0 :     if(max_stale >= AGE_MAXIMUM)
    1201             :     {
    1202           0 :         f_max_stale = AGE_MAXIMUM;
    1203             :     }
    1204           0 :     else if(max_stale < 0)
    1205             :     {
    1206           0 :         f_max_stale = IGNORE_VALUE;
    1207             :     }
    1208             :     else
    1209             :     {
    1210           0 :         f_max_stale = max_stale;
    1211             :     }
    1212           0 : }
    1213             : 
    1214             : 
    1215             : /** \brief Set the 'max-stale' field value from a string.
    1216             :  *
    1217             :  * This function accepts a string as input to setup the 'max-stale'
    1218             :  * field.
    1219             :  *
    1220             :  * The value may be set to IGNORE_VALUE if the string does not
    1221             :  * represent a valid decimal number (no signs allowed.)
    1222             :  *
    1223             :  * The value is clamped to a maximum of AGE_MAXIMUM.
    1224             :  *
    1225             :  * \param[in] max_stale  The 'max-stale' parameter as a string.
    1226             :  *
    1227             :  * \sa get_max_stale()
    1228             :  */
    1229           0 : void cache_control_settings::set_max_stale(QString const & max_stale)
    1230             : {
    1231           0 :     set_max_stale(string_to_seconds(max_stale));
    1232           0 : }
    1233             : 
    1234             : 
    1235             : /** \brief Retrieve the current maximum 'stale' value.
    1236             :  *
    1237             :  * This function returns the maximum number of seconds the client is
    1238             :  * willing to accept after the cache expiration date.
    1239             :  *
    1240             :  * So if your cache expires at 14:30:00 and the user makes a new
    1241             :  * request on 14:32:50 with a 'max-stale' value of 3600, then you
    1242             :  * may return the stale cache instead of regenerating it.
    1243             :  *
    1244             :  * Note that only shared caches are expected to return stale data.
    1245             :  * The server itself currently always regenerate the data as
    1246             :  * required.
    1247             :  *
    1248             :  * The stale value may be set to zero in which case the cache data
    1249             :  * is always returned if available.
    1250             :  *
    1251             :  * \note
    1252             :  * This flag may appear in the client request.
    1253             :  *
    1254             :  * \return The number of seconds the cache may be stale by before
    1255             :  *         regenerating it.
    1256             :  *
    1257             :  * \sa set_max_stale()
    1258             :  */
    1259           0 : int64_t cache_control_settings::get_max_stale() const
    1260             : {
    1261           0 :     return f_max_stale;
    1262             : }
    1263             : 
    1264             : 
    1265             : /** \brief Set the number of seconds of freshness required by the client.
    1266             :  *
    1267             :  * The freshness is the amount of seconds before the cache goes stale.
    1268             :  * So if the cache goes stale in 60 seconds and the freshness query
    1269             :  * is 3600, then the cache is ignored.
    1270             :  *
    1271             :  * Note that freshness cannot always be satisfied since a page cache
    1272             :  * duration ('max-age') may always be smaller than the specified
    1273             :  * freshness amount.
    1274             :  *
    1275             :  * You may set this parameter to its maximum using the AGE_MAXIMUM
    1276             :  * value.
    1277             :  *
    1278             :  * You may set this parameter to IGNORE_VALUE to mark it as being
    1279             :  * ignored (not set by client.)
    1280             :  *
    1281             :  * \note
    1282             :  * This flag may appear in the client request.
    1283             :  *
    1284             :  * \param[in] min_fresh  The minimum freshness in seconds.
    1285             :  *
    1286             :  * \sa get_min_fresh()
    1287             :  */
    1288           0 : void cache_control_settings::set_min_fresh(int64_t const min_fresh)
    1289             : {
    1290           0 :     if(min_fresh >= AGE_MAXIMUM)
    1291             :     {
    1292           0 :         f_min_fresh = AGE_MAXIMUM;
    1293             :     }
    1294           0 :     else if(min_fresh < 0)
    1295             :     {
    1296           0 :         f_min_fresh = IGNORE_VALUE;
    1297             :     }
    1298             :     else
    1299             :     {
    1300           0 :         f_min_fresh = min_fresh;
    1301             :     }
    1302           0 : }
    1303             : 
    1304             : 
    1305             : /** \brief Set the 'min-fresh' field value from a string.
    1306             :  *
    1307             :  * This function accepts a string as input to setup the 'min-fresh'
    1308             :  * field.
    1309             :  *
    1310             :  * The value may be set to INGORE_VALUE if the string does not represent
    1311             :  * a valid decimal number (no signs allowed.) It will be clamped to
    1312             :  * a maximum of AGE_MAXIMUM.
    1313             :  *
    1314             :  * \param[in] min_fresh  The minimum freshness required by the client.
    1315             :  *
    1316             :  * \sa get_min_fresh()
    1317             :  */
    1318           0 : void cache_control_settings::set_min_fresh(QString const & min_fresh)
    1319             : {
    1320           0 :     set_min_fresh(string_to_seconds(min_fresh));
    1321           0 : }
    1322             : 
    1323             : 
    1324             : /** \brief Retrieve the 'min-fresh' value from the Cache-Control.
    1325             :  *
    1326             :  * If the cache is to get stale within less than 'min-fresh' then
    1327             :  * the server is expected to recalculate the page.
    1328             :  *
    1329             :  * Pages that are given a 'max-age' of less than what 'min-fresh'
    1330             :  * is set at will react as fully dynamic pages (i.e. as if no
    1331             :  * caches were available.)
    1332             :  *
    1333             :  * \note
    1334             :  * This flag may appear in the client request.
    1335             :  *
    1336             :  * \return The number of seconds of freshness that are required.
    1337             :  *
    1338             :  * \sa set_min_fresh()
    1339             :  */
    1340           0 : int64_t cache_control_settings::get_min_fresh() const
    1341             : {
    1342           0 :     return f_min_fresh;
    1343             : }
    1344             : 
    1345             : 
    1346             : /** \brief Set the 'only-if-cached' flag.
    1347             :  *
    1348             :  * The 'only-if-cached' flag is used by clients with poor network
    1349             :  * connectivity to request any available data from any cache instead
    1350             :  * of gettings newer data.
    1351             :  *
    1352             :  * The server ignores that flag since the user connected to the server
    1353             :  * it would not make sense to not return a valid response from that
    1354             :  * point.
    1355             :  *
    1356             :  * \note
    1357             :  * This flag may appear in the client request.
    1358             :  *
    1359             :  * \param[in] only_if_cached  The new flag value.
    1360             :  *
    1361             :  * \sa get_only_if_cached()
    1362             :  */
    1363           0 : void cache_control_settings::set_only_if_cached(bool const only_if_cached)
    1364             : {
    1365           0 :     f_only_if_cached = only_if_cached;
    1366           0 : }
    1367             : 
    1368             : 
    1369             : /** \brief Retrieve the 'only-if-cached' flag.
    1370             :  *
    1371             :  * This function returns the current status of the 'only-if-cached' flag.
    1372             :  *
    1373             :  * The server ignores this flag since it is generally used so a client
    1374             :  * can request one of the in between caches to return any data they have
    1375             :  * available, instead of trying to reconnect to the server. However,
    1376             :  * the server may still check the flag and if true change the behavior.
    1377             :  * Yet, that would mean the cache behavior would change for all clients.
    1378             :  *
    1379             :  * Note that caches still do not return stale data unless the client
    1380             :  * also specifies the max-stale parameter.
    1381             :  *
    1382             :  * \code
    1383             :  *      Cache-Control: max-stale=0,only-if-cached
    1384             :  * \endcode
    1385             :  *
    1386             :  * \return Return true if the only-if-cached flag was specified in the
    1387             :  *         request.
    1388             :  *
    1389             :  * \sa set_only_if_cached()
    1390             :  */
    1391           0 : bool cache_control_settings::get_only_if_cached() const
    1392             : {
    1393           0 :     return f_only_if_cached;
    1394             : }
    1395             : 
    1396             : 
    1397             : /** \brief Convert a string to a number.
    1398             :  *
    1399             :  * This function returns a number as defined in a string. The input
    1400             :  * string must exclusively be composed of decimal digits.
    1401             :  *
    1402             :  * No plus or minus signs are allowed. If any character is not valid,
    1403             :  * then the function returns IGNORE_VALUE.
    1404             :  *
    1405             :  * If the value is larger than AGE_MAXIMUM, it will be clamped at
    1406             :  * AGE_MAXIMUM.
    1407             :  *
    1408             :  * \note
    1409             :  * The function only accepts decimal numbers.
    1410             :  *
    1411             :  * \param[in] max_age  The maximum age decimal number defined as a string.
    1412             :  *
    1413             :  * \return The number of seconds the string represents
    1414             :  *         or IGNORE_VALUE on errors.
    1415             :  */
    1416           0 : int64_t cache_control_settings::string_to_seconds(QString const & max_age)
    1417             : {
    1418           0 :     if(max_age.isEmpty())
    1419             :     {
    1420             :         // undefined / invalid (not 0)
    1421             :         //
    1422           0 :         return IGNORE_VALUE;
    1423             :     }
    1424             : 
    1425           0 :     QByteArray const utf8(max_age.toUtf8());
    1426           0 :     char const * s(utf8.data());
    1427           0 :     char const * const start(s);
    1428           0 :     int64_t result(0);
    1429           0 :     for(; *s != '\0'; ++s)
    1430             :     {
    1431           0 :         if(*s < '0'
    1432           0 :         || *s > '9'
    1433           0 :         || s - start > 9) // too large! (for 1 year in seconds we need 8 digits maximum)
    1434             :         {
    1435             :             // invalid
    1436             :             //
    1437           0 :             return IGNORE_VALUE;
    1438             :         }
    1439           0 :         result = result * 10 + *s - '0';
    1440             :     }
    1441             : 
    1442           0 :     return result > AGE_MAXIMUM ? AGE_MAXIMUM : result;
    1443             : }
    1444             : 
    1445             : 
    1446             : /** \brief Retrieve the smallest value of two.
    1447             :  *
    1448             :  * This special minimum function returns the smallest of two values,
    1449             :  * only if one of those values is IGNORE_VALUE, then it is ignored
    1450             :  * and the other is returned. Of course, if both are IGNORE_VALUE,
    1451             :  * you get IGNORE_VALUE as a result.
    1452             :  *
    1453             :  * \note
    1454             :  * This function is expected to be used with the 'max-age' and
    1455             :  * 's-maxage' numbers. These numbers are expected to be defined
    1456             :  * between 0 and AGE_MAXIMUM, or set to IGNORE_VALUE.
    1457             :  *
    1458             :  * \param[in] a  The left hand side value.
    1459             :  * \param[in] b  The right hand side value.
    1460             :  *
    1461             :  * \return The smallest of a and b, ignoring either if set to IGNORE_VALUE.
    1462             :  */
    1463           0 : int64_t cache_control_settings::minimum(int64_t const a, int64_t const b)
    1464             : {
    1465             :     // if a or b are -1, then return the other
    1466             :     //
    1467           0 :     if(a == IGNORE_VALUE)
    1468             :     {
    1469             :         // in this case the value may return -1
    1470             :         //
    1471           0 :         return b;
    1472             :     }
    1473           0 :     if(b == IGNORE_VALUE)
    1474             :     {
    1475           0 :         return a;
    1476             :     }
    1477             : 
    1478             :     // normal std::min() otherwise
    1479             :     //
    1480           0 :     return std::min(a, b);
    1481             : }
    1482             : 
    1483             : 
    1484           6 : } // namespace snap
    1485             : 
    1486             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13