webserver: Moved platform2/libwebserv to platform2/webserver

Cleaned up the code structure a bit inside the web server directory
to reflect the current layout of functionality:

- Renamed the top-level director from libwebserv to webserver
- Moved the client library code to sub-directory of libwebserv to
  be on the same level as the web server daemon (webservd).
- Updated the source code to reflect the new include paths.

BUG=brillo:10
TEST=FEATURES=test emerge-storm webserver privetd ap-daemons
CQ-DEPEND=CL:245755,CL:*195317

Change-Id: Idb8d665b6e0c15b5ee0219ff72327045a7084363
Reviewed-on: https://chromium-review.googlesource.com/245736
Reviewed-by: Christopher Wiley <wiley@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/libwebserv/request.cc b/libwebserv/request.cc
new file mode 100644
index 0000000..37ea1c1
--- /dev/null
+++ b/libwebserv/request.cc
@@ -0,0 +1,191 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <libwebserv/request.h>
+
+#include <libwebserv/connection.h>
+
+namespace libwebserv {
+
+FileInfo::FileInfo(const std::string& file_name,
+                   const std::string& content_type,
+                   const std::string& transfer_encoding)
+    : file_name_(file_name),
+      content_type_(content_type),
+      transfer_encoding_(transfer_encoding) {
+}
+
+const std::vector<uint8_t>& FileInfo::GetData() const {
+  return data_;
+}
+
+Request::Request(const std::string& url, const std::string& method)
+    : url_{url}, method_{method} {
+}
+
+Request::~Request() {
+}
+
+scoped_ptr<Request> Request::Create(const std::string& url,
+                                    const std::string& method) {
+  // Can't use make_shared here since Request::Request is private.
+  return scoped_ptr<Request>(new Request(url, method));
+}
+
+const std::vector<uint8_t>& Request::GetData() const {
+  return raw_data_;
+}
+
+bool Request::AddRawRequestData(const void* data, size_t size) {
+  const uint8_t* byte_data_ = static_cast<const uint8_t*>(data);
+  raw_data_.insert(raw_data_.end(), byte_data_, byte_data_ + size);
+  return true;
+}
+
+bool Request::AddPostFieldData(const char* key,
+                               const char* filename,
+                               const char* content_type,
+                               const char* transfer_encoding,
+                               const char* data,
+                               size_t size) {
+  if (filename) {
+    std::unique_ptr<FileInfo> file_info{
+        new FileInfo{filename, content_type ? content_type : "",
+                     transfer_encoding ? transfer_encoding : ""}};
+    file_info->data_.assign(data, data + size);
+    file_info_.emplace(key, std::move(file_info));
+    last_posted_data_was_file_ = true;
+    return true;
+  }
+  std::string value{data, size};
+  post_data_.emplace(key, value);
+  last_posted_data_was_file_ = false;
+  return true;
+}
+
+bool Request::AppendPostFieldData(const char* key,
+                                  const char* data,
+                                  size_t size) {
+  if (last_posted_data_was_file_) {
+    auto file_pair = file_info_.equal_range(key);
+    if (file_pair.first == file_info_.end())
+      return false;
+    FileInfo* file_info = file_pair.second->second.get();
+    file_info->data_.insert(file_info->data_.end(), data, data + size);
+    return true;
+  }
+
+  auto pair = post_data_.equal_range(key);
+  if (pair.first == post_data_.end())
+    return false;
+  --pair.second;  // Get the last form field with this name/key.
+  pair.second->second.append(data, size);
+  return true;
+}
+
+std::vector<PairOfStrings> Request::GetFormData() const {
+  auto data = GetFormDataGet();
+  auto post_data = GetFormDataPost();
+  data.insert(data.end(), post_data.begin(), post_data.end());
+  return data;
+}
+
+std::vector<PairOfStrings> Request::GetFormDataGet() const {
+  return std::vector<PairOfStrings>{get_data_.begin(), get_data_.end()};
+}
+
+std::vector<PairOfStrings> Request::GetFormDataPost() const {
+  return std::vector<PairOfStrings>{post_data_.begin(), post_data_.end()};
+}
+
+std::vector<std::pair<std::string, const FileInfo*>> Request::GetFiles() const {
+  std::vector<std::pair<std::string, const FileInfo*>> data;
+  data.reserve(file_info_.size());
+  for (const auto& pair : file_info_) {
+    data.emplace_back(pair.first, pair.second.get());
+  }
+  return data;
+}
+
+std::vector<std::string> Request::GetFormField(const std::string& name) const {
+  std::vector<std::string> data;
+  auto pair = get_data_.equal_range(name);
+  while (pair.first != pair.second) {
+    data.push_back(pair.first->second);
+    ++pair.first;
+  }
+  pair = post_data_.equal_range(name);
+  while (pair.first != pair.second) {
+    data.push_back(pair.first->second);
+    ++pair.first;
+  }
+  return data;
+}
+
+std::vector<std::string> Request::GetFormFieldPost(
+    const std::string& name) const {
+  std::vector<std::string> data;
+  auto pair = post_data_.equal_range(name);
+  while (pair.first != pair.second) {
+    data.push_back(pair.first->second);
+    ++pair.first;
+  }
+  return data;
+}
+
+std::vector<std::string> Request::GetFormFieldGet(
+    const std::string& name) const {
+  std::vector<std::string> data;
+  auto pair = get_data_.equal_range(name);
+  while (pair.first != pair.second) {
+    data.push_back(pair.first->second);
+    ++pair.first;
+  }
+  return data;
+}
+
+std::vector<const FileInfo*> Request::GetFileInfo(
+    const std::string& name) const {
+  std::vector<const FileInfo*> data;
+  auto pair = file_info_.equal_range(name);
+  while (pair.first != pair.second) {
+    data.push_back(pair.first->second.get());
+    ++pair.first;
+  }
+  return data;
+}
+
+std::vector<PairOfStrings> Request::GetHeaders() const {
+  return std::vector<PairOfStrings>{headers_.begin(), headers_.end()};
+}
+
+std::vector<std::string> Request::GetHeader(const std::string& name) const {
+  std::vector<std::string> data;
+  auto pair = headers_.equal_range(GetCanonicalHeaderName(name));
+  while (pair.first != pair.second) {
+    data.push_back(pair.first->second);
+    ++pair.first;
+  }
+  return data;
+}
+
+std::string Request::GetCanonicalHeaderName(const std::string& name) {
+  std::string canonical_name = name;
+  bool word_begin = true;
+  for (char& c : canonical_name) {
+    if (c == '-') {
+      word_begin = true;
+    } else {
+      if (word_begin) {
+        c = toupper(c);
+      } else {
+        c = tolower(c);
+      }
+      word_begin = false;
+    }
+  }
+  return canonical_name;
+}
+
+}  // namespace libwebserv