20 Commits

Autor SHA1 Mensagem Data
ptarjan e8141ac49d Revert "Update folly"
This reverts commit 4cf537888b.
2014-01-14 14:50:32 -08:00
Sara Golemon 4cf537888b Update folly
Conflicts:
	CMake/HPHPSetup.cmake
2014-01-14 14:35:31 -08:00
ptarjan 2752b5bbb1 bump version to 2.3.3 2014-01-14 14:21:24 -08:00
Paul Tarjan cc6cbf3852 fix fastcgi segfaults a better way
I think this is what julk originally wanted. He has a `m_keepConn` boolean that is set by `ConnectionFlags::KEEP_CONN` and if that is false, he calls this callback in both the error and the success case.

This doesn't segfault when the connection is abruptly closed by the requestor.

Closes #1522

Reviewed By: @scannell

Differential Revision: D1124995
2014-01-14 14:17:54 -08:00
Antony Puckey 1a4fac8a25 add getRemoteAddr to transport which defaults to empty string. add getRemoteAddr to fastcgi transport to return the proper header. fi no remoteAddr set it to the remoteHost ( libevent ) only set REMOTE_HOST if there is something in it as per php-src
Differential Revision: D1126545
2014-01-14 14:14:39 -08:00
Antony Puckey ae6443500e Set HTTPS header appropriately in fastcgi
Check passed header values for HTTPS.

IIS sets this header to "off" so check for that and empty value before
using transport->setSSL().

Only change to lower case if the value is not empty for performance.

Closes #1546

Reviewed By: @ptarjan

Differential Revision: D1125440

Pulled By: @scannell
2014-01-13 18:37:49 -08:00
Antony Puckey e42452e4f2 Allow transport to override SERVER_ headers
Uses the following headers from the transport (for fastcgi)
instead of the local config if they exist:

SERVER_NAME
SERVER_ADDR
SERVER_PORT

Closes #1445

Reviewed By: @ptarjan

Differential Revision: D1114969

Pulled By: @scannell
2014-01-13 18:37:16 -08:00
Antony Puckey 1dd7e6165e Populate fastcgi (transport-specific) headers
Added new function CopyServerParams in http-protocol which uses the new transport function getServerParams that adds any transport specific SERVER variables ie: FASTCGI_PARAMS to the _SERVER array

Closes #1437
Closes #1511

Reviewed By: @sgolemon

Differential Revision: D1120838

Pulled By: @scannell
2014-01-13 18:36:41 -08:00
Paul Tarjan 01ef59346e Support mod_fastcgi
when using mod_fastcgi SCRIPT_NAME is the Action instead of the actual document you want
this commit uses PATH_TRANSLATED - DOCUMENT_ROOT

tested with:
apache+mod_fastcgi
apache+mod_proxy_fcgi
nginx with no PATH_TRANSLATED header
nginx with this as PATH_TRANSLATED: fastcgi_param PATH_TRANSLATED $document_root$fastcgi_script_name;

Reviewed By: @scannell

Differential Revision: D1114124
2014-01-13 18:36:22 -08:00
Paul Tarjan 9380a44469 delete FastCGIConnection object
This was a leak appearing in @apuckey's valgrind dump. @simpkins said the object should delete itself since either the success or error callbacks will for sure be called for each connection.

Closes #1252

Reviewed By: @scannell

Differential Revision: D1115399
2014-01-13 13:32:58 -08:00
Paul Tarjan 3f859af167 stop emitting regex debugging message
This message is breaking composer installing things with enormous regexes. I tried to change the default error level but @markw65 didn't like that and we need to do something, so I guess lets not emit this if EHHS is off.

Closes #1347

Reviewed By: @markw65

Differential Revision: D1118365
2014-01-13 13:27:01 -08:00
Scott MacVicar 55ecfbdbb6 Fix libxml_disable_entity_loader()
This wasn't calling requestInit and setting the libxml handler no null.
So the first time an error came along it would reset the handler from
no-op to reading again.

This is a much better fix, we set our custom handler in requestInit and
when libxml_disable_entity_loader we store that state as a member bool
ensuring requestInit is always called to set our own handler.

If the handler isn't inserted then the behavious is as before. The only
time this could go pear shaped is say we wanted to make the default be
off. In that case we'd need a global requestInit that is always called
since there are libxml references everywhere.

Reviewed By: @jdelong

Differential Revision: D1116686
2014-01-13 13:20:25 -08:00
ptarjan f951cb8d88 bump version to 2.3.2 2013-12-23 12:51:42 -08:00
Paul Tarjan 2a3225ecd0 fix DOCUMENT_ROOT for fastcgi
We shouldn't have spcialized code in here for fastcgi, and it didn't even work.

Reviewed By: @markw65

Differential Revision: D1109072
2013-12-21 15:36:40 -08:00
Paul Tarjan 65cfdabb76 Allow fastcgi to use the DOCUMENT_ROOT from the web server
: We shouldn't use the current directory or the configured `SourceRoot` since the webserver could have many virtual hosts and always will send us a DOCUMENT_ROOT header.

The only scary part of the change is checking for `sourceRoot` instead of `getDocumentRoot` but I think it is right.

Differential Revision: D1108017
2013-12-21 15:36:27 -08:00
Paul Tarjan 25a26c6bd7 Fix Phar's directory detection
I screwed up the prefix check. Something that is a directory has to have a `/` between the prefix and the file, not just any character.

Closes #1334

Reviewed By: @JoelMarcey

Differential Revision: D1104260
2013-12-20 18:11:39 -08:00
Daniel Sloof 3effbfe5d1 Close pdo connection after request ends
When a request finishes and the PDO connection is not closed in
userland, we need to explictly close it to prevent excessive amount of
connections (and eventually causing MySQL to reject them).

This can obviously be solved in userland by closing the connection in a
register_shutdown_function, but we need to be consistent with PHP.

Closes #1345

Reviewed By: @markw65

Differential Revision: D1098327

Pulled By: @scannell
2013-12-20 11:44:02 -08:00
ptarjan 3a708166b8 bump version to 2.3.1 2013-12-17 13:48:38 -08:00
Paul Tarjan 3c17422435 Make FastCGI less magical for headers
When I changed `getHeaders()` to be the same for fastcgi as all the other transports I didn't notice julk has put in special rules to deal with the fact they weren't the same. Rip that out.

This makes `$_SERVER` contain `HTTP_HOST` instead of just `HOST`.

Reviewed By: @sgolemon

Differential Revision: D1100779
2013-12-17 13:48:08 -08:00
Paul Tarjan d3f23f393f fastcgi headers need unmangling
Headers as mangled in the FastCGI protocol, but the `getHeader()` method on `Transport` assumed the header was the original value.

Closes #1359

Reviewed By: @alexmalyshev

Differential Revision: D1098954
2013-12-17 13:48:07 -08:00
31 arquivos alterados com 369 adições e 94 exclusões
+3
Ver Arquivo
@@ -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;
-11
Ver Arquivo
@@ -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);
+4 -4
Ver Arquivo
@@ -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());
+15 -10
Ver Arquivo
@@ -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;
}
///////////////////////////////////////////////////////////////////////////////
+6
Ver Arquivo
@@ -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());
+2 -1
Ver Arquivo
@@ -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
+9
Ver Arquivo
@@ -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;
}
+1
Ver Arquivo
@@ -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);
+3 -1
Ver Arquivo
@@ -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) {
+1 -1
Ver Arquivo
@@ -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();
}
+128 -7
Ver Arquivo
@@ -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;
+61 -41
Ver Arquivo
@@ -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();
+3 -2
Ver Arquivo
@@ -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);
+1 -2
Ver Arquivo
@@ -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);
+1 -2
Ver Arquivo
@@ -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()) {
+12 -3
Ver Arquivo
@@ -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;
+1 -1
Ver Arquivo
@@ -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);
+22 -4
Ver Arquivo
@@ -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) {};
/**
+2 -2
Ver Arquivo
@@ -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",
+3
Ver Arquivo
@@ -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);
+1 -1
Ver Arquivo
@@ -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);
+14
Ver Arquivo
@@ -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);
}
}
+8
Ver Arquivo
@@ -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
Ver Arquivo
@@ -1 +1 @@
HHVM_VERSION(2.3.0)
HHVM_VERSION(2.3.3)