Boost logo

Boost-Commit :

From: lists.drrngrvy_at_[hidden]
Date: 2007-10-08 16:32:31


Author: drrngrvy
Date: 2007-10-08 16:32:31 EDT (Mon, 08 Oct 2007)
New Revision: 39816
URL: http://svn.boost.org/trac/boost/changeset/39816

Log:
Adding test for cgi::cookie and modifying the cookie class to be more realistic
Added:
   sandbox/SOC/2007/cgi/libs/cgi/test/run/cookie.cpp (contents, props changed)
   sandbox/SOC/2007/cgi/libs/cgi/test/run/response.cpp (contents, props changed)
Properties modified:
   sandbox/SOC/2007/cgi/ (props changed)
Text files modified:
   sandbox/SOC/2007/cgi/boost/cgi/cookie.hpp | 113 ++++++++++++++++++++++++++++++++++-----
   sandbox/SOC/2007/cgi/boost/cgi/response.hpp | 9 --
   sandbox/SOC/2007/cgi/libs/cgi/test/run/Jamfile.v2 | 2
   3 files changed, 101 insertions(+), 23 deletions(-)

Modified: sandbox/SOC/2007/cgi/boost/cgi/cookie.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/boost/cgi/cookie.hpp (original)
+++ sandbox/SOC/2007/cgi/boost/cgi/cookie.hpp 2007-10-08 16:32:31 EDT (Mon, 08 Oct 2007)
@@ -10,46 +10,127 @@
 #define CGI_COOKIE_HPP_INCLUDED__
 
 #include <string>
+#include <boost/system/error_code.hpp>
+#include <boost/tokenizer/
 
 namespace cgi {
 
- /// A `cookie` object that can be streamed to a `response` object
+ template<typename String> struct basic_cookie;
+
+ // typedefs for common usage
+ typedef basic_cookie<std::string> cookie;
+ typedef basic_cookie<std::wstring> wcookie;
+
+ /// A `basic_cookie<>` object that can be (out-) streamed
   /**
    * Either set the parameters in the constructor, or set them directly.
    * Note: If you want to set the parameters individually, remember that each
    * parameter must NOT have a trailing semi-colon!
    *
    * TODO
- * - Add 'domain' attribute
- * - Add 'HttpOnly' attribute
- * - Data should be URL-encoded
+ * - Data should be URL-encoded, or maybe provide an overload for url_decode
+ * that takes an HttpCookie?
+ * - Add to_string() ?
    */
- struct cookie
+ template<typename String>
+ struct basic_cookie
   {
- cookie() {}
+ typedef String string_type;
+
+ basic_cookie() {}
 
     /// Delete the cookie named `_name`.
- cookie(const std::string& _name)
- : content(_name + "=")
- , expires("Fri, 07 May 1824 16:30:00 GMT")
+ basic_cookie(const string_type& _name)
+ : content(_name)
+ , value()
+ , expires("Fri, 05-Jun-1989 15:30:00 GMT")
+ , path("/")
+ , secure(false)
+ , http_only(false)
     {
     }
 
     /// Create a cookie.
- cookie(const std::string& _name, const std::string& _val
- , const std::string& _expires = ""
- , const std::string& _path = "")
- : content(_name + "=" + _val)
+ basic_cookie(const string_type& _name, const string_type& _val
+ , const string_type& _expires = ""
+ , const string_type& _path = "/"
+ , const string_type& _domain = ""
+ , bool _secure = false
+ , bool HttpOnly = false)
+ : content(_name)
+ , value(_val)
       , expires(_expires)
       , path(_path)
+ , domain(_domain)
+ , secure(_secure)
+ , http_only(HttpOnly)
+ {
+ }
+
+ string_type name;
+ string_type value;
+ string_type expires;
+ string_type path;
+ string_type domain;
+ bool secure;
+ bool http_only;
+
+ /// Create a cookie from a const char*
+ /**
+ * Rules taken from: http://wp.netscape.com/newsref/std/cookie_spec.html
+ *
+ * Assumes:
+ * - Parts of the cookie are delimited by '; '. ie. if there is no space,
+ * or multiple spaces after the semi-colon, this function won't work...
+ */
+ /* Actually, I'm omitting these functions for now, just had a though...
+ static basic_cookie<string_type>
+ from_string(const char* str, boost::system::error_code& ec)
+ {
+ typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+ boost::char_separator<char> sep(";=");
+ tokenizer tokens(str, sep);
+ for (tokenizer::iterator iter = tokens.begin();
+ iter != tokens.end(); ++iter)
+ {
+
+ }
+ return ck;
+ }
+
+ static basic_cookie<string_type> from_string(const char* str)
+ {
+ boost::system::error_code ec;
+ cookie ck = from_string(ec);
+ detail::throw_error(ec);
+ return ck;
+ }
+
+ static basic_cookie<string_type> from_string(std::string& str)
     {
+ return from_string(str.c_str());
     }
 
- std::string content;
- std::string expires;
- std::string path;
+ static basic_cookie<string_type>
+ from_string(std::string& str, boost::system::error_code& ec)
+ {
+ return from_string(str.c_str(), ec);
+ }
+ */
   };
 
+ template<typename OutStream, typename Cookie>
+ OutStream& operator<<(OutStream& os, Cookie ck)
+ {
+ os<< ck.name << "=" << ck.value;
+ if (!ck.expires.empty()) os<< "; expires=" << ck.expires;
+ if (!ck.path.empty() ) os<< "; path=" << ck.path;
+ if (!ck.domain.empty() ) os<< "; domain=" << ck.domain;
+ if ( secure ) os<< "; secure";
+ if ( ck.http_only ) os<< "; HttpOnly";
+ return os;
+ }
+
 } // namespace cgi
 
 #endif // CGI_COOKIE_HPP_INCLUDED__

Modified: sandbox/SOC/2007/cgi/boost/cgi/response.hpp
==============================================================================
--- sandbox/SOC/2007/cgi/boost/cgi/response.hpp (original)
+++ sandbox/SOC/2007/cgi/boost/cgi/response.hpp 2007-10-08 16:32:31 EDT (Mon, 08 Oct 2007)
@@ -78,17 +78,12 @@
   }
 
   template<>
- response& operator<<(response& resp, const cookie& c)
+ response& operator<<(response& resp, const cookie& ck)
   {
     // Note: the 'set-cookie' isn't part of the cookie object since
     // the cookie can also be set after the headers have been sent.
     // See http://tinyurl.com/33znkj
- resp<< "Set-cookie: " << c.content << "; ";
- if (!c.expires.empty())
- resp<< c.expires << "; ";
- if (!c.path.empty())
- resp<< c.path << "; ";
- return resp<< "\r\n";
+ return resp<< "Set-cookie: " << ck << "\r\n";
   }
 
 } // namespace cgi

Modified: sandbox/SOC/2007/cgi/libs/cgi/test/run/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/cgi/libs/cgi/test/run/Jamfile.v2 (original)
+++ sandbox/SOC/2007/cgi/libs/cgi/test/run/Jamfile.v2 2007-10-08 16:32:31 EDT (Mon, 08 Oct 2007)
@@ -6,4 +6,6 @@
 test-suite run_test_suite
   :
     #[ run [ glob *.cpp ] ]
+
+ [ run cookie.cpp ]
   ;

Added: sandbox/SOC/2007/cgi/libs/cgi/test/run/cookie.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/libs/cgi/test/run/cookie.cpp 2007-10-08 16:32:31 EDT (Mon, 08 Oct 2007)
@@ -0,0 +1,88 @@
+// Test the cgi::cookie class works as advertised
+
+/* TODO
+ * ----
+ * - Verify it works with other string types (std::wstring is probably enough)
+ */
+
+#define BOOST_TEST_MAIN
+#include <boost/test/unit_test.hpp>
+
+#include <sstream>
+#include "boost/cgi/cookie.hpp"
+
+
+BOOST_AUTO_TEST_CASE( cookie_constructor_delete )
+{
+ // Constructing a cookie with only a name should be a valid way to
+ // delete the cookie. ie. set its value to NULL and give it a date
+ // in the past
+ using namespace cgi;
+
+ cookie ck("unwanted_cookie_name");
+
+ BOOST_CHECK(ck.name == "unwanted_cookie_name");
+ BOOST_CHECK(ck.value == "");
+ BOOST_CHECK(ck.path == "/");
+ // this one could be more robust (by using a generic RFC2616 date parser)
+ // see: http://www.apps.ietf.org/rfc/rfc2616.html#sec-3.3
+ BOOST_CHECK(ck.data == "Fri, 05 Jun 1989 15:30:00 GMT");
+ BOOST_CHECK(ck.domain == "");
+ BOOST_CHECK(ck.secure == false);
+ BOOST_CHECK(ck.http_only == false);
+}
+
+BOOST_AUTO_TEST_CASE( cookie_constructor_full )
+{
+ // Check the full version of the constructor works (simple test)
+ using namespace cgi;
+
+ cookie ck("name", "value", "Wed, 03-Oct-2007 16:26:06 GMT"
+ , "/cookie", "example.com", false, true);
+
+ BOOST_CHECK(ck.name == "name");
+ BOOST_CHECK(ck.value == "value");
+ BOOST_CHECK(ck.path == "/cookie");
+ // this one could be more robust (by using a generic RFC2616 date parser)
+ // see: http://www.apps.ietf.org/rfc/rfc2616.html#sec-3.3
+ BOOST_CHECK(ck.data == "Wed, 03-Oct-2007 16:26:06 GMT");
+ BOOST_CHECK(ck.domain == "example.com");
+ BOOST_CHECK(ck.secure == false);
+ BOOST_CHECK(ck.http_only == true);
+}
+
+BOOST_AUTO_TEST_CASE( cookie_stream_operator )
+{
+ // Constructing a cookie with only a name should be a valid way to
+ // delete the cookie. ie. set its value to NULL and give it a date
+ // in the past
+ using namespace cgi;
+ using namespace std;
+
+ string cookie_content(
+ "unwanted_cookie_name=; expires=Fri, 05-Jun-1989 15:30:00 GMT; path=/");
+
+ // First check the cookie below outputs the above string when streamed
+ // (don't continue if it doesn't: the rest of the test relies on this).
+ cookie ck("unwanted_cookie_name");
+ ostringstream oss;
+ oss<< ck;
+ BOOST_ASSERT(oss.str() == cookie_content);
+
+ // Now check if the string cookie_content can be turned into a cookie type,
+ // then streamed without being altered.
+ //cookie ck2(cookie::from_string(cookie_content));
+ //oss.clear();
+ //oss<< ck2;
+ //BOOST_CHECK(oss.str() == cookie_content);
+
+ // Now try a more complete cookie, using the detailed constructor
+ cookie_content = "name=value; expires=Wed, 03-Oct-2007 16:26:06 GMT;"
+ " path=/cookie; domain=example.com; secure; HttpOnly";
+
+ cookie ck("name", "value", "Wed, 03-Oct-2007 16:26:06 GMT"
+ , "/cookie", "example.com", true, true);
+ oss.clear();
+ oss<< ck;
+ BOOST_CHECK(oss.str() == cookie_content);
+}

Added: sandbox/SOC/2007/cgi/libs/cgi/test/run/response.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/cgi/libs/cgi/test/run/response.cpp 2007-10-08 16:32:31 EDT (Mon, 08 Oct 2007)
@@ -0,0 +1,10 @@
+// Test the cgi::response class works as advertised
+#define BOOST_TEST_MAIN
+#include <boost/test/unit_test.hpp>
+
+#include "boost/cgi/response.hpp"
+
+BOOST_AUTO_TEST_CASE( response_test )
+{
+ using namespace cgi;
+}
\ No newline at end of file


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk