2013-05-31 21:04:42 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <string>
|
2020-09-29 10:44:47 +00:00
|
|
|
#include <cstring>
|
|
|
|
#include <cstdio>
|
2013-05-31 21:04:42 +00:00
|
|
|
#include <cstdarg>
|
2020-09-29 10:44:47 +00:00
|
|
|
#include <cstdint>
|
2020-10-14 21:30:40 +00:00
|
|
|
#include <cstdlib>
|
2016-06-12 16:07:04 +00:00
|
|
|
#include <vector>
|
2013-05-31 21:04:42 +00:00
|
|
|
|
2015-03-06 08:19:31 +00:00
|
|
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
2013-05-31 21:04:42 +00:00
|
|
|
#undef snprintf
|
|
|
|
#define snprintf _snprintf
|
|
|
|
#endif
|
|
|
|
|
|
|
|
struct UrlEncoder
|
|
|
|
{
|
|
|
|
UrlEncoder() : paramCount(0)
|
|
|
|
{
|
|
|
|
data.reserve(256);
|
2013-07-15 16:45:00 +00:00
|
|
|
}
|
2013-05-31 21:04:42 +00:00
|
|
|
|
2014-02-10 05:42:52 +00:00
|
|
|
virtual void Add(const std::string &key, const std::string &value)
|
2013-05-31 21:04:42 +00:00
|
|
|
{
|
|
|
|
if (++paramCount > 1)
|
|
|
|
data += '&';
|
|
|
|
AppendEscaped(key);
|
|
|
|
data += '=';
|
|
|
|
AppendEscaped(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Add(const std::string &key, const char *value)
|
|
|
|
{
|
|
|
|
Add(key, std::string(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Add(const std::string &key, const int value)
|
|
|
|
{
|
|
|
|
AddT(key, "%d", value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Add(const std::string &key, const uint32_t value)
|
|
|
|
{
|
|
|
|
AddT(key, "%u", value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Add(const std::string &key, const uint64_t value)
|
|
|
|
{
|
|
|
|
AddT(key, "%llu", value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Add(const std::string &key, const double value)
|
|
|
|
{
|
|
|
|
AddT(key, "%f", value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Add(const std::string &key, const bool value)
|
|
|
|
{
|
|
|
|
Add(key, value ? "true" : "false");
|
|
|
|
}
|
|
|
|
|
2014-02-10 05:56:34 +00:00
|
|
|
virtual void Finish()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-02-10 05:42:52 +00:00
|
|
|
const std::string &ToString() const
|
|
|
|
{
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2014-02-10 05:56:34 +00:00
|
|
|
virtual std::string GetMimeType() const
|
|
|
|
{
|
|
|
|
return "application/x-www-form-urlencoded";
|
|
|
|
}
|
|
|
|
|
2014-02-10 05:42:52 +00:00
|
|
|
protected:
|
|
|
|
template <typename T>
|
|
|
|
void AddT(const std::string &key, const char *fmt, const T value)
|
|
|
|
{
|
|
|
|
char temp[64];
|
|
|
|
snprintf(temp, sizeof(temp), fmt, value);
|
|
|
|
temp[sizeof(temp) - 1] = '\0';
|
|
|
|
Add(key, temp);
|
|
|
|
}
|
|
|
|
|
2013-05-31 21:04:42 +00:00
|
|
|
// Percent encoding, aka application/x-www-form-urlencoded.
|
|
|
|
void AppendEscaped(const std::string &value)
|
|
|
|
{
|
|
|
|
for (size_t lastEnd = 0; lastEnd < value.length(); )
|
|
|
|
{
|
|
|
|
size_t pos = value.find_first_not_of(unreservedChars, lastEnd);
|
|
|
|
if (pos == value.npos)
|
|
|
|
{
|
|
|
|
data += value.substr(lastEnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pos != lastEnd)
|
|
|
|
data += value.substr(lastEnd, pos - lastEnd);
|
|
|
|
lastEnd = pos;
|
|
|
|
|
|
|
|
// Encode the reserved character.
|
|
|
|
char c = value[pos];
|
|
|
|
data += '%';
|
|
|
|
data += hexChars[(c >> 4) & 15];
|
|
|
|
data += hexChars[(c >> 0) & 15];
|
|
|
|
++lastEnd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string data;
|
|
|
|
int paramCount;
|
|
|
|
static const char *unreservedChars;
|
|
|
|
static const char *hexChars;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-02-10 05:42:52 +00:00
|
|
|
// Stores everything in memory, not super efficient.
|
|
|
|
// Easy to swap out for a UrlEncoder.
|
|
|
|
struct MultipartFormDataEncoder : UrlEncoder
|
|
|
|
{
|
|
|
|
MultipartFormDataEncoder() : UrlEncoder()
|
|
|
|
{
|
|
|
|
data.reserve(8192);
|
|
|
|
int r1 = rand();
|
|
|
|
int r2 = rand();
|
|
|
|
char temp[256];
|
|
|
|
snprintf(temp, sizeof(temp), "NATIVE-DATA-BOUNDARY-%08x%08x-%d", r1, r2, seq++);
|
|
|
|
boundary = temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual void Add(const std::string &key, const std::string &value)
|
|
|
|
{
|
|
|
|
Add(key, value, "", "");
|
|
|
|
}
|
|
|
|
|
|
|
|
void Add(const std::string &key, const std::string &value, const std::string &filename, const std::string &mimeType)
|
|
|
|
{
|
|
|
|
data += "--" + boundary + "\r\n";
|
|
|
|
data += "Content-Disposition: form-data; name=\"" + key + "\"";
|
|
|
|
if (!filename.empty())
|
|
|
|
data += "; filename=\"" + filename + "\"";
|
|
|
|
data += "\r\n";
|
|
|
|
if (!mimeType.empty())
|
|
|
|
data += "Content-Type: " + mimeType + "\r\n";
|
|
|
|
char temp[64];
|
|
|
|
snprintf(temp, sizeof(temp), "Content-Length: %d\r\n", (int)value.size());
|
|
|
|
data += temp;
|
2016-06-12 16:07:04 +00:00
|
|
|
data += "Content-Transfer-Encoding: binary\r\n";
|
2014-02-10 05:42:52 +00:00
|
|
|
data += "\r\n";
|
|
|
|
|
|
|
|
data += value;
|
|
|
|
data += "\r\n";
|
|
|
|
}
|
|
|
|
|
2016-06-12 16:07:04 +00:00
|
|
|
void Add(const std::string &key, const std::vector<uint8_t> &value, const std::string &filename, const std::string &mimeType)
|
|
|
|
{
|
|
|
|
Add(key, std::string((const char *)&value[0], value.size()), filename, mimeType);
|
|
|
|
}
|
|
|
|
|
2014-02-10 05:56:34 +00:00
|
|
|
virtual void Finish()
|
2014-02-10 05:42:52 +00:00
|
|
|
{
|
|
|
|
data += "--" + boundary + "--";
|
|
|
|
}
|
|
|
|
|
2014-02-10 05:56:34 +00:00
|
|
|
virtual std::string GetMimeType() const
|
2014-02-10 05:42:52 +00:00
|
|
|
{
|
|
|
|
return "multipart/form-data; boundary=\"" + boundary + "\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
std::string boundary;
|
|
|
|
|
|
|
|
static int seq;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-05-31 21:04:42 +00:00
|
|
|
class Url {
|
|
|
|
public:
|
2013-07-15 16:45:00 +00:00
|
|
|
Url(const std::string url) : valid_(false), url_(url) {
|
2013-05-31 21:04:42 +00:00
|
|
|
Split();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Valid() const { return valid_; }
|
|
|
|
|
2014-12-31 17:36:51 +00:00
|
|
|
// Host = Hostname:Port, or just Hostname.
|
2013-05-31 21:04:42 +00:00
|
|
|
std::string Host() const { return host_; }
|
2014-12-31 17:36:51 +00:00
|
|
|
int Port() const { return port_; }
|
2013-05-31 21:04:42 +00:00
|
|
|
std::string Protocol() const { return protocol_; }
|
|
|
|
std::string Resource() const { return resource_; }
|
|
|
|
|
2019-06-23 19:21:56 +00:00
|
|
|
Url Relative(const std::string &next) const;
|
|
|
|
|
|
|
|
std::string ToString() const;
|
|
|
|
|
2013-05-31 21:04:42 +00:00
|
|
|
private:
|
|
|
|
void Split();
|
|
|
|
bool valid_;
|
|
|
|
std::string url_;
|
|
|
|
std::string host_;
|
|
|
|
std::string resource_;
|
|
|
|
std::string protocol_;
|
2014-12-31 17:36:51 +00:00
|
|
|
int port_;
|
2013-06-09 11:39:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
std::string UriDecode(const std::string & sSrc);
|
|
|
|
std::string UriEncode(const std::string & sSrc);
|