Comparar commits
20 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| e8141ac49d | |||
| 4cf537888b | |||
| 2752b5bbb1 | |||
| cc6cbf3852 | |||
| 1a4fac8a25 | |||
| ae6443500e | |||
| e42452e4f2 | |||
| 1dd7e6165e | |||
| 01ef59346e | |||
| 9380a44469 | |||
| 3f859af167 | |||
| 55ecfbdbb6 | |||
| f951cb8d88 | |||
| 2a3225ecd0 | |||
| 65cfdabb76 | |||
| 25a26c6bd7 | |||
| 3effbfe5d1 | |||
| 3a708166b8 | |||
| 3c17422435 | |||
| d3f23f393f |
@@ -443,6 +443,9 @@ static void pcre_log_error(const char *func, int line, int pcre_code,
|
||||
const char *repl, int repl_size,
|
||||
int arg1 = 0, int arg2 = 0,
|
||||
int arg3 = 0, int arg4 = 0) {
|
||||
if (!RuntimeOption::EnableHipHopSyntax) {
|
||||
return;
|
||||
}
|
||||
const char *escapedPattern;
|
||||
const char *escapedSubject;
|
||||
const char *escapedRepl;
|
||||
|
||||
@@ -926,13 +926,6 @@ c_PDO::c_PDO(Class* cb) : ExtObjectData(cb) {
|
||||
c_PDO::~c_PDO() {
|
||||
}
|
||||
|
||||
void c_PDO::sweep() {
|
||||
// PDOConnection is not sweepable, so clean it up manually.
|
||||
static_assert(!std::is_base_of<Sweepable, PDOConnection>::value,
|
||||
"Remove the call to reset() below.");
|
||||
m_dbh.detach();
|
||||
}
|
||||
|
||||
void c_PDO::t___construct(const String& dsn, const String& username /* = null_string */,
|
||||
const String& password /* = null_string */,
|
||||
CArrRef options /* = null_array */) {
|
||||
@@ -2642,10 +2635,6 @@ c_PDOStatement::~c_PDOStatement() {
|
||||
m_row.reset();
|
||||
}
|
||||
|
||||
void c_PDOStatement::sweep() {
|
||||
// No resources allocated outside HHVM's control
|
||||
}
|
||||
|
||||
Variant c_PDOStatement::t_execute(CArrRef params /* = null_array */) {
|
||||
SYNC_VM_REGS_SCOPED();
|
||||
strcpy(m_stmt->error_code, PDO_ERR_NONE);
|
||||
|
||||
@@ -112,9 +112,9 @@ extern const int64_t q_PDO$$MYSQL_ATTR_IGNORE_SPACE;
|
||||
// class PDO
|
||||
|
||||
FORWARD_DECLARE_CLASS(PDO);
|
||||
class c_PDO : public ExtObjectData, public Sweepable {
|
||||
class c_PDO : public ExtObjectData {
|
||||
public:
|
||||
DECLARE_CLASS(PDO)
|
||||
DECLARE_CLASS_NO_SWEEP(PDO)
|
||||
|
||||
// need to implement
|
||||
public: c_PDO(Class* cls = c_PDO::classof());
|
||||
@@ -152,9 +152,9 @@ class c_PDO : public ExtObjectData, public Sweepable {
|
||||
// class PDOStatement
|
||||
|
||||
FORWARD_DECLARE_CLASS(PDOStatement);
|
||||
class c_PDOStatement : public ExtObjectData, public Sweepable {
|
||||
class c_PDOStatement : public ExtObjectData {
|
||||
public:
|
||||
DECLARE_CLASS(PDOStatement)
|
||||
DECLARE_CLASS_NO_SWEEP(PDOStatement)
|
||||
|
||||
// need to implement
|
||||
public: c_PDOStatement(Class* cls = c_PDOStatement::classof());
|
||||
|
||||
@@ -1244,6 +1244,9 @@ void c_LibXMLError::t___construct() {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// libxml
|
||||
|
||||
static xmlParserInputBufferPtr
|
||||
hphp_libxml_input_buffer(const char *URI, xmlCharEncoding enc);
|
||||
|
||||
class xmlErrorVec : public std::vector<xmlError> {
|
||||
public:
|
||||
~xmlErrorVec() {
|
||||
@@ -1263,13 +1266,15 @@ public:
|
||||
virtual void requestInit() {
|
||||
m_use_error = false;
|
||||
m_errors.reset();
|
||||
xmlParserInputBufferCreateFilenameDefault(nullptr);
|
||||
m_entity_loader_disabled = false;
|
||||
xmlParserInputBufferCreateFilenameDefault(hphp_libxml_input_buffer);
|
||||
}
|
||||
virtual void requestShutdown() {
|
||||
m_use_error = false;
|
||||
m_errors.reset();
|
||||
}
|
||||
|
||||
bool m_entity_loader_disabled;
|
||||
bool m_use_error;
|
||||
xmlErrorVec m_errors;
|
||||
};
|
||||
@@ -1376,19 +1381,19 @@ void f_libxml_set_streams_context(CResRef streams_context) {
|
||||
}
|
||||
|
||||
static xmlParserInputBufferPtr
|
||||
hphp_libxml_input_buffer_noload(const char *URI, xmlCharEncoding enc) {
|
||||
return nullptr;
|
||||
hphp_libxml_input_buffer(const char *URI, xmlCharEncoding enc) {
|
||||
if (s_libxml_errors->m_entity_loader_disabled) {
|
||||
return nullptr;
|
||||
}
|
||||
return __xmlParserInputBufferCreateFilename(URI, enc);
|
||||
}
|
||||
|
||||
bool f_libxml_disable_entity_loader(bool disable /* = true */) {
|
||||
xmlParserInputBufferCreateFilenameFunc old;
|
||||
bool old = s_libxml_errors->m_entity_loader_disabled;
|
||||
|
||||
if (disable) {
|
||||
old = xmlParserInputBufferCreateFilenameDefault(hphp_libxml_input_buffer_noload);
|
||||
} else {
|
||||
old = xmlParserInputBufferCreateFilenameDefault(nullptr);
|
||||
}
|
||||
return (old == hphp_libxml_input_buffer_noload);
|
||||
s_libxml_errors->m_entity_loader_disabled = disable;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -72,6 +72,12 @@ PDOConnection::PDOConnection()
|
||||
PDOConnection::~PDOConnection() {
|
||||
}
|
||||
|
||||
void PDOConnection::sweep() {
|
||||
assert(!is_persistent);
|
||||
def_stmt_ctor_args.asTypedValue()->m_type = KindOfNull;
|
||||
delete this;
|
||||
}
|
||||
|
||||
void PDOConnection::persistentSave() {
|
||||
String serialized = f_serialize(def_stmt_ctor_args);
|
||||
serialized_def_stmt_ctor_args = string(serialized.data(), serialized.size());
|
||||
|
||||
@@ -235,7 +235,7 @@ class PDOStatement;
|
||||
typedef SmartResource<PDOStatement> sp_PDOStatement;
|
||||
|
||||
/* represents a connection to a database */
|
||||
class PDOConnection : public ResourceData {
|
||||
class PDOConnection : public SweepableResourceData {
|
||||
public:
|
||||
static const char *PersistentKey;
|
||||
|
||||
@@ -259,6 +259,7 @@ public:
|
||||
PDOConnection();
|
||||
virtual ~PDOConnection();
|
||||
virtual bool create(CArrRef options) = 0;
|
||||
virtual void sweep();
|
||||
|
||||
CLASSNAME_IS("PDOConnection")
|
||||
// overriding ResourceData
|
||||
|
||||
@@ -114,6 +114,15 @@ bool PDOSqliteConnection::create(CArrRef options) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PDOSqliteConnection::sweep() {
|
||||
for (auto& udf : m_udfs) {
|
||||
udf->func.asTypedValue()->m_type = KindOfNull;
|
||||
udf->step.asTypedValue()->m_type = KindOfNull;
|
||||
udf->fini.asTypedValue()->m_type = KindOfNull;
|
||||
}
|
||||
PDOConnection::sweep();
|
||||
}
|
||||
|
||||
bool PDOSqliteConnection::support(SupportedMethod method) {
|
||||
return method != MethodCheckLiveness;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ public:
|
||||
PDOSqliteConnection();
|
||||
virtual ~PDOSqliteConnection();
|
||||
virtual bool create(CArrRef options);
|
||||
virtual void sweep();
|
||||
|
||||
int handleError(const char *file, int line, PDOStatement *stmt = nullptr);
|
||||
|
||||
|
||||
@@ -62,7 +62,8 @@ void FastCGIAcceptor::onNewConnection(
|
||||
localAddress = s_unknownSocketAddress;
|
||||
}
|
||||
|
||||
FastCGIConnection* conn = new FastCGIConnection(
|
||||
// Will delete itself when it gets a closing callback
|
||||
auto conn = new FastCGIConnection(
|
||||
m_server,
|
||||
std::move(sock),
|
||||
localAddress,
|
||||
@@ -145,6 +146,7 @@ void FastCGIConnection::onSessionError() {
|
||||
|
||||
void FastCGIConnection::onSessionClose() {
|
||||
shutdownTransport();
|
||||
delete this;
|
||||
}
|
||||
|
||||
void FastCGIConnection::setMaxConns(int max_conns) {
|
||||
|
||||
@@ -527,8 +527,8 @@ void FastCGISession::handleStdErr(RequestId request_id,
|
||||
}
|
||||
|
||||
void FastCGISession::handleComplete(RequestId request_id) {
|
||||
writeEndRequest(request_id, 0, ProtoStatus::REQUEST_COMPLETE);
|
||||
endTransaction(request_id);
|
||||
writeEndRequest(request_id, 0, ProtoStatus::REQUEST_COMPLETE);
|
||||
if (!m_keepConn) {
|
||||
handleClose();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "hphp/runtime/server/fastcgi/fastcgi-transport.h"
|
||||
#include "hphp/runtime/server/fastcgi/fastcgi-server.h"
|
||||
#include "hphp/runtime/server/transport.h"
|
||||
#include "hphp/runtime/base/runtime-error.h"
|
||||
#include "folly/io/IOBuf.h"
|
||||
#include "folly/io/IOBufQueue.h"
|
||||
#include "thrift/lib/cpp/async/TAsyncTransport.h"
|
||||
@@ -27,6 +28,9 @@
|
||||
#include "hphp/util/timer.h"
|
||||
#include "folly/MoveWrapper.h"
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
using folly::IOBuf;
|
||||
using folly::IOBufQueue;
|
||||
using folly::io::Cursor;
|
||||
@@ -39,22 +43,48 @@ namespace HPHP {
|
||||
FastCGITransport::FastCGITransport(FastCGIConnection* connection, int id)
|
||||
: m_connection(connection),
|
||||
m_id(id),
|
||||
m_remotePort(0), m_method(Method::Unknown), m_requestSize(0),
|
||||
m_headersSent(false), m_readMore(false),
|
||||
m_waiting(0), m_readComplete(false) {}
|
||||
m_remotePort(0),
|
||||
m_serverPort(0),
|
||||
m_method(Method::Unknown),
|
||||
m_requestSize(0),
|
||||
m_headersSent(false),
|
||||
m_readMore(false),
|
||||
m_waiting(0),
|
||||
m_readComplete(false) {}
|
||||
|
||||
const char *FastCGITransport::getUrl() {
|
||||
return m_requestURI.c_str();
|
||||
}
|
||||
|
||||
const std::string FastCGITransport::getDocumentRoot() {
|
||||
return m_documentRoot;
|
||||
}
|
||||
|
||||
const char *FastCGITransport::getRemoteHost() {
|
||||
return m_remoteHost.c_str();
|
||||
}
|
||||
|
||||
const char *FastCGITransport::getRemoteAddr() {
|
||||
return m_remoteAddr.c_str();
|
||||
}
|
||||
|
||||
uint16_t FastCGITransport::getRemotePort() {
|
||||
return m_remotePort;
|
||||
}
|
||||
|
||||
const char *FastCGITransport::getServerName() {
|
||||
return m_serverName.c_str();
|
||||
}
|
||||
|
||||
const char *FastCGITransport::getServerAddr() {
|
||||
return (!m_serverAddr.empty()) ? m_serverAddr.c_str() :
|
||||
Transport::getServerAddr();
|
||||
}
|
||||
|
||||
uint16_t FastCGITransport::getServerPort() {
|
||||
return (m_serverPort != 0) ? m_serverPort : Transport::getServerPort();
|
||||
}
|
||||
|
||||
const void *FastCGITransport::getPostData(int &size) {
|
||||
DCHECK(!m_readMore);
|
||||
return getPostDataImpl(size, false);
|
||||
@@ -127,7 +157,48 @@ const char *FastCGITransport::getServerObject() {
|
||||
return m_serverObject.c_str();
|
||||
}
|
||||
|
||||
std::string FastCGITransport::unmangleHeader(const std::string& name) {
|
||||
if (!boost::istarts_with(name, "HTTP_")) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string ret;
|
||||
bool is_upper = true;
|
||||
for (auto& c : name.substr(5)) {
|
||||
if (c == '_') {
|
||||
ret += '-';
|
||||
is_upper = true;
|
||||
} else {
|
||||
ret += is_upper ? toupper(c) : tolower(c);
|
||||
is_upper = false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string FastCGITransport::mangleHeader(const std::string& name) {
|
||||
std::string ret;
|
||||
for (auto& c : name) {
|
||||
if (c == '-') {
|
||||
ret += '_';
|
||||
} else {
|
||||
ret += toupper(c);
|
||||
}
|
||||
}
|
||||
return "HTTP_" + ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passed an HTTP header like "Cookie" or "Cache-Control"
|
||||
**/
|
||||
std::string FastCGITransport::getHeader(const char *name) {
|
||||
return getRawHeader(mangleHeader(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Passed a FastCGI mangled header like "HTTP_COOKIE" or "HTTP_CACHE_CONTROL"
|
||||
**/
|
||||
std::string FastCGITransport::getRawHeader(const std::string& name) {
|
||||
if (m_requestHeaders.count(name) && m_requestHeaders[name].size()) {
|
||||
return m_requestHeaders[name][0];
|
||||
} else {
|
||||
@@ -136,12 +207,22 @@ std::string FastCGITransport::getHeader(const char *name) {
|
||||
}
|
||||
|
||||
void FastCGITransport::getHeaders(HeaderMap &headers) {
|
||||
headers = m_requestHeaders;
|
||||
for (auto& pair : m_requestHeaders) {
|
||||
auto key = unmangleHeader(pair.first);
|
||||
if (!key.empty()) {
|
||||
headers[key] = pair.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FastCGITransport::getTransportParams(HeaderMap &serverParams) {
|
||||
for (auto& pair : m_requestHeaders) {
|
||||
serverParams[pair.first] = pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
void FastCGITransport::addHeaderImpl(const char *name, const char *value) {
|
||||
CHECK(!m_headersSent);
|
||||
|
||||
if (!m_responseHeaders.count(name)) {
|
||||
m_responseHeaders.insert(std::make_pair(name,
|
||||
std::vector<std::string>()));
|
||||
@@ -221,10 +302,16 @@ void FastCGITransport::onBodyComplete() {
|
||||
|
||||
const std::string FastCGITransport::k_requestURIKey = "REQUEST_URI";
|
||||
const std::string FastCGITransport::k_remoteHostKey = "REMOTE_HOST";
|
||||
const std::string FastCGITransport::k_remoteAddrKey = "REMOTE_ADDR";
|
||||
const std::string FastCGITransport::k_remotePortKey = "REMOTE_PORT";
|
||||
const std::string FastCGITransport::k_methodKey = "REQUEST_METHOD";
|
||||
const std::string FastCGITransport::k_httpVersionKey = "HTTP_VERSION";
|
||||
const std::string FastCGITransport::k_contentLengthKey = "CONTENT_LENGTH";
|
||||
const std::string FastCGITransport::k_documentRoot = "DOCUMENT_ROOT";
|
||||
const std::string FastCGITransport::k_serverNameKey = "SERVER_NAME";
|
||||
const std::string FastCGITransport::k_serverPortKey = "SERVER_PORT";
|
||||
const std::string FastCGITransport::k_serverAddrKey = "SERVER_ADDR";
|
||||
const std::string FastCGITransport::k_httpsKey = "HTTPS";
|
||||
|
||||
void FastCGITransport::onHeader(std::unique_ptr<folly::IOBuf> key_chain,
|
||||
std::unique_ptr<folly::IOBuf> value_chain) {
|
||||
@@ -254,6 +341,8 @@ void FastCGITransport::handleHeader(const std::string& key,
|
||||
m_requestURI = value;
|
||||
} else if (compareKeys(key, k_remoteHostKey)) {
|
||||
m_remoteHost = value;
|
||||
} else if (compareKeys(key, k_remoteAddrKey)) {
|
||||
m_remoteAddr = value;
|
||||
} else if (compareKeys(key, k_remotePortKey)) {
|
||||
try {
|
||||
int remote_port = std::stoi(value);
|
||||
@@ -267,6 +356,27 @@ void FastCGITransport::handleHeader(const std::string& key,
|
||||
} catch (std::out_of_range&) {
|
||||
m_remotePort = 0;
|
||||
}
|
||||
} else if (compareKeys(key, k_serverNameKey)) {
|
||||
m_serverName = value;
|
||||
} else if (compareKeys(key, k_httpsKey)) {
|
||||
if (!value.empty()) {
|
||||
std::string lValue(value);
|
||||
boost::to_lower(lValue);
|
||||
// IIS sets this value but sets it to off when SSL is off.
|
||||
if (lValue.compare("off") != 0) {
|
||||
setSSL();
|
||||
}
|
||||
}
|
||||
} else if (compareKeys(key, k_serverAddrKey)) {
|
||||
m_serverAddr = value;
|
||||
} else if (compareKeys(key, k_serverPortKey)) {
|
||||
try {
|
||||
m_serverPort = std::stoi(value);
|
||||
} catch (std::invalid_argument&) {
|
||||
m_serverPort = 0;
|
||||
} catch (std::out_of_range&) {
|
||||
m_serverPort = 0;
|
||||
}
|
||||
} else if (compareKeys(key, k_methodKey)) {
|
||||
m_extendedMethod = value;
|
||||
if (compareValues(value, "GET")) {
|
||||
@@ -288,12 +398,23 @@ void FastCGITransport::handleHeader(const std::string& key,
|
||||
} catch (std::out_of_range&) {
|
||||
m_requestSize = 0;
|
||||
}
|
||||
} else if (compareKeys(key, k_documentRoot)) {
|
||||
m_documentRoot = value + "/";
|
||||
}
|
||||
}
|
||||
|
||||
void FastCGITransport::onHeadersComplete() {
|
||||
m_serverObject = getHeader("SCRIPT_NAME");
|
||||
std::string queryString = getHeader("QUERY_STRING");
|
||||
std::string pathTranslated = getRawHeader("PATH_TRANSLATED");
|
||||
std::string documentRoot = getRawHeader("DOCUMENT_ROOT");
|
||||
// use PATH_TRANSLATED - DOCUMENT_ROOT if it is valid instead of SCRIPT_NAME
|
||||
// for mod_fastcgi support
|
||||
if (!pathTranslated.empty() && !documentRoot.empty() &&
|
||||
pathTranslated.find(documentRoot) == 0) {
|
||||
m_serverObject = pathTranslated.substr(documentRoot.length());
|
||||
} else {
|
||||
m_serverObject = getRawHeader("SCRIPT_NAME");
|
||||
}
|
||||
std::string queryString = getRawHeader("QUERY_STRING");
|
||||
if (!queryString.empty()) {
|
||||
m_serverObject += "?" + queryString;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,12 @@ public:
|
||||
|
||||
virtual const char *getUrl() override;
|
||||
virtual const char *getRemoteHost() override;
|
||||
virtual const char *getRemoteAddr() override;
|
||||
virtual uint16_t getRemotePort() override;
|
||||
virtual const std::string getDocumentRoot() override;
|
||||
virtual const char *getServerName() override;
|
||||
virtual const char *getServerAddr() override;
|
||||
virtual uint16_t getServerPort() override;
|
||||
|
||||
virtual const void *getPostData(int &size) override;
|
||||
virtual bool hasMorePostData() override;
|
||||
@@ -65,6 +70,7 @@ public:
|
||||
|
||||
virtual std::string getHeader(const char *name) override;
|
||||
virtual void getHeaders(HeaderMap &headers) override;
|
||||
virtual void getTransportParams(HeaderMap &serverParams) override;
|
||||
|
||||
virtual void addHeaderImpl(const char *name, const char *value) override;
|
||||
virtual void removeHeaderImpl(const char *name) override;
|
||||
@@ -87,6 +93,15 @@ private:
|
||||
typedef std::map<std::string, std::vector<std::string>> ResponseHeaders;
|
||||
|
||||
void handleHeader(const std::string& key, const std::string& value);
|
||||
std::string getRawHeader(const std::string& name);
|
||||
/*
|
||||
* HTTP_IF_MODIFIED_SINCE -> If-Unmodified-Since
|
||||
*/
|
||||
std::string unmangleHeader(const std::string& name);
|
||||
/*
|
||||
* If-Unmodified-Since -> HTTP_IF_MODIFIED_SINCE
|
||||
*/
|
||||
std::string mangleHeader(const std::string& name);
|
||||
|
||||
static bool compareKeys(const std::string& key,
|
||||
const std::string& other_key);
|
||||
@@ -97,10 +112,16 @@ private:
|
||||
|
||||
static const std::string k_requestURIKey;
|
||||
static const std::string k_remoteHostKey;
|
||||
static const std::string k_remoteAddrKey;
|
||||
static const std::string k_remotePortKey;
|
||||
static const std::string k_methodKey;
|
||||
static const std::string k_httpVersionKey;
|
||||
static const std::string k_contentLengthKey;
|
||||
static const std::string k_documentRoot;
|
||||
static const std::string k_serverNameKey;
|
||||
static const std::string k_serverPortKey;
|
||||
static const std::string k_serverAddrKey;
|
||||
static const std::string k_httpsKey;
|
||||
|
||||
FastCGIConnection* m_connection;
|
||||
int m_id;
|
||||
@@ -108,8 +129,13 @@ private:
|
||||
std::unique_ptr<folly::IOBuf> m_currBody;
|
||||
HeaderMap m_requestHeaders;
|
||||
std::string m_requestURI;
|
||||
std::string m_documentRoot;
|
||||
std::string m_remoteHost;
|
||||
std::string m_remoteAddr;
|
||||
uint16_t m_remotePort;
|
||||
std::string m_serverName;
|
||||
std::string m_serverAddr;
|
||||
uint16_t m_serverPort;
|
||||
Method m_method;
|
||||
std::string m_extendedMethod;
|
||||
std::string m_httpVersion;
|
||||
|
||||
@@ -323,24 +323,9 @@ bool HttpProtocol::PrepareCookieVariable(Variant& cookie,
|
||||
}
|
||||
|
||||
void HttpProtocol::CopyHeaderVariables(Variant& server,
|
||||
const HeaderMap& headers,
|
||||
bool normalize) {
|
||||
const HeaderMap& headers) {
|
||||
static std::atomic<int> badRequests(-1);
|
||||
|
||||
if (!normalize) {
|
||||
for (HeaderMap::const_iterator iter = headers.begin();
|
||||
iter != headers.end();
|
||||
++iter) {
|
||||
const vector<string> &values = iter->second;
|
||||
for (unsigned int i = 0; i < values.size(); i++) {
|
||||
String key = string_replace(f_strtoupper(iter->first), s_dash,
|
||||
s_underscore);
|
||||
server.set(key, String(values[i]));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> badHeaders;
|
||||
for (auto const& header : headers) {
|
||||
auto const& key = header.first;
|
||||
@@ -392,12 +377,35 @@ void HttpProtocol::CopyHeaderVariables(Variant& server,
|
||||
}
|
||||
}
|
||||
|
||||
void HttpProtocol::CopyTransportParams(Variant& server,
|
||||
Transport *transport) {
|
||||
HeaderMap transportParams;
|
||||
// Get additional server params from the transport if it has any. In the case
|
||||
// of fastcgi this is basically a full header list from apache/nginx.
|
||||
transport->getTransportParams(transportParams);
|
||||
for (auto const& header : transportParams) {
|
||||
auto const& key = header.first;
|
||||
auto const& values = header.second;
|
||||
auto normalizedKey = string_replace(f_strtoupper(key), s_dash,
|
||||
s_underscore);
|
||||
|
||||
// Be careful here to not overwrite any _SERVER variable
|
||||
// that has already been set elsewhere and make sure it has a value.
|
||||
if (!values.empty() && !server.asArrRef().exists(normalizedKey)) {
|
||||
// When a header has multiple values, we always take the last one.
|
||||
server.set(normalizedKey, String(values.back()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HttpProtocol::CopyServerInfo(Variant& server,
|
||||
Transport *transport,
|
||||
const VirtualHost *vhost) {
|
||||
|
||||
string hostHeader = transport->getHeader("Host");
|
||||
String hostName(vhost->serverName(hostHeader));
|
||||
String serverNameHeader(transport->getServerName());
|
||||
|
||||
if (hostHeader.empty()) {
|
||||
server.set(s_HTTP_HOST, hostName);
|
||||
@@ -405,19 +413,26 @@ void HttpProtocol::CopyServerInfo(Variant& server,
|
||||
} else {
|
||||
StackTraceNoHeap::AddExtraLogging("Server", hostHeader.c_str());
|
||||
}
|
||||
if (hostName.empty() || RuntimeOption::ForceServerNameToHeader) {
|
||||
|
||||
// Use the header from the transport if it is available
|
||||
if (!serverNameHeader.empty()) {
|
||||
hostName = serverNameHeader;
|
||||
} else if (hostName.empty() || RuntimeOption::ForceServerNameToHeader) {
|
||||
hostName = hostHeader;
|
||||
// _SERVER['SERVER_NAME'] shouldn't contain the port number
|
||||
int colonPos = hostName.find(':');
|
||||
if (colonPos != String::npos) {
|
||||
hostName = hostName.substr(0, colonPos);
|
||||
}
|
||||
}
|
||||
|
||||
// _SERVER['SERVER_NAME'] shouldn't contain the port number
|
||||
int colonPos = hostName.find(':');
|
||||
if (colonPos != String::npos) {
|
||||
hostName = hostName.substr(0, colonPos);
|
||||
}
|
||||
|
||||
StackTraceNoHeap::AddExtraLogging("Server_SERVER_NAME", hostName.data());
|
||||
|
||||
server.set(s_GATEWAY_INTERFACE, s_CGI_1_1);
|
||||
server.set(s_SERVER_ADDR, String(RuntimeOption::ServerPrimaryIP));
|
||||
server.set(s_SERVER_ADDR, transport->getServerAddr());
|
||||
server.set(s_SERVER_NAME, hostName);
|
||||
server.set(s_SERVER_PORT, RuntimeOption::ServerPort);
|
||||
server.set(s_SERVER_PORT, transport->getServerPort());
|
||||
server.set(s_SERVER_SOFTWARE, s_HPHP);
|
||||
server.set(s_SERVER_PROTOCOL, "HTTP/" + transport->getHTTPVersion());
|
||||
server.set(s_SERVER_ADMIN, empty_string);
|
||||
@@ -426,8 +441,17 @@ void HttpProtocol::CopyServerInfo(Variant& server,
|
||||
|
||||
void HttpProtocol::CopyRemoteInfo(Variant& server,
|
||||
Transport *transport) {
|
||||
server.set(s_REMOTE_ADDR, String(transport->getRemoteHost(), CopyString));
|
||||
server.set(s_REMOTE_HOST, empty_string); // I don't think we need to nslookup
|
||||
String remoteAddr(transport->getRemoteAddr(), CopyString);
|
||||
String remoteHost(transport->getRemoteHost(), CopyString);
|
||||
|
||||
if(remoteAddr.empty()) {
|
||||
remoteAddr = remoteHost;
|
||||
}
|
||||
|
||||
server.set(s_REMOTE_ADDR, remoteAddr);
|
||||
if(!remoteHost.empty()) {
|
||||
server.set(s_REMOTE_HOST, remoteHost);
|
||||
}
|
||||
server.set(s_REMOTE_PORT, transport->getRemotePort());
|
||||
}
|
||||
|
||||
@@ -515,15 +539,13 @@ void HttpProtocol::CopyPathInfo(Variant& server,
|
||||
server.set(s_PHP_SELF, r.resolvedURL() + r.origPathInfo());
|
||||
}
|
||||
|
||||
String documentRoot;
|
||||
if (RuntimeOption::ServerType != "fastcgi") {
|
||||
String documentRoot = transport->getDocumentRoot();
|
||||
if (documentRoot.empty()) {
|
||||
// Right now this is just RuntimeOption::SourceRoot but mwilliams wants to
|
||||
// fix it so it is settable, so I'll leave this for now
|
||||
documentRoot = vhost->getDocumentRoot();
|
||||
server.set(s_DOCUMENT_ROOT, documentRoot);
|
||||
} else if (server.asCArrRef().exists(s_DOCUMENT_ROOT)) {
|
||||
CHECK(server[s_DOCUMENT_ROOT].isString());
|
||||
documentRoot = server[s_DOCUMENT_ROOT].toCStrRef();
|
||||
}
|
||||
|
||||
server.set(s_DOCUMENT_ROOT, documentRoot);
|
||||
server.set(s_SCRIPT_FILENAME, r.absolutePath());
|
||||
|
||||
if (r.pathInfo().empty()) {
|
||||
@@ -590,14 +612,10 @@ void HttpProtocol::PrepareServerVariable(Variant& server,
|
||||
// "may" exclude them; this is not what APE does, but it's harmless.
|
||||
HeaderMap headers;
|
||||
transport->getHeaders(headers);
|
||||
if (RuntimeOption::ServerType != "fastcgi") {
|
||||
CopyHeaderVariables(server, headers, true);
|
||||
CopyServerInfo(server, transport, vhost);
|
||||
CopyRemoteInfo(server, transport);
|
||||
CopyAuthInfo(server, transport);
|
||||
} else {
|
||||
CopyHeaderVariables(server, headers, false);
|
||||
}
|
||||
CopyHeaderVariables(server, headers);
|
||||
CopyServerInfo(server, transport, vhost);
|
||||
CopyRemoteInfo(server, transport);
|
||||
CopyAuthInfo(server, transport);
|
||||
|
||||
CopyPathInfo(server, transport, r, vhost);
|
||||
|
||||
@@ -622,6 +640,8 @@ void HttpProtocol::PrepareServerVariable(Variant& server,
|
||||
iter != vServerVars.end(); ++iter) {
|
||||
server.set(String(iter->first), String(iter->second));
|
||||
}
|
||||
// Do this last as to not overwrite any existing server variables.
|
||||
CopyTransportParams(server, transport);
|
||||
sri.setServerVariables(server);
|
||||
|
||||
const char *threadType = transport->getThreadTypeName();
|
||||
|
||||
@@ -59,8 +59,9 @@ public:
|
||||
const SourceRootInfo &sri,
|
||||
const VirtualHost *vhost);
|
||||
static void CopyHeaderVariables(Variant& server,
|
||||
const HeaderMap& headers,
|
||||
bool normalize);
|
||||
const HeaderMap& headers);
|
||||
static void CopyTransportParams(Variant& server,
|
||||
Transport *transport);
|
||||
static void CopyServerInfo(Variant& server,
|
||||
Transport *transport,
|
||||
const VirtualHost *vhost);
|
||||
|
||||
@@ -154,8 +154,7 @@ void HttpRequestHandler::handleRequest(Transport *transport) {
|
||||
vhost->getName().c_str());
|
||||
|
||||
// resolve source root
|
||||
string host = transport->getHeader("Host");
|
||||
SourceRootInfo sourceRootInfo(host.c_str());
|
||||
SourceRootInfo sourceRootInfo(transport);
|
||||
|
||||
if (sourceRootInfo.error()) {
|
||||
sourceRootInfo.handleError(transport);
|
||||
|
||||
@@ -157,8 +157,7 @@ void RPCRequestHandler::handleRequest(Transport *transport) {
|
||||
};
|
||||
|
||||
// resolve source root
|
||||
string host = transport->getHeader("Host");
|
||||
SourceRootInfo sourceRootInfo(host.c_str());
|
||||
SourceRootInfo sourceRootInfo(transport);
|
||||
|
||||
// set thread type
|
||||
switch (m_serverInfo->getType()) {
|
||||
|
||||
@@ -30,12 +30,22 @@ namespace HPHP {
|
||||
IMPLEMENT_THREAD_LOCAL_NO_CHECK(string, SourceRootInfo::s_path);
|
||||
IMPLEMENT_THREAD_LOCAL_NO_CHECK(string, SourceRootInfo::s_phproot);
|
||||
|
||||
SourceRootInfo::SourceRootInfo(const char *host)
|
||||
SourceRootInfo::SourceRootInfo(Transport* transport)
|
||||
: m_sandboxCond(RuntimeOption::SandboxMode ? SandboxCondition::On :
|
||||
SandboxCondition::Off) {
|
||||
s_path.destroy();
|
||||
s_phproot.destroy();
|
||||
|
||||
auto documentRoot = transport->getDocumentRoot();
|
||||
if (!documentRoot.empty()) {
|
||||
// The transport take precedence over the config file
|
||||
m_path = documentRoot;
|
||||
*s_path.getCheck() = documentRoot;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sandboxOn()) return;
|
||||
auto host = transport->getHeader("Host");
|
||||
Variant matches;
|
||||
Variant r = preg_match(String(RuntimeOption::SandboxPattern.c_str(),
|
||||
RuntimeOption::SandboxPattern.size(),
|
||||
@@ -242,8 +252,7 @@ string SourceRootInfo::parseSandboxServerVariable(const string &format) const {
|
||||
}
|
||||
|
||||
string SourceRootInfo::path() const {
|
||||
if (sandboxOn()) {
|
||||
// Should return RuntimeOption::SourceRoot if m_data is empty?
|
||||
if (sandboxOn() || !m_path.empty()) {
|
||||
return string(m_path.data(), m_path.size());
|
||||
} else {
|
||||
return RuntimeOption::SourceRoot;
|
||||
|
||||
@@ -27,7 +27,7 @@ class Transport;
|
||||
|
||||
class SourceRootInfo {
|
||||
public:
|
||||
explicit SourceRootInfo(const char *host);
|
||||
explicit SourceRootInfo(Transport* transport);
|
||||
SourceRootInfo(const std::string &user, const std::string &sandbox);
|
||||
void createFromUserConfig();
|
||||
void createFromCommonRoot(const String &sandboxName);
|
||||
|
||||
@@ -84,10 +84,10 @@ public:
|
||||
virtual ~Transport();
|
||||
|
||||
void onRequestStart(const timespec &queueTime);
|
||||
const timespec &getQueueTime() const { return m_queueTime;}
|
||||
const timespec &getWallTime() const { return m_wallTime;}
|
||||
const timespec &getCpuTime() const { return m_cpuTime;}
|
||||
const int64_t &getInstructions() const { return m_instructions;}
|
||||
const timespec &getQueueTime() const { return m_queueTime; }
|
||||
const timespec &getWallTime() const { return m_wallTime; }
|
||||
const timespec &getCpuTime() const { return m_cpuTime; }
|
||||
const int64_t &getInstructions() const { return m_instructions; }
|
||||
const int64_t &getSleepTime() const { return m_sleepTime; }
|
||||
void incSleepTime(unsigned int seconds) { m_sleepTime += seconds; }
|
||||
const int64_t &getuSleepTime() const { return m_usleepTime; }
|
||||
@@ -109,6 +109,23 @@ public:
|
||||
virtual const char *getUrl() = 0;
|
||||
virtual const char *getRemoteHost() = 0;
|
||||
virtual uint16_t getRemotePort() = 0;
|
||||
// The transport can override REMOTE_ADDR if it has one
|
||||
virtual const char *getRemoteAddr() { return ""; }
|
||||
// The transport can override the virtualhosts' docroot
|
||||
virtual const std::string getDocumentRoot() { return ""; }
|
||||
|
||||
/**
|
||||
* Server Headers
|
||||
*/
|
||||
virtual const char *getServerName() {
|
||||
return "";
|
||||
};
|
||||
virtual const char *getServerAddr() {
|
||||
return RuntimeOption::ServerPrimaryIP.c_str();
|
||||
};
|
||||
virtual uint16_t getServerPort() {
|
||||
return RuntimeOption::ServerPort;
|
||||
};
|
||||
|
||||
/**
|
||||
* POST request's data.
|
||||
@@ -139,6 +156,7 @@ public:
|
||||
*/
|
||||
virtual std::string getHeader(const char *name) = 0;
|
||||
virtual void getHeaders(HeaderMap &headers) = 0;
|
||||
virtual void getTransportParams(HeaderMap &serverParams) {};
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1817,11 +1817,11 @@
|
||||
},
|
||||
{
|
||||
"name": "HPHP_VERSION",
|
||||
"value": "2.3.0"
|
||||
"value": "2.3.3"
|
||||
},
|
||||
{
|
||||
"name": "HHVM_VERSION",
|
||||
"value": "2.3.0"
|
||||
"value": "2.3.3"
|
||||
},
|
||||
{
|
||||
"name": "HTML_ENTITIES",
|
||||
|
||||
@@ -1053,6 +1053,9 @@ class Phar extends RecursiveDirectoryIterator
|
||||
if (strpos($filename, $prefix) === 0) {
|
||||
$entry = substr($filename, strlen($prefix) + 1);
|
||||
if (strlen($entry) > 0) {
|
||||
if ($filename[strlen($prefix)] != '/') {
|
||||
continue;
|
||||
}
|
||||
$next_slash = strpos($entry, '/');
|
||||
if ($next_slash !== false) {
|
||||
$entry = substr($entry, 0, $next_slash);
|
||||
|
||||
@@ -388,7 +388,7 @@ bool TestFastCGIServer::VerifyExchange(const TestMessageExchange& mx,
|
||||
printf("Error while receiving payload\n");
|
||||
result = false;
|
||||
} else if (recv_len.toInt32() < len) {
|
||||
printf("Too little date received\n");
|
||||
printf("Too little data received\n");
|
||||
result = false;
|
||||
} else {
|
||||
CHECK(recv_len.toInt32() == len);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
class Hello {
|
||||
public function sayHello($name) {
|
||||
return "Hello $name!";
|
||||
}
|
||||
}
|
||||
|
||||
class StackTest extends PHPUnit_Framework_TestCase {
|
||||
public function testTrueIsActuallyTrue() {
|
||||
$stub = $this->getMock('Hello');
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
$argv[] = __DIR__."/phpunit_mock.inc";
|
||||
$arvc += 1;
|
||||
$_SERVER['argv'] = $argv;
|
||||
$_SERVER['argc'] = $argc;
|
||||
|
||||
include __DIR__."/phpunit.phar";
|
||||
@@ -0,0 +1,7 @@
|
||||
PHPUnit 3.7.22 by Sebastian Bergmann.
|
||||
|
||||
.
|
||||
|
||||
Time: %d second%A, Memory: %s
|
||||
|
||||
OK (1 test, 1 assertion)
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
$xml = <<<EOT
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE test [<!ENTITY xxe SYSTEM "XXE_URI">]>
|
||||
<foo>&xxe;</foo>
|
||||
EOT;
|
||||
|
||||
$xml = str_replace('XXE_URI', __DIR__ . '/libxml_disable_entity_loader_payload.txt', $xml);
|
||||
|
||||
function parseXML($xml) {
|
||||
$doc = new DOMDocument();
|
||||
$doc->resolveExternals = true;
|
||||
$doc->substituteEntities = true;
|
||||
$doc->validateOnParse = false;
|
||||
$doc->loadXML($xml, 0);
|
||||
return $doc->saveXML();
|
||||
}
|
||||
|
||||
var_dump(strpos(parseXML($xml), 'SECRET_DATA') !== false);
|
||||
var_dump(libxml_disable_entity_loader(true));
|
||||
var_dump(strpos(parseXML($xml), 'SECRET_DATA') === false);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
@@ -0,0 +1,7 @@
|
||||
bool(true)
|
||||
bool(false)
|
||||
I/O warning : failed to load external entity "%s"
|
||||
HipHop Warning: %s
|
||||
HipHop Warning: %s
|
||||
bool(true)
|
||||
Done
|
||||
@@ -0,0 +1 @@
|
||||
<?php if (!extension_loaded('simplexml') || !extension_loaded('dom') || defined('PHP_WINDOWS_VERSION_MAJOR')) die('skip'); ?>
|
||||
@@ -0,0 +1 @@
|
||||
SECRET_DATA
|
||||
+1
-1
@@ -1 +1 @@
|
||||
HHVM_VERSION(2.3.0)
|
||||
HHVM_VERSION(2.3.3)
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário