diff options
| author | Glenn Smith <glenn@vector35.com> | 2021-08-13 16:14:48 -0400 |
|---|---|---|
| committer | Glenn Smith <glenn@vector35.com> | 2021-08-17 16:50:10 -0400 |
| commit | 54c78775ab4eb53c991ed17e4317bf876dea5bb0 (patch) | |
| tree | e3852837d01b1c1b6d683692a5ec92b764724195 /http.h | |
| parent | 176cc79219cdf015cbcf7f90bb6eb5f6a8c59940 (diff) | |
HTTP C++ library via downloadprovider
Diffstat (limited to 'http.h')
| -rw-r--r-- | http.h | 361 |
1 files changed, 361 insertions, 0 deletions
@@ -0,0 +1,361 @@ +// Copyright (c) 2015-2021 Vector 35 Inc +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#pragma once + +#include <vector> +#include <string> +#include <optional> +#include <unordered_map> +#include <functional> +#include <utility> +#include <stdint.h> +#include "binaryninjaapi.h" + + +namespace BinaryNinja::Http +{ + + enum ResponseCode + { + Continue = 100, + SwitchingProtocols = 101, + OK = 200, + Created = 201, + Accepted = 202, + NonAuthoritativeInformation = 203, + NoContent = 204, + ResetContent = 205, + PartialContent = 206, + MultipleChoices = 300, + MovedPermanently = 301, + Found = 302, + SeeOther = 303, + NotModified = 304, + UseProxy = 305, + TemporaryRedirect = 307, + BadRequest = 400, + Unauthorized = 401, + PaymentRequired = 402, + Forbidden = 403, + NotFound = 404, + MethodNotAllowed = 405, + NotAcceptable = 406, + ProxyAuthenticationRequired = 407, + RequestTimeout = 408, + Conflict = 409, + Gone = 410, + LengthRequired = 411, + PreconditionFailed = 412, + RequestEntityTooLarge = 413, + RequestURITooLong = 414, + UnsupportedMediaType = 415, + RequestedRangeNotSatisfiable = 416, + ExpectationFailed = 417, + ImATeapot = 418, + InternalServerError = 500, + NotImplemented = 501, + BadGateway = 502, + ServiceUnavailable = 503, + GatewayTimeout = 504, + HTTPVersionNotSupported = 505, + }; + + + /*! + Basic HTTP response structure + */ + struct Response + { + BinaryNinja::DownloadInstance::Response response; + std::vector<uint8_t> body; + std::string error; + + /*! + Get response body as uint8_t vector + \return Response body bytes + */ + std::vector<uint8_t> GetRaw() const noexcept; + /*! + Get response body as text string + \return Response body string + */ + std::string GetString() const noexcept; + /*! + Get response body as a json value + \return Response body json + \throws runtime_error On JSON parse error + */ + Json::Value GetJson() const; + /*! + Get response body as a json value without throwing + \param value Output json value + \return True if successful + */ + bool GetJson(Json::Value& value) const noexcept; + }; + + + /*! + Structure for multipart form fields + */ + struct MultipartField + { + std::string name; + std::vector<uint8_t> content; + std::optional<std::string> filename; + + /*! + Construct a Multipart Field structure with a UTF-8 string encoded body + \param name Name of the field to be sent in a POST request + \param content Contents of the field + */ + MultipartField(std::string name, const std::string& content): + name(std::move(name)), content({}), filename({}) + { + std::copy(content.begin(), content.end(), std::back_inserter(this->content)); + } + + /*! + Construct a Multipart Field structure for a file with a UTF-8 string encoded body + \param name Name of the field to be sent in a POST request + \param content Contents of the field + \param filename Filename associated with the contents + */ + MultipartField(std::string name, const std::string& content, std::string filename): + name(std::move(name)), content({}), filename(std::move(filename)) + { + std::copy(content.begin(), content.end(), std::back_inserter(this->content)); + } + + /*! + Construct a Multipart Field structure with a binary blob body + \param name Name of the field to be sent in a POST request + \param content Contents of the field + */ + MultipartField(std::string name, std::vector<uint8_t> content): + name(std::move(name)), content(std::move(content)), filename({}) + { + + } + + /*! + Construct a Multipart Field structure for a file with a binary blob body + \param name Name of the field to be sent in a POST request + \param content Contents of the field + \param filename Filename associated with the contents + */ + MultipartField(std::string name, std::vector<uint8_t> content, std::string filename): + name(std::move(name)), content(std::move(content)), filename(std::move(filename)) + { + + } + }; + + + /*! + Structure containing HTTP metadata for requests + */ + struct Request + { + std::string m_method; + std::string m_url; + std::unordered_map<std::string, std::string> m_headers; + std::vector<uint8_t> m_body; + + std::function<bool(size_t, size_t)> m_downloadProgress; + std::function<bool(size_t, size_t)> m_uploadProgress; + + /*! + Construct an arbitrary HTTP request with an empty body + \param method Request method eg GET + \param url Target URL eg https://binary.ninja + \param headers Header keys/values + \param params Query parameters, keys/values + \param downloadProgress Function to call for download progress updates + \param uploadProgress Function to call for upload progress updates + */ + Request(std::string method, std::string url, + std::unordered_map<std::string, std::string> headers = {}, + std::vector<std::pair<std::string, std::string>> params = {}, + std::function<bool(size_t, size_t)> downloadProgress = {}, + std::function<bool(size_t, size_t)> uploadProgress = {}); + + + /*! + Construct an arbitrary HTTP request with a binary data body + \param method Request method eg GET + \param url Target URL eg https://binary.ninja + \param headers Header keys/values + \param params Query parameters, keys/values + \param body Content body (binary data) + \param downloadProgress Function to call for download progress updates + \param uploadProgress Function to call for upload progress updates + */ + Request(std::string method, std::string url, + std::unordered_map<std::string, std::string> headers, + std::vector<std::pair<std::string, std::string>> params, + std::vector<uint8_t> body, + std::function<bool(size_t, size_t)> downloadProgress = {}, + std::function<bool(size_t, size_t)> uploadProgress = {}); + + + /*! + Construct an arbitrary HTTP request with url encoded form fields as the body + \param method Request method eg GET + \param url Target URL eg https://binary.ninja + \param headers Header keys/values + \param params Query parameters, keys/values + \param formFields HTTP form fields, keys/values (both must be strings) + \param downloadProgress Function to call for download progress updates + \param uploadProgress Function to call for upload progress updates + */ + Request(std::string method, std::string url, + std::unordered_map<std::string, std::string> headers, + std::vector<std::pair<std::string, std::string>> params, + std::vector<std::pair<std::string, std::string>> formFields, + std::function<bool(size_t, size_t)> downloadProgress = {}, + std::function<bool(size_t, size_t)> uploadProgress = {}); + + + /*! + Construct an arbitrary HTTP request with Multipart encoded form fields as the body + \param method Request method eg GET + \param url Target URL eg https://binary.ninja + \param headers Header keys/values + \param params Query parameters, keys/values + \param formFields HTTP form fields, keys/values (values can be arbitrary data) + \param downloadProgress Function to call for download progress updates + \param uploadProgress Function to call for upload progress updates + */ + Request(std::string method, std::string url, + std::unordered_map<std::string, std::string> headers, + std::vector<std::pair<std::string, std::string>> params, + std::vector<MultipartField> formFields, + std::function<bool(size_t, size_t)> downloadProgress = {}, + std::function<bool(size_t, size_t)> uploadProgress = {}); + + + /*! + Construct an HTTP GET request + \param url Target URL eg https://binary.ninja + \param headers Header keys/values + \param params Query parameters, keys/values + \param downloadProgress Function to call for download progress updates + \param uploadProgress Function to call for upload progress updates + \return Request structure with specified fields + */ + static Request Get(std::string url, + std::unordered_map<std::string, std::string> headers = {}, + std::vector<std::pair<std::string, std::string>> params = {}, + std::function<bool(size_t, size_t)> downloadProgress = {}, + std::function<bool(size_t, size_t)> uploadProgress = {}); + + + /*! + Construct an HTTP POST request with a binary data body + \param url Target URL eg https://binary.ninja + \param headers Header keys/values + \param params Query parameters, keys/values + \param body Request body data + \param downloadProgress Function to call for download progress updates + \param uploadProgress Function to call for upload progress updates + \return Request structure with specified fields + */ + static Request Post(std::string url, + std::unordered_map<std::string, std::string> headers = {}, + std::vector<std::pair<std::string, std::string>> params = {}, + std::vector<uint8_t> body = {}, + std::function<bool(size_t, size_t)> downloadProgress = {}, + std::function<bool(size_t, size_t)> uploadProgress = {}); + + + /*! + Construct an HTTP POST request with url encoded form fields as the body + \param url Target URL eg https://binary.ninja + \param headers Header keys/values + \param params Query parameters, keys/values + \param formFields HTTP form fields, keys/values (both must be strings) + \param downloadProgress Function to call for download progress updates + \param uploadProgress Function to call for upload progress updates + \return Request structure with specified fields + */ + static Request Post(std::string url, + std::unordered_map<std::string, std::string> headers, + std::vector<std::pair<std::string, std::string>> params, + std::vector<std::pair<std::string, std::string>> formFields, + std::function<bool(size_t, size_t)> downloadProgress = {}, + std::function<bool(size_t, size_t)> uploadProgress = {}); + + + /*! + Construct an HTTP POST request with Multipart encoded form fields as the body + \param url Target URL eg https://binary.ninja + \param headers Header keys/values + \param params Query parameters, keys/values + \param formFields HTTP form fields, keys/values (values can be arbitrary data) + \param downloadProgress Function to call for download progress updates + \param uploadProgress Function to call for upload progress updates + \return Request structure with specified fields + */ + static Request Post(std::string url, + std::unordered_map<std::string, std::string> headers, + std::vector<std::pair<std::string, std::string>> params, + std::vector<MultipartField> formFields, + std::function<bool(size_t, size_t)> downloadProgress = {}, + std::function<bool(size_t, size_t)> uploadProgress = {}); + }; + + + /*! + Convert a string to a URLEncoded form-field safe form + \param str Input string + \return URLEncoded string + */ + std::string UrlEncode(const std::string& str); + + + /*! + Convert a list of key/value pair strings into a URLEncoded form body + \param fields Input key/value pairs + \return URLEncoded form body + */ + std::string UrlEncode(const std::vector<std::pair<std::string, std::string>>& fields); + + + /*! + Convert a list of form fields (potentially containing binary data) into a multipart encoded + form body + \param fields Input fields + \param boundary Output boundary between fields in the body (for Content-Type header) + \return Multipart encoded form body + */ + std::vector<uint8_t> MultipartEncode(const std::vector<MultipartField>& fields, std::string& boundary); + + + /*! + Perform an HTTP request as specified by a Request, storing results in a Response + \param instance DownloadInstance instance + \param request Input Request structure with fields + \param response Output Response structure with body + \return Zero or greater on success + */ + int Perform(const BinaryNinja::Ref<BinaryNinja::DownloadInstance>& instance, const Request& request, Response& response); +}
\ No newline at end of file |
