LCOV - code coverage report
Current view: top level - edhttp - http_link.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 53 1.9 %
Date: 2022-07-09 10:44:38 Functions: 2 11 18.2 %
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             : 
      20             : // self
      21             : //
      22             : #include    "edhttp/http_link.h"
      23             : 
      24             : #include    "edhttp/exception.h"
      25             : #include    "edhttp/uri.h"
      26             : 
      27             : 
      28             : // C
      29             : //
      30             : //#include    <sys/time.h>
      31             : 
      32             : 
      33             : // last include
      34             : //
      35             : #include    <snapdev/poison.h>
      36             : 
      37             : 
      38             : 
      39             : namespace edhttp
      40             : {
      41             : 
      42             : 
      43             : 
      44             : /** \brief Initializes the link.
      45             :  *
      46             :  * This function initializes the link.
      47             :  *
      48             :  * \param[in] snap  The snap child creating this link.
      49             :  * \param[in] link  The URI for this link.
      50             :  * \param[in] rel  What the link represents (relative).
      51             :  *
      52             :  * \sa add_param()
      53             :  * \sa has_param()
      54             :  * \sa get_param()
      55             :  * \sa get_params()
      56             :  * \sa to_http_header()
      57             :  */
      58           0 : http_link::http_link(std::string const & link, std::string const & rel)
      59             :     : f_link(link)
      60           0 :     , f_rel(rel)
      61             : {
      62           0 :     if(f_link.empty())
      63             :     {
      64           0 :         throw link_parse_exception("the URI of a link cannot be empty.");
      65             :     }
      66           0 :     uri u;
      67           0 :     if(!u.set_uri(f_link))
      68             :     {
      69             :         // the snap_uri uses libtld so we arrive here if the TLD is not
      70             :         // considered valid
      71             :         //
      72           0 :         throw link_parse_exception("link URI is not valid.");
      73             :     }
      74           0 : }
      75             : 
      76             : 
      77             : /** \brief Retrieve the link "name".
      78             :  *
      79             :  * This function returns the relation string for this link. This is most
      80             :  * often viewed as the link name. In generatl, links are saved by name.
      81             :  * As a result, you cannot have two links with the same name.
      82             :  *
      83             :  * \return The "rel" string as passed to the constructor.
      84             :  */
      85           0 : std::string http_link::get_name() const
      86             : {
      87           0 :     return f_rel;
      88             : }
      89             : 
      90             : 
      91             : /** \brief Set whether to include this link on a redirect or not.
      92             :  *
      93             :  * Whenever Snap! generates a 301 or a 302, links do not get added to
      94             :  * the header (there are generally useless there in that situation.)
      95             :  *
      96             :  * By calling this function with true you indicate that it should be
      97             :  * added whether the process is about to redirect the client to another
      98             :  * page or not.
      99             :  *
     100             :  * See the shortcut implementation for an example where this is used.
     101             :  *
     102             :  * \param[in] redirect  Whether to include the link on a redirect.
     103             :  */
     104           0 : void http_link::set_redirect(bool redirect)
     105             : {
     106           0 :     f_redirect = redirect;
     107           0 : }
     108             : 
     109             : 
     110             : /** \brief Check whether to add this link on a redirect.
     111             :  *
     112             :  * By default links do not get added to the header if the request
     113             :  * ends up in a redirect.
     114             :  *
     115             :  * If this function returns true, then it will be added to the header.
     116             :  *
     117             :  * \return true if link is expected to be added on normal or redirect calls.
     118             :  */
     119           0 : bool http_link::get_redirect() const
     120             : {
     121           0 :     return f_redirect;
     122             : }
     123             : 
     124             : 
     125             : /** \brief Add a parameter to this link.
     126             :  *
     127             :  * Each link accept any number of parameter, although usually it will be
     128             :  * limited to just 2 or 3. The "rel" parameter is defined on construction
     129             :  * and cannot be re-added or modified with this function.
     130             :  *
     131             :  * The name of the parameter cannot be the empty string.
     132             :  *
     133             :  * If that parameter already exists, its value gets replaced.
     134             :  *
     135             :  * \param[in] name  The parameter name.
     136             :  * \param[in] value  The value for the named parameter.
     137             :  */
     138           0 : void http_link::add_param(std::string const & name, std::string const & value)
     139             : {
     140           0 :     if(name.empty())
     141             :     {
     142           0 :         throw link_parameter_exception("the name of a link parameter cannot be empty.");
     143             :     }
     144           0 :     if(name == "rel")
     145             :     {
     146           0 :         throw link_parameter_exception("the \"rel\" link parameter cannot be modified, it is set on construction only.");
     147             :     }
     148           0 :     for(char const * s(name.c_str()); *s != '\0'; ++s)
     149             :     {
     150           0 :         if(*s < 'a'
     151           0 :         || *s > 'z')
     152             :         {
     153             :             // this is probably wrong, but right now that's all we need
     154             :             // extend as required
     155           0 :             throw link_parameter_exception("the name of a link parameter must be defined with lowercase letters only (a-z).");
     156             :         }
     157             :     }
     158           0 :     for(char const * s(value.c_str()); *s != '\0'; ++s)
     159             :     {
     160           0 :         if(*s == '"'
     161           0 :         || *s < ' ')
     162             :         {
     163           0 :             throw link_parameter_exception("the value of a link parameter cannot include a control character or a double quote (\").");
     164             :         }
     165             :     }
     166             : 
     167           0 :     f_params[name] = value;
     168           0 : }
     169             : 
     170             : 
     171             : /** \brief Check whether a named parameter exists.
     172             :  *
     173             :  * This function checks whether a parameter with the specified name exists
     174             :  * in the list of parameters.
     175             :  *
     176             :  * \param[in] name  The new value of the cookie.
     177             :  *
     178             :  * \return true if the named parameter is defined.
     179             :  */
     180           0 : bool http_link::has_param(std::string const & name) const
     181             : {
     182           0 :     return f_params.find(name) != f_params.end();
     183             : }
     184             : 
     185             : 
     186             : /** \brief Retrieve the value of a parameter.
     187             :  *
     188             :  * This function returns the value of the specified parameter. If the
     189             :  * parameter is not defined, the empty string is returned.
     190             :  *
     191             :  * \param[in] name  The name of the parameter to read.
     192             :  *
     193             :  * \sa add_param();
     194             :  */
     195           0 : std::string http_link::get_param(std::string const & name) const
     196             : {
     197           0 :     if(has_param(name))
     198             :     {
     199           0 :         auto const it(f_params.find(name));
     200           0 :         return it->second;
     201             :     }
     202             : 
     203           0 :     return std::string();
     204             : }
     205             : 
     206             : 
     207             : /** \brief Get the complete list of parameters.
     208             :  *
     209             :  * This function can be used to retrieve the entire list of parameters from
     210             :  * this link.
     211             :  *
     212             :  * \warning
     213             :  * By default the function returns a reference meaning that a call to
     214             :  * add_param() will change the map you are dealing with here.
     215             :  *
     216             :  * \return The list of parameters, a map.
     217             :  */
     218           0 : http_link::param_t const & http_link::get_params() const
     219             : {
     220           0 :     return f_params;
     221             : }
     222             : 
     223             : 
     224             : /** \brief Transform the link for the HTTP header.
     225             :  *
     226             :  * This function transforms the link so it works as an HTTP header.
     227             :  *
     228             :  * \warning
     229             :  * This generates that one link string. Not the actual header. The
     230             :  * header requires all the links to be added in one "Link: ..." entry.
     231             :  *
     232             :  * See https://tools.ietf.org/html/rfc5988
     233             :  *
     234             :  * \return A valid HTTP link header.
     235             :  */
     236           0 : std::string http_link::to_http_header() const
     237             : {
     238             :     // Note: the name was already checked for invalid characters
     239           0 :     std::string result;
     240             : 
     241           0 :     result += "<";
     242           0 :     result += f_link;
     243           0 :     result += ">; rel=";
     244           0 :     result += f_rel;
     245             : 
     246           0 :     for(auto p : f_params)
     247             :     {
     248             :         // Note: if we test the value of each parameter, then we could
     249             :         //       already know whether it needs quoting or not when we
     250             :         //       reach here
     251             :         //
     252           0 :         result += "; ";
     253           0 :         result += p.first;
     254           0 :         result += "=\"";
     255           0 :         result += p.second;
     256           0 :         result += "\"";
     257             :     }
     258             : 
     259           0 :     return result;
     260             : }
     261             : 
     262             : 
     263             : 
     264           6 : } // namespace edhttp
     265             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13