8 Commits

Autor SHA1 Mensagem Data
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
23 arquivos alterados com 157 adições e 64 exclusões
-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());
+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);
@@ -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,8 @@
#include "hphp/util/timer.h"
#include "folly/MoveWrapper.h"
#include <boost/algorithm/string/predicate.hpp>
using folly::IOBuf;
using folly::IOBufQueue;
using folly::io::Cursor;
@@ -47,6 +50,10 @@ 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();
}
@@ -127,7 +134,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,7 +184,12 @@ 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::addHeaderImpl(const char *name, const char *value) {
@@ -225,6 +278,7 @@ 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";
void FastCGITransport::onHeader(std::unique_ptr<folly::IOBuf> key_chain,
std::unique_ptr<folly::IOBuf> value_chain) {
@@ -288,12 +342,14 @@ 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");
m_serverObject = getRawHeader("SCRIPT_NAME");
std::string queryString = getRawHeader("QUERY_STRING");
if (!queryString.empty()) {
m_serverObject += "?" + queryString;
}
@@ -49,6 +49,7 @@ public:
virtual const char *getUrl() override;
virtual const char *getRemoteHost() override;
virtual uint16_t getRemotePort() override;
virtual const std::string getDocumentRoot() override;
virtual const void *getPostData(int &size) override;
virtual bool hasMorePostData() override;
@@ -87,6 +88,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);
@@ -101,6 +111,7 @@ private:
static const std::string k_methodKey;
static const std::string k_httpVersionKey;
static const std::string k_contentLengthKey;
static const std::string k_documentRoot;
FastCGIConnection* m_connection;
int m_id;
@@ -108,6 +119,7 @@ private:
std::unique_ptr<folly::IOBuf> m_currBody;
HeaderMap m_requestHeaders;
std::string m_requestURI;
std::string m_documentRoot;
std::string m_remoteHost;
uint16_t m_remotePort;
Method m_method;
+10 -31
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;
@@ -515,15 +500,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 +573,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);
+1 -2
Ver Arquivo
@@ -59,8 +59,7 @@ public:
const SourceRootInfo &sri,
const VirtualHost *vhost);
static void CopyHeaderVariables(Variant& server,
const HeaderMap& headers,
bool normalize);
const HeaderMap& headers);
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);
+2
Ver Arquivo
@@ -109,6 +109,8 @@ public:
virtual const char *getUrl() = 0;
virtual const char *getRemoteHost() = 0;
virtual uint16_t getRemotePort() = 0;
// The transport can override the virtualhosts' docroot
virtual const std::string getDocumentRoot() { return ""; }
/**
* POST request's data.
+2 -2
Ver Arquivo
@@ -1817,11 +1817,11 @@
},
{
"name": "HPHP_VERSION",
"value": "2.3.0"
"value": "2.3.2"
},
{
"name": "HHVM_VERSION",
"value": "2.3.0"
"value": "2.3.2"
},
{
"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)
+1 -1
Ver Arquivo
@@ -1 +1 @@
HHVM_VERSION(2.3.0)
HHVM_VERSION(2.3.2)