LCOV - code coverage report
Current view: top level - edhttp - cache_control.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 226 0.0 %
Date: 2022-07-09 10:44:38 Functions: 0 44 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13