aboutsummaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/apache/request12
-rw-r--r--web/apache/request.cxx125
-rw-r--r--web/mime-url-encoding26
-rw-r--r--web/mime-url-encoding.cxx135
-rw-r--r--web/module12
-rw-r--r--web/xhtml53
6 files changed, 236 insertions, 127 deletions
diff --git a/web/apache/request b/web/apache/request
index 59d4600..88b38a9 100644
--- a/web/apache/request
+++ b/web/apache/request
@@ -43,6 +43,11 @@ namespace web
int
flush ();
+ // Get request path.
+ //
+ virtual const path_type&
+ path ();
+
// Get request body data stream.
//
virtual std::istream&
@@ -93,12 +98,6 @@ namespace web
void
parse_parameters (const char* args);
- static void
- mime_url_encode (const char* v, std::ostream& o);
-
- static std::string
- mime_url_decode (const char* b, const char* e, bool trim = false);
-
bool
get_write_state () const noexcept {return write_state_;}
@@ -129,6 +128,7 @@ namespace web
std::unique_ptr<std::ostream> out_;
std::unique_ptr<std::streambuf> in_buf_;
std::unique_ptr<std::istream> in_;
+ path_type path_;
std::unique_ptr<name_values> parameters_;
std::unique_ptr<name_values> cookies_;
std::unique_ptr<std::string> form_data_;
diff --git a/web/apache/request.cxx b/web/apache/request.cxx
index 7727b35..497d2d6 100644
--- a/web/apache/request.cxx
+++ b/web/apache/request.cxx
@@ -14,18 +14,20 @@
#include <memory> // unique_ptr
#include <sstream>
#include <ostream>
+#include <istream>
#include <cstring>
#include <utility> // move()
#include <stdexcept>
#include <streambuf>
+#include <web/mime-url-encoding>
+
using namespace std;
namespace web
{
namespace apache
{
-
istream& request::
content ()
{
@@ -46,10 +48,25 @@ namespace web
return *in_;
}
+ const path& request::
+ path ()
+ {
+ if (path_.empty ())
+ {
+ path_ = path_type (rec_->uri);
+
+ // Module request handler can not be called if URI is empty.
+ //
+ assert (!path_.empty ());
+ }
+
+ return path_;
+ }
+
const name_values& request::
parameters ()
{
- if (!parameters_)
+ if (parameters_ == nullptr)
{
parameters_.reset (new name_values ());
@@ -70,7 +87,7 @@ namespace web
const name_values& request::
cookies ()
{
- if (!cookies_)
+ if (cookies_ == nullptr)
{
cookies_.reset (new name_values ());
@@ -264,107 +281,5 @@ namespace web
n = e ? e + 1 : 0;
}
}
-
- void request::
- mime_url_encode (const char* v, ostream& o)
- {
- char f (o.fill ());
- ios_base::fmtflags g (o.flags ());
- o << hex << uppercase << right << setfill ('0');
-
- char c;
-
- while ((c = *v++) != '\0')
- {
- if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9'))
- {
- o << c;
- }
- else
- switch (c)
- {
- case ' ': o << '+'; break;
- case '.':
- case '_':
- case '-':
- case '~': o << c; break;
- default:
- {
- o << "%" << setw (2) << static_cast<unsigned short> (c);
- break;
- }
- }
- }
-
- o.flags (g);
- o.fill (f);
- }
-
- string request::
- mime_url_decode (const char* b, const char* e, bool trim)
- {
- if (trim)
- {
- b += strspn (b, " ");
-
- if (b >= e)
- return string ();
-
- while (*--e == ' ');
- ++e;
- }
-
- string value;
- value.reserve (e - b);
-
- char bf[3];
- bf[2] = '\0';
-
- while (b != e)
- {
- char c (*b++);
-
- switch (c)
- {
- case '+':
- {
- value.append (" ");
- break;
- }
- case '%':
- {
- if (*b == '\0' || b[1] == '\0')
- {
- throw invalid_argument (
- "::web::apache::request::mime_url_decode short");
- }
-
- *bf = *b;
- bf[1] = b[1];
-
- char* ebf (nullptr);
- size_t vl (strtoul (bf, &ebf, 16));
-
- if (*ebf != '\0')
- {
- throw invalid_argument (
- "::web::apache::request::mime_url_decode wrong");
- }
-
- value.append (1, static_cast<char> (vl));
- b += 2;
- break;
- }
- default:
- {
- value.append (1, c);
- break;
- }
- }
- }
-
- return value;
- }
}
}
diff --git a/web/mime-url-encoding b/web/mime-url-encoding
new file mode 100644
index 0000000..9ae5d6d
--- /dev/null
+++ b/web/mime-url-encoding
@@ -0,0 +1,26 @@
+// file : web/mime-url-encoding -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#ifndef WEB_MIME_URL_ENCODING
+#define WEB_MIME_URL_ENCODING
+
+#include <string>
+#include <iosfwd>
+
+namespace web
+{
+ void
+ mime_url_encode (const char* v, std::ostream& o);
+
+ std::string
+ mime_url_encode (const char* v);
+
+ std::string
+ mime_url_encode (const std::string& v);
+
+ std::string
+ mime_url_decode (const char* b, const char* e, bool trim = false);
+}
+
+#endif // WEB_MIME_URL_ENCODING
diff --git a/web/mime-url-encoding.cxx b/web/mime-url-encoding.cxx
new file mode 100644
index 0000000..1d68bf3
--- /dev/null
+++ b/web/mime-url-encoding.cxx
@@ -0,0 +1,135 @@
+// file : web/mime-url-encoding.cxx -*- C++ -*-
+// copyright : Copyright (c) 2014-2015 Code Synthesis Ltd
+// license : MIT; see accompanying LICENSE file
+
+#include <web/mime-url-encoding>
+
+#include <ios> // hex, uppercase, right
+#include <string>
+#include <iomanip> // setw(), setfill ()
+#include <ostream>
+#include <sstream>
+#include <cstring> // size_t, strspn()
+#include <stdexcept> // invalid_argument
+
+using namespace std;
+
+namespace web
+{
+ // Encode characters different from unreserved ones specified in
+ // "2.3. Unreserved Characters" of http://tools.ietf.org/html/rfc3986.
+ //
+ void
+ mime_url_encode (const char* v, ostream& o)
+ {
+ char f (o.fill ());
+ ostream::fmtflags g (o.flags ());
+ o << hex << uppercase << right << setfill ('0');
+
+ char c;
+ while ((c = *v++) != '\0')
+ {
+ if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9'))
+ {
+ o << c;
+ }
+ else
+ {
+ switch (c)
+ {
+ case ' ': o << '+'; break;
+ case '.':
+ case '_':
+ case '-':
+ case '~': o << c; break;
+ default:
+ {
+ o << "%" << setw (2) << static_cast<unsigned short> (c);
+ break;
+ }
+ }
+ }
+ }
+
+ o.flags (g);
+ o.fill (f);
+ }
+
+ string
+ mime_url_encode (const char* v)
+ {
+ stringstream o;
+ mime_url_encode (v, o);
+ return o.str ();
+ }
+
+ string
+ mime_url_encode (const string& v)
+ {
+ return mime_url_encode (v.c_str ());
+ }
+
+ string
+ mime_url_decode (const char* b, const char* e, bool trim)
+ {
+ if (trim)
+ {
+ b += strspn (b, " ");
+
+ if (b >= e)
+ return string ();
+
+ while (*--e == ' ');
+ ++e;
+ }
+
+ string value;
+ value.reserve (e - b);
+
+ char bf[3];
+ bf[2] = '\0';
+
+ while (b != e)
+ {
+ char c (*b++);
+ switch (c)
+ {
+ case '+':
+ {
+ value.append (" ");
+ break;
+ }
+ case '%':
+ {
+ if (*b == '\0' || b[1] == '\0')
+ {
+ throw invalid_argument ("::web::mime_url_decode short");
+ }
+
+ *bf = *b;
+ bf[1] = b[1];
+
+ char* ebf (nullptr);
+ size_t vl (strtoul (bf, &ebf, 16));
+
+ if (*ebf != '\0')
+ {
+ throw invalid_argument ("::web::mime_url_decode wrong");
+ }
+
+ value.append (1, static_cast<char> (vl));
+ b += 2;
+ break;
+ }
+ default:
+ {
+ value.append (1, c);
+ break;
+ }
+ }
+ }
+
+ return value;
+ }
+}
diff --git a/web/module b/web/module
index e1cccf0..7398d45 100644
--- a/web/module
+++ b/web/module
@@ -13,6 +13,8 @@
#include <utility> // move()
#include <stdexcept> // runtime_error
+#include <butl/path>
+
namespace web
{
// HTTP status code.
@@ -68,10 +70,20 @@ namespace web
};
using name_values = std::vector<name_value>;
+ using path = butl::path;
class request
{
public:
+ using path_type = web::path;
+
+ // Corresponds to abs_path portion of HTTP URL as described in
+ // "3.2.2 HTTP URL" of http://tools.ietf.org/html/rfc2616.
+ // Returns '/' if no abs_path is present in URL.
+ //
+ virtual const path_type&
+ path () = 0;
+
//@@ Why not pass parameters directly? Lazy parsing?
//@@ Why not have something like operator[] for lookup? Probably
// in name_values.
diff --git a/web/xhtml b/web/xhtml
index b8d6ce0..4fc6119 100644
--- a/web/xhtml
+++ b/web/xhtml
@@ -5,6 +5,8 @@
#ifndef WEB_XHTML
#define WEB_XHTML
+#include <functional> // function
+
#include <xml/serializer>
namespace web
@@ -36,9 +38,9 @@ namespace web
//
namespace xhtml
{
- const char* xmlns = "http://www.w3.org/1999/xhtml";
+ const char* const xmlns = "http://www.w3.org/1999/xhtml";
- using serializer_func = void (*) (xml::serializer&);
+ using serializer_func = std::function<void(xml::serializer&)>;
struct attr_value_base
{
@@ -124,7 +126,10 @@ namespace web
operator() (xml::serializer& s) const {s.start_element (xmlns, name);}
virtual serializer_func
- operator~ () const {return [](xml::serializer& s) {s.end_element ();};}
+ operator~ () const
+ {
+ return [this](xml::serializer& s) {s.end_element (xmlns, name);};
+ }
// s << elem(attr1 = 123, attr2 = "abc");
//
@@ -143,8 +148,11 @@ namespace web
return attr_element (*this, a1);
}
- protected:
- element () = default;
+// @@ Now always need to provide element name, so operator~ () could create
+// the lambda capable to pass a valid name to end_element call.
+//
+// protected:
+// element () = default;
};
struct inline_element: element
@@ -162,9 +170,9 @@ namespace web
virtual serializer_func
operator~ () const
{
- return [](xml::serializer& s)
+ return [this](xml::serializer& s)
{
- s.end_element (); s.resume_indentation ();
+ s.end_element (xmlns, name); s.resume_indentation ();
};
}
};
@@ -194,7 +202,10 @@ namespace web
operator() (xml::serializer& s) const {s.start_attribute (name);}
virtual serializer_func
- operator~ () const {return [](xml::serializer& s) {s.end_attribute ();};}
+ operator~ () const
+ {
+ return [this](xml::serializer& s) {s.end_attribute (name);};
+ }
};
// Elements.
@@ -206,13 +217,13 @@ namespace web
//
struct html_element: element
{
- html_element () {} // Uninitialized const static.
+ html_element (): element ("html") {}
virtual void
operator() (xml::serializer& s) const
{
s.doctype_decl ("html");
- s.start_element (xmlns, "html");
+ s.start_element (xmlns, name);
s.namespace_decl (xmlns, "");
}
};
@@ -220,12 +231,12 @@ namespace web
struct head_element: element
{
- head_element () {} // Uninitialized const static.
+ head_element (): element ("head") {}
virtual void
operator() (xml::serializer& s) const
{
- s.start_element (xmlns, "head");
+ s.start_element (xmlns, name);
s.start_element (xmlns, "meta");
s.attribute ("charset", "UTF-8");
s.end_element ();
@@ -233,10 +244,13 @@ namespace web
};
static const head_element HEAD;
+ static const element BODY ("body");
+ static const element DIV ("div");
+ static const element P ("p");
+ static const element STYLE ("style");
static const element TITLE ("title");
- static const element BODY ("body");
- static const element P ("p");
+ static const inline_element A ("a");
static const inline_element B ("b");
static const inline_element I ("i");
static const inline_element U ("u");
@@ -246,9 +260,16 @@ namespace web
// Attributes.
//
- static const attribute ID ("id");
static const attribute CLASS ("class");
- static const attribute STYLE ("style");
+ static const attribute HREF ("href");
+ static const attribute ID ("id");
+ static const attribute TYPE ("type");
+
+// @@ Attribute variable names clash with element variable names.
+// Should we prefix/suffix attribute names like _STYLE, STYLE_ or there
+// are some better ideas ?
+//
+// static const attribute STYLE ("style");
}
}