Fix URL encode issue.

master
Chunting Gu 6 years ago
parent 53a731caf5
commit 9f3d968e77

@ -1 +0,0 @@
#include "webcc/encoding.h"

@ -1,21 +0,0 @@
#ifndef WEBCC_ENCODING_H_
#define WEBCC_ENCODING_H_
#include <string>
#include <codecvt>
namespace webcc {
std::string Utf16ToUtf8(const std::wstring& utf16_string) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.to_bytes(utf16_string);
}
std::wstring Utf8ToUtf16(const std::string& utf8_string) {
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
return converter.from_bytes(utf8_string);
}
} // namespace webcc
#endif // WEBCC_ENCODING_H_

@ -57,3 +57,8 @@ target_link_libraries(form_server ${EXAMPLE_LIBS})
add_subdirectory(book_server)
add_subdirectory(book_client)
if(WIN32)
add_executable(url_unicode url_unicode.cc encoding.cc encoding.h)
target_link_libraries(url_unicode ${EXAMPLE_LIBS})
endif()

@ -1,61 +0,0 @@
#include "examples/common/book.h"
#include <algorithm>
#include <iostream>
const Book kNullBook{};
std::ostream& operator<<(std::ostream& os, const Book& book) {
os << "{ " << book.id << ", " << book.title << ", " << book.price << " }";
return os;
}
const Book& BookStore::GetBook(const std::string& id) const {
auto it = FindBook(id);
return (it == books_.end() ? kNullBook : *it);
}
std::string BookStore::AddBook(const Book& book) {
std::string id = NewID();
books_.push_back({ id, book.title, book.price });
return id;
}
bool BookStore::UpdateBook(const Book& book) {
auto it = FindBook(book.id);
if (it != books_.end()) {
it->title = book.title;
it->price = book.price;
return true;
}
return false;
}
bool BookStore::DeleteBook(const std::string& id) {
auto it = FindBook(id);
if (it != books_.end()) {
books_.erase(it);
return true;
}
return false;
}
std::list<Book>::const_iterator BookStore::FindBook(const std::string& id)
const {
return std::find_if(books_.begin(), books_.end(),
[&id](const Book& book) { return book.id == id; });
}
std::list<Book>::iterator BookStore::FindBook(const std::string& id) {
return std::find_if(books_.begin(), books_.end(),
[&id](Book& book) { return book.id == id; });
}
std::string BookStore::NewID() const {
static int s_id_counter = 0;
++s_id_counter;
return std::to_string(s_id_counter);
}

@ -1,52 +0,0 @@
#ifndef EXAMPLE_COMMON_BOOK_H_
#define EXAMPLE_COMMON_BOOK_H_
#include <list>
#include <string>
#include "boost/filesystem/path.hpp"
// In-memory test data.
// There should be some database in a real product.
struct Book {
std::string id;
std::string title;
double price;
boost::filesystem::path photo;
bool IsNull() const { return id.empty(); }
};
std::ostream& operator<<(std::ostream& os, const Book& book);
extern const Book kNullBook;
class BookStore {
public:
const std::list<Book>& books() const {
return books_;
}
const Book& GetBook(const std::string& id) const;
// Add a book, return the ID.
// NOTE: The ID of the input book will be ignored so should be empty.
std::string AddBook(const Book& book);
bool UpdateBook(const Book& book);
bool DeleteBook(const std::string& id);
private:
std::list<Book>::const_iterator FindBook(const std::string& id) const;
std::list<Book>::iterator FindBook(const std::string& id);
// Allocate a new book ID.
std::string NewID() const;
std::list<Book> books_;
};
#endif // EXAMPLE_COMMON_BOOK_H_

@ -1,57 +0,0 @@
#include "examples/common/book_json.h"
#include <sstream>
#include <iostream>
#include "json/json.h"
#include "examples/common/book.h"
std::string JsonToString(const Json::Value& json) {
Json::StreamWriterBuilder builder;
return Json::writeString(builder, json);
}
Json::Value StringToJson(const std::string& str) {
Json::Value json;
Json::CharReaderBuilder builder;
std::stringstream stream(str);
std::string errs;
if (!Json::parseFromStream(builder, stream, &json, &errs)) {
std::cerr << errs << std::endl;
}
return json;
}
Json::Value BookToJson(const Book& book) {
Json::Value json;
json["id"] = book.id;
json["title"] = book.title;
json["price"] = book.price;
return json;
}
Book JsonToBook(const Json::Value& json) {
return {
json["id"].asString(),
json["title"].asString(),
json["price"].asDouble(),
};
}
std::string BookToJsonString(const Book& book) {
return JsonToString(BookToJson(book));
}
bool JsonStringToBook(const std::string& json_str, Book* book) {
Json::Value json = StringToJson(json_str);
if (!json) {
return false;
}
*book = JsonToBook(json);
return true;
}

@ -1,20 +0,0 @@
#ifndef EXAMPLE_COMMON_BOOK_JSON_H_
#define EXAMPLE_COMMON_BOOK_JSON_H_
#include <string>
#include "json/json-forwards.h"
struct Book;
std::string JsonToString(const Json::Value& json);
Json::Value StringToJson(const std::string& str);
Json::Value BookToJson(const Book& book);
Book JsonToBook(const Json::Value& json);
std::string BookToJsonString(const Book& book);
bool JsonStringToBook(const std::string& json_str, Book* book);
#endif // EXAMPLE_COMMON_BOOK_JSON_H_

@ -0,0 +1,60 @@
#include "encoding.h"
#include <Windows.h>
namespace {
// Wrapper for Windows API MultiByteToWideChar.
std::wstring MB2WC(const std::string& input, unsigned int code_page) {
if (input.empty()) {
return L"";
}
int length = ::MultiByteToWideChar(code_page, 0, &input[0],
static_cast<int>(input.size()),
NULL, 0);
std::wstring output(length, '\0');
::MultiByteToWideChar(code_page, 0, &input[0], static_cast<int>(input.size()),
&output[0], static_cast<int>(output.size()));
return output;
}
// Wrapper for Windows API WideCharToMultiByte.
std::string WC2MB(const std::wstring& input, unsigned int code_page) {
if (input.empty()) {
return "";
}
// There do have other code pages which require the flags to be 0, e.g.,
// 50220, 50211, and so on. But they are not included in our charset
// dictionary. So, only consider 65001 (UTF-8) and 54936 (GB18030).
DWORD flags = 0;
if (code_page != 65001 && code_page != 54936) {
flags = WC_NO_BEST_FIT_CHARS | WC_COMPOSITECHECK | WC_DEFAULTCHAR;
}
int length = ::WideCharToMultiByte(code_page, flags, &input[0],
static_cast<int>(input.size()), NULL, 0,
NULL, NULL);
std::string output(length, '\0');
::WideCharToMultiByte(code_page, flags, &input[0],
static_cast<int>(input.size()), &output[0],
static_cast<int>(output.size()), NULL, NULL);
return output;
}
} // namespace
std::string Utf16ToUtf8(const std::wstring& utf16_string) {
return WC2MB(utf16_string, CP_UTF8);
}
std::wstring Utf8ToUtf16(const std::string& utf8_string) {
return MB2WC(utf8_string, CP_UTF8);
}

@ -0,0 +1,12 @@
#ifndef ENCODING_H_
#define ENCODING_H_
#include <string>
// Convert UTF16 to UTF8.
std::string Utf16ToUtf8(const std::wstring& utf16_string);
// Convert UTF8 to UTF16.
std::wstring Utf8ToUtf16(const std::string& utf8_string);
#endif // ENCODING_H_

Binary file not shown.

@ -83,7 +83,8 @@ std::string EncodeImpl(const std::string& raw, // UTF8
for (auto i = raw.begin(); i != raw.end(); ++i) {
// For UTF8 encoded string, char ASCII can be greater than 127.
int c = static_cast<int>(*i);
// Cast to unsigned char firstly to make sure it's in [0,255].
int c = static_cast<unsigned char>(*i);
if (should_encode(c)) {
encoded.push_back('%');
@ -101,7 +102,8 @@ std::string EncodeImpl(const std::string& raw, // UTF8
// are called unreserved. These include uppercase and lowercase letters, decimal
// digits, hyphen, period, underscore, and tilde.
inline bool IsUnreserved(int c) {
return std::isalnum(c) || c == '-' || c == '.' || c == '_' || c == '~';
return std::isalnum((unsigned char)c) || c == '-' || c == '.' || c == '_' ||
c == '~';
}
// General delimiters serve as the delimiters between different uri components.

Loading…
Cancel
Save