tdlight/tdnet/td/net/HttpReader.h
levlam 692bc1f26d Fix leakage of a too big temporary file in HttpReader.
GitOrigin-RevId: b9bc7646013206fb30490cfb24e939eadb15e9c3
2018-08-27 15:52:47 +03:00

110 lines
3.6 KiB
C++

//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/net/HttpChunkedByteFlow.h"
#include "td/net/HttpContentLengthByteFlow.h"
#include "td/net/HttpQuery.h"
#include "td/utils/buffer.h"
#include "td/utils/ByteFlow.h"
#include "td/utils/common.h"
#include "td/utils/GzipByteFlow.h"
#include "td/utils/port/FileFd.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"
#include <limits>
namespace td {
class HttpReader {
public:
void init(ChainBufferReader *input, size_t max_post_size = std::numeric_limits<size_t>::max(),
size_t max_files = 100);
Result<size_t> read_next(HttpQuery *query) TD_WARN_UNUSED_RESULT; // TODO move query to init
HttpReader() = default;
HttpReader(const HttpReader &other) = delete;
HttpReader &operator=(const HttpReader &other) = delete;
HttpReader(HttpReader &&other) = delete;
HttpReader &operator=(HttpReader &&other) = delete;
~HttpReader() {
if (!temp_file_.empty()) {
temp_file_.close();
}
}
static void delete_temp_file(CSlice file_name);
private:
size_t max_post_size_;
size_t max_files_;
enum { ReadHeaders, ReadContent, ReadContentToFile, ReadArgs, ReadMultipartFormData } state_;
size_t headers_read_length_;
size_t content_length_;
ChainBufferReader *input_;
ByteFlowSource flow_source_;
HttpChunkedByteFlow chunked_flow_;
GzipByteFlow gzip_flow_;
HttpContentLengthByteFlow content_length_flow_;
ByteFlowSink flow_sink_;
ChainBufferReader *content_;
HttpQuery *query_;
Slice transfer_encoding_;
Slice content_encoding_;
Slice content_type_;
string content_type_lowercased_;
size_t total_parameters_length_;
size_t total_headers_length_;
string boundary_;
size_t form_data_read_length_;
size_t form_data_skipped_length_;
enum {
SkipPrologue,
ReadPartHeaders,
ReadPartValue,
ReadFile,
CheckForLastBoundary,
SkipEpilogue
} form_data_parse_state_;
MutableSlice field_name_;
string file_field_name_;
string field_content_type_;
string file_name_;
FileFd temp_file_;
string temp_file_name_;
int64 file_size_;
Result<size_t> split_header() TD_WARN_UNUSED_RESULT;
void process_header(MutableSlice header_name, MutableSlice header_value);
Result<bool> parse_multipart_form_data() TD_WARN_UNUSED_RESULT;
Status parse_url(MutableSlice url) TD_WARN_UNUSED_RESULT;
Status parse_parameters(MutableSlice parameters) TD_WARN_UNUSED_RESULT;
Status parse_json_parameters(MutableSlice parameters) TD_WARN_UNUSED_RESULT;
Status parse_head(MutableSlice head) TD_WARN_UNUSED_RESULT;
Status open_temp_file(CSlice desired_file_name) TD_WARN_UNUSED_RESULT;
Status try_open_temp_file(Slice directory_name, CSlice desired_file_name) TD_WARN_UNUSED_RESULT;
Status save_file_part(BufferSlice &&file_part) TD_WARN_UNUSED_RESULT;
void close_temp_file();
void clean_temporary_file();
static constexpr size_t MAX_CONTENT_SIZE = 150 << 20; // Some reasonable limit
static constexpr size_t MAX_TOTAL_PARAMETERS_LENGTH = 1 << 16; // Some reasonable limit
static constexpr size_t MAX_TOTAL_HEADERS_LENGTH = 1 << 18; // Some reasonable limit
static constexpr size_t MAX_BOUNDARY_LENGTH = 70; // As defined by RFC1341
static constexpr int64 MAX_FILE_SIZE = 1500 << 20; // Telegram server file size limit
static constexpr const char TEMP_DIRECTORY_PREFIX[] = "tdlib-server-tmp";
};
} // namespace td