Arquivos
hhvm/hphp/runtime/base/server/source_root_info.cpp
T
Edwin Smith ada1c7b2f9 Eliminate most Variant litstr methods
Doesn't eliminate the Variant(litstr) constructor, or the
same/equals/more/less/etc helpers called from comparisons.h;
those will come in a followon diff.
2013-05-15 13:05:10 -07:00

267 linhas
8.2 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/base/runtime_option.h"
#include "hphp/runtime/base/server/source_root_info.h"
#include "hphp/runtime/base/preg.h"
#include "hphp/runtime/base/server/http_request_handler.h"
#include "hphp/runtime/base/server/transport.h"
#include "hphp/runtime/eval/debugger/debugger.h"
using std::map;
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)
: m_sandboxCond(RuntimeOption::SandboxMode ? SandboxOn : SandboxOff) {
s_path.destroy();
s_phproot.destroy();
if (!sandboxOn()) return;
Variant matches;
Variant r = preg_match(String(RuntimeOption::SandboxPattern.c_str(),
RuntimeOption::SandboxPattern.size(),
AttachLiteral), host, matches);
if (!r.same(1)) {
m_sandboxCond = SandboxOff;
return;
}
if (RuntimeOption::SandboxFromCommonRoot) {
String sandboxName = matches.rvalAt(1).toString();
createFromCommonRoot(sandboxName);
} else {
Array pair = StringUtil::Explode(matches.rvalAt(1), "-", 2);
m_user = pair.rvalAt(0).toString();
bool defaultSb = pair.size() == 1;
if (defaultSb) {
m_sandbox = "default";
} else {
m_sandbox = pair.rvalAt(1).toString();
}
createFromUserConfig();
}
*s_path.getCheck() = m_path.c_str();
}
SourceRootInfo::SourceRootInfo(const std::string &user,
const std::string &sandbox)
: m_sandboxCond(RuntimeOption::SandboxMode ? SandboxOn : SandboxOff) {
s_path.destroy();
s_phproot.destroy();
if (!sandboxOn()) return;
m_user = user;
m_sandbox = sandbox;
createFromUserConfig();
*s_path.getCheck() = m_path.c_str();
}
void SourceRootInfo::createFromCommonRoot(const String &sandboxName) {
m_user = "";
m_sandbox = string(sandboxName);
String sandboxesRoot = String(RuntimeOption::SandboxDirectoriesRoot);
String logsRoot = String(RuntimeOption::SandboxLogsRoot);
m_path = sandboxesRoot + "/" + sandboxName;
if (m_path.charAt(m_path.size() - 1) != '/') {
m_path += "/";
}
String logPath = logsRoot + "/" + sandboxName + "_error.log";
String accessLogPath = logsRoot + "/" + sandboxName + "_access.log";
if (!Logger::SetThreadLog(logPath.c_str())) {
Logger::Warning("Sandbox error log %s could not be opened",
logPath.c_str());
}
if (!HttpRequestHandler::GetAccessLog().setThreadLog(accessLogPath.c_str())) {
Logger::Warning("Sandbox access log %s could not be opened",
accessLogPath.c_str());
}
}
void SourceRootInfo::createFromUserConfig() {
String homePath = String(RuntimeOption::SandboxHome) + "/" + m_user + "/";
{
struct stat hstat;
if (stat(homePath.c_str(), &hstat) != 0) {
if (!RuntimeOption::SandboxFallback.empty()) {
homePath = String(RuntimeOption::SandboxFallback) + "/" + m_user + "/";
if (stat(homePath.c_str(), &hstat) != 0) {
m_sandboxCond = SandboxOff;
return;
}
}
}
}
string confpath = string(homePath.c_str()) +
RuntimeOption::SandboxConfFile;
Hdf config, serverVars;
String sp, lp, alp, userOverride;
try {
config.open(confpath);
userOverride = config["user_override"].get();
Hdf sboxConf = config[m_sandbox.c_str()];
if (sboxConf.exists()) {
sp = sboxConf["path"].get();
lp = sboxConf["log"].get();
alp = sboxConf["accesslog"].get();
serverVars = sboxConf["ServerVars"];
}
} catch (HdfException &e) {
Logger::Error("%s ignored: %s", confpath.c_str(),
e.getMessage().c_str());
}
if (serverVars.exists()) {
for (Hdf hdf = serverVars.firstChild(); hdf.exists(); hdf = hdf.next()) {
m_serverVars.set(String(hdf.getName()), String(hdf.getString()));
}
}
if (!userOverride.empty()) {
m_user = std::move(userOverride);
}
if (m_sandbox == "default") {
if (sp.isNull()) {
sp = "www/";
}
}
if (sp.isNull()) {
m_sandboxCond = SandboxError;
return;
}
if (sp.charAt(0) == '/') {
m_path = std::move(sp);
} else {
m_path = homePath + sp;
}
if (m_path.charAt(m_path.size() - 1) != '/') {
m_path += "/";
}
if (!lp.isNull()) {
if (lp.charAt(0) != '/') {
lp = homePath + lp;
}
if (!Logger::SetThreadLog(lp.c_str())) {
Logger::Warning("Sandbox error log %s could not be opened",
lp.c_str());
}
}
if (!alp.isNull()) {
if (alp.charAt(0) != '/') {
alp = homePath + alp;
}
if (!HttpRequestHandler::GetAccessLog().setThreadLog(alp.c_str())) {
Logger::Warning("Sandbox access log %s could not be opened",
alp.c_str());
}
}
}
SourceRootInfo::~SourceRootInfo() {
if (sandboxOn()) {
Logger::ClearThreadLog();
HttpRequestHandler::GetAccessLog().clearThreadLog();
}
}
void SourceRootInfo::handleError(Transport *t) {
t->sendString("Sandbox not found", 200);
}
///////////////////////////////////////////////////////////////////////////////
void SourceRootInfo::setServerVariables(Variant &server) const {
if (!sandboxOn()) return;
for (map<string, string>::const_iterator it =
RuntimeOption::SandboxServerVariables.begin();
it != RuntimeOption::SandboxServerVariables.end(); ++it) {
server.set(String(it->first),
String(parseSandboxServerVariable(it->second)));
}
if (!m_serverVars.empty()) {
server += m_serverVars;
}
}
Eval::DSandboxInfo SourceRootInfo::getSandboxInfo() const {
Eval::DSandboxInfo sandbox;
sandbox.m_user = m_user.data();
sandbox.m_name = m_sandbox.data();
sandbox.m_path = m_path.data();
return sandbox;
}
string SourceRootInfo::parseSandboxServerVariable(const string &format) const {
std::ostringstream res;
bool control = false;
for (uint i = 0; i < format.size(); i++) {
char c = format[i];
if (control) {
switch (c) {
case 'p':
{
// skip trailing /
const char *data = m_path.data();
int n = m_path.size() - 1;
assert(data[n] == '/');
res.write(data, n);
break;
}
case 's': res << m_sandbox.c_str(); break;
case 'u': res << m_user.c_str(); break;
default: res << c; break;
}
control = false;
} else if (c == '%') {
control = true;
} else {
res << c;
}
}
return res.str();
}
string SourceRootInfo::path() const {
if (sandboxOn()) {
// Should return RuntimeOption::SourceRoot if m_data is empty?
return string(m_path.data(), m_path.size());
} else {
return RuntimeOption::SourceRoot;
}
}
static const StaticString s_PHP_ROOT("PHP_ROOT");
string& SourceRootInfo::initPhpRoot() {
SystemGlobals *g = (SystemGlobals*)get_global_variables();
Variant &server = g->GV(_SERVER);
Variant v = server.rvalAt(s_PHP_ROOT);
if (v.isString()) {
*s_phproot.getCheck() = string(v.asCStrRef().data()) + string("/");
} else {
// Our best guess at the source root.
*s_phproot.getCheck() = GetCurrentSourceRoot();
}
return *s_phproot.getCheck();
}
///////////////////////////////////////////////////////////////////////////////
}