From acbe6db15f9f943f35a588d41ef1fce86e7ad30d Mon Sep 17 00:00:00 2001 From: Thomas Davis Date: Sat, 31 Aug 2013 19:30:05 -0400 Subject: [PATCH] Added URLEncode methods --- RELEASE_NOTES.md | 1 + include/CivetServer.h | 46 +++++++++++++++++++++++++++++++++++++++++-- include/civetweb.h | 5 +++++ src/CivetServer.cpp | 29 +++++++++++++++++++++++++++ src/civetweb.c | 26 +++++++++++++----------- 5 files changed, 93 insertions(+), 14 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 5b530944..4a986250 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -4,6 +4,7 @@ Release Notes v1.4 (UNDER DEVELOPMENT) - Added CivetServer::getParam methods - Added CivetServer::urlDecode methods +- Added CivetServer::urlEncode methods - Dealt with compiler warnings and some static analysis hits. - Added mg_get_var2() to parse repeated query variables - Externalized logging function cry() as mg_cry() diff --git a/include/CivetServer.h b/include/CivetServer.h index 2a05fd65..31fc4220 100644 --- a/include/CivetServer.h +++ b/include/CivetServer.h @@ -223,7 +223,7 @@ public: /** - * urlDecode(const char *, int, std::string &, bool) + * urlDecode(const std::string &, std::string &, bool) * * @param src string to be decoded * @param dst destination string @@ -237,7 +237,7 @@ public: } /** - * urlDecode(const char *, int, std::string &, bool) + * urlDecode(const char *, size_t, std::string &, bool) * * @param src buffer to be decoded * @param src_len length of buffer to be decoded @@ -249,6 +249,48 @@ public: */ static void urlDecode(const char *src, size_t src_len, std::string &dst, bool is_form_url_encoded=true); + /** + * urlDecode(const char *, std::string &, bool) + * + * @param src buffer to be decoded (0 terminated) + * @param dst destination string + * @is_form_url_encoded true if form url encoded + * form-url-encoded data differs from URI encoding in a way that it + * uses '+' as character for space, see RFC 1866 section 8.2.1 + * http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt + */ + static void urlDecode(const char *src, std::string &dst, bool is_form_url_encoded=true); + + /** + * urlEncode(const std::string &, std::string &, bool) + * + * @param src buffer to be encoded + * @param dst destination string + * @append true if string should not be cleared before encoding. + */ + static void urlEncode(const std::string &src, std::string &dst, bool append=false) { + urlEncode(src.c_str(), src.length(), dst, append); + } + + /** + * urlEncode(const char *, size_t, std::string &, bool) + * + * @param src buffer to be encoded (0 terminated) + * @param dst destination string + * @append true if string should not be cleared before encoding. + */ + static void urlEncode(const char *src, std::string &dst, bool append=false); + + /** + * urlEncode(const char *, size_t, std::string &, bool) + * + * @param src buffer to be encoded + * @param src_len length of buffer to be decoded + * @param dst destination string + * @append true if string should not be cleared before encoding. + */ + static void urlEncode(const char *src, size_t src_len, std::string &dst, bool append=false); + protected: /** diff --git a/include/civetweb.h b/include/civetweb.h index aa4409c4..0ffd5457 100644 --- a/include/civetweb.h +++ b/include/civetweb.h @@ -409,6 +409,11 @@ const char *mg_version(void); int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int is_form_url_encoded); +// URL-encode input buffer into destination buffer. +// returns the length of the resulting buffer or -1 +// is the buffer is too small. +int mg_url_encode(const char *src, char *dst, size_t dst_len); + // MD5 hash given strings. // Buffer 'buf' must be 33 bytes long. Varargs is a NULL terminated list of // ASCIIz strings. When function returns, buf will contain human-readable diff --git a/src/CivetServer.cpp b/src/CivetServer.cpp index 0c5b9bc8..fd394578 100644 --- a/src/CivetServer.cpp +++ b/src/CivetServer.cpp @@ -171,6 +171,11 @@ const char* CivetServer::getHeader(struct mg_connection *conn, const std::string return mg_get_header(conn, headerName.c_str()); } +void +CivetServer::urlDecode(const char *src, std::string &dst, bool is_form_url_encoded) { + urlDecode(src, strlen(src), dst, is_form_url_encoded); +} + void CivetServer::urlDecode(const char *src, size_t src_len, std::string &dst, bool is_form_url_encoded) { int i, j, a, b; @@ -236,3 +241,27 @@ CivetServer::getParam(const char *data, size_t data_len, const char *name, return false; } +void +CivetServer::urlEncode(const char *src, std::string &dst, bool append) { + urlEncode(src, strlen(src), dst, append); +} + +void +CivetServer::urlEncode(const char *src, size_t src_len, std::string &dst, bool append) { + static const char *dont_escape = "._-$,;~()"; + static const char *hex = "0123456789abcdef"; + + if (!append) + dst.clear(); + + for (; src_len > 0; src_len--) { + if (isalnum(*(const unsigned char *) src) || + strchr(dont_escape, * (const unsigned char *) src) != NULL) { + dst.push_back(*src); + } else { + dst.push_back('%'); + dst.push_back(hex[(* (const unsigned char *) src) >> 4]); + dst.push_back(hex[(* (const unsigned char *) src) & 0xf]); + } + } +} diff --git a/src/civetweb.c b/src/civetweb.c index c824c50c..21cbc8d6 100644 --- a/src/civetweb.c +++ b/src/civetweb.c @@ -2435,26 +2435,28 @@ static SOCKET conn2(const char *host, int port, int use_ssl, return sock; } - - -void mg_url_encode(const char *src, char *dst, size_t dst_len) { +int mg_url_encode(const char *src, char *dst, size_t dst_len) { static const char *dont_escape = "._-$,;~()"; static const char *hex = "0123456789abcdef"; + char *pos = dst; const char *end = dst + dst_len - 1; - for (; *src != '\0' && dst < end; src++, dst++) { + for (; *src != '\0' && pos < end; src++, pos++) { if (isalnum(*(const unsigned char *) src) || strchr(dont_escape, * (const unsigned char *) src) != NULL) { - *dst = *src; - } else if (dst + 2 < end) { - dst[0] = '%'; - dst[1] = hex[(* (const unsigned char *) src) >> 4]; - dst[2] = hex[(* (const unsigned char *) src) & 0xf]; - dst += 2; - } + *pos = *src; + } else if (pos + 2 < end) { + pos[0] = '%'; + pos[1] = hex[(* (const unsigned char *) src) >> 4]; + pos[2] = hex[(* (const unsigned char *) src) & 0xf]; + pos += 2; + } else { + return -1; + } } - *dst = '\0'; + *pos = '\0'; + return (*src == '\0') ? (int)(pos - dst) : -1; } static void print_dir_entry(struct de *de) {