<commit_before>/* <x0/HttpRequest.cpp>
 *
 * This file is part of the x0 web server project and is released under LGPL-3.
 * http://www.xzero.io/
 *
 * (c) 2009-2012 <NAME> <<EMAIL>>
 */

#include <x0/http/HttpRequest.h>
#include <x0/http/HttpConnection.h>
#include <x0/io/BufferSource.h>
#include <x0/io/FilterSource.h>
#include <x0/io/ChunkedEncoder.h>
#include <x0/Process.h>                // Process::dumpCore()
#include <x0/strutils.h>
#include <strings.h>                   // strcasecmp()
#include <stdlib.h>                   // realpath()
#include <limits.h>                   // PATH_MAX

#if !defined(NDEBUG)
#	define TRACE(level, msg...) log(Severity::debug ## level, "http-request: " msg)
#else
#	define TRACE(level, msg...) do { } while (0)
#endif

namespace x0 {

char HttpRequest::statusCodes_[512][4];

HttpRequest::HttpRequest(HttpConnection& conn) :
	outputState_(Unhandled),
	connection(conn),
	method(),
	unparsedUri(),
	path(),
	query(),
	pathinfo(),
	fileinfo(),
	httpVersionMajor(0),
	httpVersionMinor(0),
	hostname(),
	requestHeaders(),
	bytesTransmitted_(0),
	username(),
	documentRoot(),
	expectingContinue(false),
	//customData(),

	status(),
	responseHeaders(),
	outputFilters(),

	inspectHandlers_(),

	hostid_(),
	directoryDepth_(0),
	bodyCallback_(nullptr),
	bodyCallbackData_(nullptr),
	errorHandler_(nullptr)
{
#ifndef NDEBUG
	static std::atomic<unsigned long long> rid(0);
	setLoggingPrefix("HttpRequest(%lld,%s:%d)", ++rid, connection.remoteIP().c_str(), connection.remotePort());
#endif

	responseHeaders.push_back("Date", connection.worker().now().http_str().str());
}

HttpRequest::~HttpRequest()
{
	TRACE(2, "destructing");
}

/**
 * Sssigns unparsed URI to request and decodes it for path and query attributes.
 *
 * We also compute the directory depth for directory traversal detection.
 *
 * \see HttpRequest::path
 * \see HttpRequest::query
 * \see HttpRequest::testDirectoryTraversal()
 */
bool HttpRequest::setUri(const BufferRef& uri)
{
	unparsedUri = uri;

	if (unparsedUri == "*") {
		// XXX this is a special case, described in RFC 2616, section 5.1.2
		path = "*";
		return true;
	}

	enum class UriState {
		Content,
		Slash,
		Dot,
		DotDot,
		QuoteStart,
		QuoteChar2,
		QueryStart,
	};

#if !defined(NDEBUG)
	static const char* uriStateNames[] = {
		"Content",
		"Slash",
		"Dot",
		"DotDot",
		"QuoteStart",
		"QuoteChar2",
		"QueryStart",
	};
#endif

	const unsigned char* i = (const unsigned char*) unparsedUri.begin();
	const unsigned char* e = (const unsigned char*) unparsedUri.end() + 1;

	int depth = 0;
	UriState state = UriState::Content;
	UriState quotedState;
	unsigned char decodedChar;
	unsigned char ch = *i++;

#if !defined(NDEBUG) // suppress uninitialized warning
	quotedState = UriState::Content;
	decodedChar = '\0';<commit_msg>quick-fix signedness<commit_after>/* <x0/HttpRequest.cpp>
 *
 * This file is part of the x0 web server project and is released under LGPL-3.
 * http://www.xzero.io/
 *
 * (c) 2009-2012 <NAME> <<EMAIL>>
 */

#include <x0/http/HttpRequest.h>
#include <x0/http/HttpConnection.h>
#include <x0/io/BufferSource.h>
#include <x0/io/FilterSource.h>
#include <x0/io/ChunkedEncoder.h>
#include <x0/Process.h>                // Process::dumpCore()
#include <x0/strutils.h>
#include <strings.h>                   // strcasecmp()
#include <stdlib.h>                   // realpath()
#include <limits.h>                   // PATH_MAX

#if !defined(NDEBUG)
#	define TRACE(level, msg...) log(Severity::debug ## level, "http-request: " msg)
#else
#	define TRACE(level, msg...) do { } while (0)
#endif

namespace x0 {

char HttpRequest::statusCodes_[512][4];

HttpRequest::HttpRequest(HttpConnection& conn) :
	outputState_(Unhandled),
	connection(conn),
	method(),
	unparsedUri(),
	path(),
	query(),
	pathinfo(),
	fileinfo(),
	httpVersionMajor(0),
	httpVersionMinor(0),
	hostname(),
	requestHeaders(),
	bytesTransmitted_(0),
	username(),
	documentRoot(),
	expectingContinue(false),
	//customData(),

	status(),
	responseHeaders(),
	outputFilters(),

	inspectHandlers_(),

	hostid_(),
	directoryDepth_(0),
	bodyCallback_(nullptr),
	bodyCallbackData_(nullptr),
	errorHandler_(nullptr)
{
#ifndef NDEBUG
	static std::atomic<unsigned long long> rid(0);
	setLoggingPrefix("HttpRequest(%lld,%s:%d)", ++rid, connection.remoteIP().c_str(), connection.remotePort());
#endif

	responseHeaders.push_back("Date", connection.worker().now().http_str().str());
}

HttpRequest::~HttpRequest()
{
	TRACE(2, "destructing");
}

/**
 * Sssigns unparsed URI to request and decodes it for path and query attributes.
 *
 * We also compute the directory depth for directory traversal detection.
 *
 * \see HttpRequest::path
 * \see HttpRequest::query
 * \see HttpRequest::testDirectoryTraversal()
 */
bool HttpRequest::setUri(const BufferRef& uri)
{
	unparsedUri = uri;

	if (unparsedUri == "*") {
		// XXX this is a special case, described in RFC 2616, section 5.1.2
		path = "*";
		return true;
	}

	enum class UriState {
		Content,
		Slash,
		Dot,
		DotDot,
		QuoteStart,
		QuoteChar2,
		QueryStart,
	};

#if !defined(NDEBUG)
	static const char* uriStateNames[] = {
		"Content",
		"Slash",
		"Dot",
		"DotDot",
		"QuoteStart",
		"QuoteChar2",
		"QueryStart",
	};
#endif

	const char* i = unparsedUri.begin();
	const char* e = unparsedUri.end() + 1;

	int depth = 0;
	UriState state = UriState::Content;
	UriState quotedState;
	unsigned char decodedChar;
	char ch = *i++;

#if !defined(NDEBUG) // suppress uninitialized warning
	quotedState = UriState::Content;
	decodedChar = '\0';
{'fraction_non_alphanumeric': 0.15860700108264164, 'fraction_numerical': 0.015156983038614218, 'mean_word_length': 4.190074906367041, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2816438', 'n_tokens_mistral': 2004, 'n_tokens_neox': 1911, 'n_words': 449}