This repository has been archived on 2020-05-10. You can view files and clone it, but cannot push or open issues or pull requests.
mastodon-cpp/src/mastodon-cpp.cpp

160 lines
4.2 KiB
C++

/* This file is part of mastodon-cpp.
* Copyright © 2018 tastytea <tastytea@tastytea.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
#include <map>
#include <vector>
#include "version.hpp"
#include "macros.hpp"
#include "mastodon-cpp.hpp"
#include <iostream>
using namespace Mastodon;
using std::string;
API::API(const string &instance, const string &access_token)
: _instance(instance)
, _access_token(access_token)
, _useragent(string("mastodon-cpp/") + global::version)
, _http(*this, instance, access_token)
{
//
}
const void API::set_useragent(const std::string &useragent)
{
_useragent = useragent;
}
const string API::get_useragent() const
{
return _useragent;
}
const std::string API::urlencode(const string &str) const
{
std::ostringstream oss;
for (const std::uint8_t &b: str)
{
// Check for unreserved characters (RFC 3986 section 2.3)
if ((b >= 0x30 && b <= 0x39) || // 0-9
(b >= 0x41 && b <= 0x5A) || // A-Z
(b >= 0x61 && b <= 0x7A) || // a-z
b == 0x2D || b == 0x2E || // -, .
b == 0x5F || b == 0x7E) // _, ~
{
oss << b;
}
else
{
oss << '%' << std::hex << std::uppercase << (int)(unsigned char)b;
}
}
return oss.str();
}
const string API::maptostr(const parametermap &map, const bool &firstparam)
{
string result = "";
char delim = '?';
if (!firstparam)
{
delim = '&';
}
for (const auto &it : map)
{
if (it.second.size() == 1)
{
result += (delim + it.first + "=" + urlencode(it.second.front()));
if (delim == '?')
{
delim = '&';
}
}
else
{
for (const string &str : it.second)
{
result += (delim + it.first + "[]=" + urlencode(str));
if (delim == '?')
{
delim = '&';
}
}
}
}
ttdebug << "Constructed parameter string: " << result << '\n';
return result;
}
const string API::maptoformdata(const parametermap &map)
{
if (map.size() == 0)
{
return "";
}
const string boundary = "MEEP";
string header;
string body;
header = "Content-type: multipart/form-data, boundary=" + boundary + "\r\n";
header += "Content-Length: ";
body = "--" + boundary;
for (const auto &it : map)
{
// This is directly after the last boundary
body += "\r\n";
if (it.second.size() == 1)
{
if (it.first == "avatar" ||
it.first == "header" ||
it.first == "file")
{
body += "Content-Transfer-Encoding: base64\r\n";
}
else
{
body += "Content-Transfer-Encoding: 8bit\r\n";
}
body += ("Content-Disposition: form-data; name=\"" +
it.first + "\"\r\n\r\n");
body += (it.second.front() + "\r\n--" + boundary);
}
else
{
for (const string &str : it.second)
{
body += ("Content-Disposition: form-data; name=\"" +
it.first + "[]\"\r\n\r\n");
body += (str + "\r\n--" + boundary);
}
}
}
// The last segment has to have "--" after the boundary
body += "--\r\n";
header += (std::to_string(body.length()) + "\r\n\r\n");
ttdebug << "Form data: \n" << header << body;
return header + body;
}