void DummySandbox::run() {
  while (!m_stopped) {
    try {
      char *argv[] = {"", NULL};
      execute_command_line_begin(1, argv, 0);

      DECLARE_THREAD_INFO;
      FRAME_INJECTION_FLAGS(empty_string, _, FrameInjection::PseudoMain);

      DSandboxInfo sandbox = m_proxy->getSandbox();
      string msg;
      if (m_inited) {
        SystemGlobals *g = (SystemGlobals *)get_global_variables();
        SourceRootInfo sri(sandbox.m_user, sandbox.m_name);
        if (sandbox.m_path.empty()) {
          sandbox.m_path = sri.path();
        }
        if (!sri.sandboxOn()) {
          msg = "Invalid sandbox was specified. "
            "PHP files may not be loaded properly.\n";
          // force HPHP_SANDBOX_ID to be set, so we can still talk to client
          g->GV(_SERVER).set("HPHP_SANDBOX_ID", sandbox.id());
        } else {
          sri.setServerVariables(g->GV(_SERVER));
        }

        std::string doc = getStartupDoc(sandbox);
        bool error; string errorMsg;
        bool ret = hphp_invoke(g_context.get(), doc, false, null_array, null,
                               "", "", "", error, errorMsg);
        if (!ret || error) {
          msg += "Unable to pre-load " + doc;
          if (!errorMsg.empty()) {
            msg += ": " + errorMsg;
          }
        }
      }

      m_inited = true;
      Debugger::RegisterSandbox(sandbox);
      Debugger::InterruptSessionStarted(NULL, msg.c_str());

      // Blocking until Ctrl-C is issued by end user and DebuggerProxy cannot
      // find a real sandbox thread to handle it.
      {
        Lock lock(this);
        while (!m_stopped && m_signum != CmdSignal::SignalBreak) {
          wait(1);
        }
        m_signum = CmdSignal::SignalNone;
      }
    } catch (const DebuggerException &e) {}
    execute_command_line_end(0, false, NULL);
  }
}
bool RPCRequestHandler::executePHPFunction(Transport *transport,
                                           SourceRootInfo &sourceRootInfo) {
  // reset timeout counter
  ThreadInfo::s_threadInfo->m_reqInjectionData.started = time(0);

  string rpcFunc = transport->getCommand();
  {
    ServerStatsHelper ssh("input");
    RequestURI reqURI(rpcFunc);
    HttpProtocol::PrepareSystemVariables(transport, reqURI, sourceRootInfo);
  }

  bool isFile = rpcFunc.rfind('.') != string::npos;
  string rpcFile;
  bool error = false;

  Array params;
  string sparams = transport->getParam("params");
  if (!sparams.empty()) {
    Variant jparams = f_json_decode(String(sparams), true);
    if (jparams.isArray()) {
      params = jparams.toArray();
    } else {
      error = true;
    }
  } else {
    vector<string> sparams;
    transport->getArrayParam("p", sparams);
    if (!sparams.empty()) {
      for (unsigned int i = 0; i < sparams.size(); i++) {
        Variant jparams = f_json_decode(String(sparams[i]), true);
        if (same(jparams, false)) {
          error = true;
          break;
        }
        params.append(jparams);
      }
    } else {
      // single string parameter, used by xbox to avoid any en/decoding
      int size;
      const void *data = transport->getPostData(size);
      if (data && size) {
        params.append(String((char*)data, size, AttachLiteral));
      }
    }
  }

  if (transport->getIntParam("reset") == 1) {
    m_reset = true;
  }
  int output = transport->getIntParam("output");

  int code;
  if (!error) {
    Variant funcRet;
    string errorMsg = "Internal Server Error";
    string warmupDoc, reqInitFunc, reqInitDoc;
    if (m_serverInfo) {
      warmupDoc = m_serverInfo->getWarmupDoc();
      reqInitFunc = m_serverInfo->getReqInitFunc();
      reqInitDoc = m_serverInfo->getReqInitDoc();
    }
    if (!warmupDoc.empty()) warmupDoc = canonicalize_path(warmupDoc, "", 0);
    if (!warmupDoc.empty()) {
      warmupDoc = getSourceFilename(warmupDoc, sourceRootInfo);
    }

    if (!reqInitDoc.empty()) reqInitDoc = canonicalize_path(reqInitDoc, "", 0);
    if (!reqInitDoc.empty()) {
        reqInitDoc = getSourceFilename(reqInitDoc, sourceRootInfo);
    }

    bool runOnce = false;
    bool ret = true;
    if (isFile) {
      rpcFile = rpcFunc;
      rpcFunc.clear();
    } else {
      rpcFile = transport->getParam("include");
      if (rpcFile.empty()) {
        rpcFile = transport->getParam("include_once");
        runOnce = true;
      }
    }
    if (!rpcFile.empty()) {
      // invoking a file through rpc
      bool forbidden = false;
      if (!RuntimeOption::ForbiddenFileExtensions.empty()) {
        const char *ext = rpcFile.c_str() + rpcFile.rfind('.') + 1;
        if (RuntimeOption::ForbiddenFileExtensions.find(ext) !=
            RuntimeOption::ForbiddenFileExtensions.end()) {
          forbidden = true;
        }
      }
      if (!forbidden) {
        rpcFile = canonicalize_path(rpcFile, "", 0);
        rpcFile = getSourceFilename(rpcFile, sourceRootInfo);
        ret = hphp_invoke(m_context, rpcFile, false, Array(), null,
                          warmupDoc, reqInitFunc, reqInitDoc,
                          error, errorMsg, runOnce);
      }
      // no need to do the initialization for a second time
      warmupDoc.clear();
      reqInitFunc.clear();
      reqInitDoc.clear();
    }
    if (ret && !rpcFunc.empty()) {
      ret = hphp_invoke(m_context, rpcFunc, true, params, ref(funcRet),
                        warmupDoc, reqInitFunc, reqInitDoc,
                        error, errorMsg);
    }
    if (ret) {
      String response;
      switch (output) {
        case 0: response = f_json_encode(funcRet);   break;
        case 1: response = m_context->obDetachContents(); break;
        case 2:
          response =
            f_json_encode(CREATE_MAP2("output", m_context->obDetachContents(),
                                      "return", f_json_encode(funcRet)));
          break;
      }
      code = 200;
      transport->sendRaw((void*)response.data(), response.size());
    } else if (error) {
      code = 500;
      transport->sendString(errorMsg, 500);
      m_reset = true;
    } else {
      code = 404;
      transport->sendString("Not Found", 404);
    }
  } else {
    code = 400;
    transport->sendString("Bad Request", 400);
  }
  params.reset();
  sourceRootInfo.clear();

  transport->onSendEnd();
  ServerStats::LogPage(isFile ? rpcFile : rpcFunc, code);

  m_context->onShutdownPostSend();
  m_context->obClean(); // in case postsend/cleanup output something
  m_context->restoreSession();
  return !error;
}
示例#3
0
void DummySandbox::run() {
  TRACE(2, "DummySandbox::run\n");
  RequestInfo *ti = RequestInfo::s_requestInfo.getNoCheck();
  while (!m_stopped) {
    try {
      CLISession hphpSession;

      DSandboxInfo sandbox = m_proxy->getSandbox();
      std::string msg;
      if (sandbox.valid()) {
        SourceRootInfo sri(sandbox.m_user, sandbox.m_name);
        if (sandbox.m_path.empty()) {
          sandbox.m_path = sri.path();
        }
        if (!sri.sandboxOn()) {
          msg = "Invalid sandbox was specified. "
            "PHP files may not be loaded properly.\n";
        } else {
          auto server = php_global_exchange(s__SERVER, init_null());
          forceToArray(server);
          Array arr = server.toArrRef();
          server.unset();
          php_global_set(s__SERVER, sri.setServerVariables(std::move(arr)));
        }
        Debugger::RegisterSandbox(sandbox);
        g_context->setSandboxId(sandbox.id());

        std::string doc = getStartupDoc(sandbox);
        if (!doc.empty()) {
          char cwd[PATH_MAX];
          getcwd(cwd, sizeof(cwd));
          Logger::Info("Start loading startup doc '%s', pwd = '%s'",
                       doc.c_str(), cwd);
          bool error; std::string errorMsg;
          bool ret = hphp_invoke(g_context.getNoCheck(), doc, false, null_array,
                                 uninit_null(), "", "", error, errorMsg, true,
                                 false, true, RuntimeOption::EvalPreludePath);
          if (!ret || error) {
            msg += "Unable to pre-load " + doc;
            if (!errorMsg.empty()) {
              msg += ": " + errorMsg;
            }
          }
          Logger::Info("Startup doc " + doc + " loaded");
        }
      } else {
        g_context->setSandboxId(m_proxy->getDummyInfo().id());
      }

      if (!DebuggerHook::attach<HphpdHook>(ti)) {
        const char* fail = "Could not attach hphpd to request: another debugger"
                           " is already attached.";
        Logger::Error("%s", fail);
        Debugger::InterruptSessionStarted(nullptr, fail);
        throw DebuggerClientAttachFailureException();
      }
      {
        DebuggerDummyEnv dde;
        // This is really the entire point of having the dummy sandbox. This
        // fires the initial session started interrupt to the client after
        // it first attaches.
        Debugger::InterruptSessionStarted(nullptr, msg.c_str());
      }

      // Blocking until Ctrl-C is issued by end user and DebuggerProxy cannot
      // find a real sandbox thread to handle it.
      {
        Lock lock(this);
        while (!m_stopped && m_signum != CmdSignal::SignalBreak) {
          wait(1);
        }
        if (m_stopped) {
          // stopped by worker thread
          break;
        }
        m_signum = CmdSignal::SignalNone;
      }
    } catch (const DebuggerClientExitException& e) {
      // stopped by the dummy sandbox thread itself
      break;
    } catch (const DebuggerException& e) {
    }
  }
}
void DummySandbox::run() {
  TRACE(2, "DummySandbox::run\n");
  ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
  Debugger::RegisterThread();
  while (!m_stopped) {
    try {
      CLISession hphpSession;

      DSandboxInfo sandbox = m_proxy->getSandbox();
      string msg;
      if (sandbox.valid()) {
        GlobalVariables *g = get_global_variables();
        SourceRootInfo sri(sandbox.m_user, sandbox.m_name);
        if (sandbox.m_path.empty()) {
          sandbox.m_path = sri.path();
        }
        if (!sri.sandboxOn()) {
          msg = "Invalid sandbox was specified. "
            "PHP files may not be loaded properly.\n";
        } else {
          sri.setServerVariables(g->getRef(s__SERVER));
        }
        Debugger::RegisterSandbox(sandbox);
        g_context->setSandboxId(sandbox.id());

        std::string doc = getStartupDoc(sandbox);
        if (!doc.empty()) {
          char cwd[PATH_MAX];
          getcwd(cwd, sizeof(cwd));
          Logger::Info("Start loading startup doc '%s', pwd = '%s'",
                       doc.c_str(), cwd);
          bool error; string errorMsg;
          bool ret = hphp_invoke(g_context.getNoCheck(), doc, false, null_array,
                                 uninit_null(), "", "", error, errorMsg, true,
                                 false, true);
          if (!ret || error) {
            msg += "Unable to pre-load " + doc;
            if (!errorMsg.empty()) {
              msg += ": " + errorMsg;
            }
          }
          Logger::Info("Startup doc " + doc + " loaded");
        }
      } else {
        g_context->setSandboxId(m_proxy->getDummyInfo().id());
      }

      ti->m_reqInjectionData.setDebugger(true);
      {
        DebuggerDummyEnv dde;
        // This is really the entire point of having the dummy sandbox. This
        // fires the initial session started interrupt to the client after
        // it first attaches.
        Debugger::InterruptSessionStarted(nullptr, msg.c_str());
      }

      // Blocking until Ctrl-C is issued by end user and DebuggerProxy cannot
      // find a real sandbox thread to handle it.
      {
        Lock lock(this);
        while (!m_stopped && m_signum != CmdSignal::SignalBreak) {
          wait(1);
        }
        if (m_stopped) {
          // stopped by worker thread
          break;
        }
        m_signum = CmdSignal::SignalNone;
      }
    } catch (const DebuggerClientExitException &e) {
      // stopped by the dummy sandbox thread itself
      break;
    } catch (const DebuggerException &e) {
    }
  }
}
bool HttpRequestHandler::executePHPRequest(Transport *transport,
                                           RequestURI &reqURI,
                                           SourceRootInfo &sourceRootInfo,
                                           bool cachableDynamicContent) {
  ExecutionContext *context = hphp_context_init();
  if (RuntimeOption::ImplicitFlush) {
    context->obSetImplicitFlush(true);
  }
  if (RuntimeOption::EnableOutputBuffering) {
    if (RuntimeOption::OutputHandler.empty()) {
      context->obStart();
    } else {
      context->obStart(String(RuntimeOption::OutputHandler));
    }
  }
  context->setTransport(transport);

  string file = reqURI.absolutePath().c_str();
  {
    ServerStatsHelper ssh("input");
    HttpProtocol::PrepareSystemVariables(transport, reqURI, sourceRootInfo);

    if (RuntimeOption::EnableDebugger) {
      Eval::DSandboxInfo sInfo = sourceRootInfo.getSandboxInfo();
      Eval::Debugger::RegisterSandbox(sInfo);
      context->setSandboxId(sInfo.id());
    }
    reqURI.clear();
    sourceRootInfo.clear();
  }

  int code;
  bool ret = true;

  if (RuntimeOption::EnableDebugger) {
    Eval::Debugger::InterruptRequestStarted(transport->getUrl());
  }

  bool error = false;
  std::string errorMsg = "Internal Server Error";
  ret = hphp_invoke(context, file, false, Array(), uninit_null(),
                    RuntimeOption::RequestInitFunction,
                    RuntimeOption::RequestInitDocument,
                    error, errorMsg);

  if (ret) {
    String content = context->obDetachContents();
    if (cachableDynamicContent && !content.empty()) {
      assert(transport->getUrl());
      string key = file + transport->getUrl();
      DynamicContentCache::TheCache.store(key, content.data(),
                                          content.size());
    }
    transport->sendRaw((void*)content.data(), content.size());
    code = transport->getResponseCode();
  } else if (error) {
    code = 500;

    string errorPage = context->getErrorPage().data();
    if (errorPage.empty()) {
      errorPage = RuntimeOption::ErrorDocument500;
    }
    if (!errorPage.empty()) {
      context->obProtect(false);
      context->obEndAll();
      context->obStart();
      context->obProtect(true);
      ret = hphp_invoke(context, errorPage, false, Array(), uninit_null(),
                        RuntimeOption::RequestInitFunction,
                        RuntimeOption::RequestInitDocument,
                        error, errorMsg);
      if (ret) {
        String content = context->obDetachContents();
        transport->sendRaw((void*)content.data(), content.size());
        code = transport->getResponseCode();
      } else {
        Logger::Error("Unable to invoke error page %s", errorPage.c_str());
        errorPage.clear(); // so we fall back to 500 return
      }
    }
    if (errorPage.empty()) {
      if (RuntimeOption::ServerErrorMessage) {
        transport->sendString(errorMsg, 500, false, false, "hphp_invoke");
      } else {
        transport->sendString(RuntimeOption::FatalErrorMessage,
                              500, false, false, "hphp_invoke");
      }
    }
  } else {
    code = 404;
    transport->sendString("Not Found", 404);
  }

  if (RuntimeOption::EnableDebugger) {
    Eval::Debugger::InterruptRequestEnded(transport->getUrl());
  }

  transport->onSendEnd();
  hphp_context_exit(context, true, true, transport->getUrl());
  ServerStats::LogPage(file, code);
  return ret;
}
bool RPCRequestHandler::executePHPFunction(Transport *transport,
                                           SourceRootInfo &sourceRootInfo,
                                           ReturnEncodeType returnEncodeType) {
  string rpcFunc = transport->getCommand();
  {
    ServerStatsHelper ssh("input");
    RequestURI reqURI(rpcFunc);
    HttpProtocol::PrepareSystemVariables(transport, reqURI, sourceRootInfo);

    GlobalVariables *g = get_global_variables();
    g->getRef(s__ENV).set(s_HPHP_RPC, 1);
  }

  bool isFile = rpcFunc.rfind('.') != string::npos;
  string rpcFile;
  bool error = false;

  Array params;
  string sparams = transport->getParam("params");
  if (!sparams.empty()) {
    Variant jparams = f_json_decode(String(sparams), true);
    if (jparams.isArray()) {
      params = jparams.toArray();
    } else {
      error = true;
    }
  } else {
    vector<string> sparams;
    transport->getArrayParam("p", sparams);
    if (!sparams.empty()) {
      for (unsigned int i = 0; i < sparams.size(); i++) {
        Variant jparams = f_json_decode(String(sparams[i]), true);
        if (same(jparams, false)) {
          error = true;
          break;
        }
        params.append(jparams);
      }
    } else {
      // single string parameter, used by xbox to avoid any en/decoding
      int size;
      const void *data = transport->getPostData(size);
      if (data && size) {
        params.append(String((char*)data, size, CopyString));
      }
    }
  }

  if (transport->getIntParam("reset") == 1) {
    m_reset = true;
  }
  int output = transport->getIntParam("output");

  int code;
  if (!error) {
    Variant funcRet;
    string errorMsg = "Internal Server Error";
    string reqInitFunc, reqInitDoc;
    reqInitDoc = transport->getHeader("ReqInitDoc");
    if (reqInitDoc.empty() && m_serverInfo) {
      reqInitFunc = m_serverInfo->getReqInitFunc();
      reqInitDoc = m_serverInfo->getReqInitDoc();
    }

    if (!reqInitDoc.empty()) {
      reqInitDoc = (std::string)canonicalize_path(reqInitDoc, "", 0);
    }
    if (!reqInitDoc.empty()) {
      reqInitDoc = getSourceFilename(reqInitDoc, sourceRootInfo);
    }

    bool runOnce = false;
    bool ret = true;
    if (isFile) {
      rpcFile = rpcFunc;
      rpcFunc.clear();
    } else {
      rpcFile = transport->getParam("include");
      if (rpcFile.empty()) {
        rpcFile = transport->getParam("include_once");
        runOnce = true;
      }
    }
    if (!rpcFile.empty()) {
      // invoking a file through rpc
      bool forbidden = false;
      if (!RuntimeOption::ForbiddenFileExtensions.empty()) {
        const char *ext = rpcFile.c_str() + rpcFile.rfind('.') + 1;
        if (RuntimeOption::ForbiddenFileExtensions.find(ext) !=
            RuntimeOption::ForbiddenFileExtensions.end()) {
          forbidden = true;
        }
      }
      if (!forbidden) {
        rpcFile = (std::string) canonicalize_path(rpcFile, "", 0);
        rpcFile = getSourceFilename(rpcFile, sourceRootInfo);
        ret = hphp_invoke(m_context, rpcFile, false, Array(), uninit_null(),
                          reqInitFunc, reqInitDoc, error, errorMsg, runOnce);
      }
      // no need to do the initialization for a second time
      reqInitFunc.clear();
      reqInitDoc.clear();
    }
    if (ret && !rpcFunc.empty()) {
      ret = hphp_invoke(m_context, rpcFunc, true, params, ref(funcRet),
                        reqInitFunc, reqInitDoc, error, errorMsg);
    }
    if (ret) {
      bool serializeFailed = false;
      String response;
      switch (output) {
        case 0: {
          assert(returnEncodeType == ReturnEncodeType::Json ||
                 returnEncodeType == ReturnEncodeType::Serialize);
          try {
            response = (returnEncodeType == ReturnEncodeType::Json) ?
                       f_json_encode(funcRet) :
                       f_serialize(funcRet);
          } catch (...) {
            serializeFailed = true;
          }
          break;
        }
        case 1: response = m_context->obDetachContents(); break;
        case 2:
          response =
            f_json_encode(
              make_map_array(s_output, m_context->obDetachContents(),
                                      s_return, f_json_encode(funcRet)));
          break;
        case 3: response = f_serialize(funcRet); break;
      }
      if (serializeFailed) {
        code = 500;
        transport->sendString(
            "Serialization of the return value failed", 500);
        m_reset = true;
      } else {
        transport->sendRaw((void*)response.data(), response.size());
        code = transport->getResponseCode();
      }
    } else if (error) {
      code = 500;
      transport->sendString(errorMsg, 500);
      m_reset = true;
    } else {
      code = 404;
      transport->sendString("Not Found", 404);
    }
  } else {
    code = 400;
    transport->sendString("Bad Request", 400);
  }

  params.reset();
  sourceRootInfo.clear();

  transport->onSendEnd();
  ServerStats::LogPage(isFile ? rpcFile : rpcFunc, code);

  m_context->onShutdownPostSend();
  m_context->obClean(); // in case postsend/cleanup output something
  m_context->restoreSession();
  return !error;
}
示例#7
0
void DummySandbox::run() {
  ThreadInfo *ti = ThreadInfo::s_threadInfo.getNoCheck();
  Debugger::RegisterThread();
  ti->m_reqInjectionData.dummySandbox = true;
  while (!m_stopped) {
    try {
      CLISession hphpSession;
      FUNCTION_INJECTION_FS("_", FrameInjection::PseudoMain);

      DSandboxInfo sandbox = m_proxy->getSandbox();
      string msg;
      if (sandbox.valid()) {
        SystemGlobals *g = (SystemGlobals *)get_global_variables();
        SourceRootInfo sri(sandbox.m_user, sandbox.m_name);
        if (sandbox.m_path.empty()) {
          sandbox.m_path = sri.path();
        }
        if (!sri.sandboxOn()) {
          msg = "Invalid sandbox was specified. "
            "PHP files may not be loaded properly.\n";
        } else {
          sri.setServerVariables(g->GV(_SERVER));
        }
        Debugger::RegisterSandbox(sandbox);
        g_context->setSandboxId(sandbox.id());

        Logger::Info("Start loading startup doc");
        std::string doc = getStartupDoc(sandbox);
        bool error; string errorMsg;
        bool ret = hphp_invoke(g_context.getNoCheck(), doc, false, null_array,
                               null, "", "", error, errorMsg, true, false,
                               true);
        if (!ret || error) {
          msg += "Unable to pre-load " + doc;
          if (!errorMsg.empty()) {
            msg += ": " + errorMsg;
          }
        }
        Logger::Info("Startup doc " + doc + " loaded");
      } else {
        g_context->setSandboxId(m_proxy->getDummyInfo().id());
      }

      ti->m_reqInjectionData.debugger = true;
      {
        DebuggerDummyEnv dde;
        Debugger::InterruptSessionStarted(NULL, msg.c_str());
      }

      // Blocking until Ctrl-C is issued by end user and DebuggerProxy cannot
      // find a real sandbox thread to handle it.
      {
        Lock lock(this);
        while (!m_stopped && m_signum != CmdSignal::SignalBreak) {
          wait(1);
        }
        if (m_stopped) {
          // stopped by worker thread
          break;
        }
        m_signum = CmdSignal::SignalNone;
      }
    } catch (const DebuggerClientExitException &e) {
      // stopped by the dummy sandbox thread itself
      break;
    } catch (const DebuggerException &e) {
    }
  }
}
bool RPCRequestHandler::executePHPFunction(Transport *transport,
                                           SourceRootInfo &sourceRootInfo) {
  // reset timeout counter
  ThreadInfo::s_threadInfo->m_reqInjectionData.started = time(0);

  std::string rpcFunc = transport->getCommand();
  {
    ServerStatsHelper ssh("input");
    RequestURI reqURI(rpcFunc);
    HttpProtocol::PrepareSystemVariables(transport, reqURI, sourceRootInfo);
    sourceRootInfo.clear();
  }

  bool error = false;

  Array params;
  std::string sparams = transport->getParam("params");
  if (!sparams.empty()) {
    Variant jparams = f_json_decode(String(sparams), true);
    if (jparams.isArray()) {
      params = jparams.toArray();
    } else {
      error = true;
    }
  } else {
    vector<string> sparams;
    transport->getArrayParam("p", sparams);
    if (!sparams.empty()) {
      for (unsigned int i = 0; i < sparams.size(); i++) {
        Variant jparams = f_json_decode(String(sparams[i]), true);
        if (same(jparams, false)) {
          error = true;
          break;
        }
        params.append(jparams);
      }
    } else {
      // single string parameter, used by xbox to avoid any en/decoding
      int size;
      const void *data = transport->getPostData(size);
      if (data && size) {
        params.append(String((char*)data, size, AttachLiteral));
      }
    }
  }

  if (transport->getIntParam("reset") == 1) {
    m_reset = true;
  }
  int output = transport->getIntParam("output");

  int code;
  if (!error) {
    Variant funcRet;
    std::string errorMsg = "Internal Server Error";
    string warmupDoc, reqInitFunc, reqInitDoc;
    if (m_serverInfo) {
      warmupDoc = m_serverInfo->getWarmupDoc();
      reqInitFunc = m_serverInfo->getReqInitFunc();
      reqInitDoc = m_serverInfo->getReqInitDoc();
    }
    if (!warmupDoc.empty()) warmupDoc = canonicalize_path(warmupDoc, "", 0);
    if (!warmupDoc.empty()) warmupDoc = get_source_filename(warmupDoc.c_str());
    bool ret = hphp_invoke(m_context, rpcFunc, true, params, ref(funcRet),
                           warmupDoc, reqInitFunc, reqInitDoc,
                           error, errorMsg);
    if (ret) {
      String response;
      switch (output) {
        case 0: response = f_json_encode(funcRet);   break;
        case 1: response = m_context->obDetachContents(); break;
        case 2:
          response =
            f_json_encode(CREATE_MAP2("output", m_context->obDetachContents(),
                                      "return", f_json_encode(funcRet)));
          break;
      }
      code = 200;
      transport->sendRaw((void*)response.data(), response.size());
    } else if (error) {
      code = 500;
      transport->sendString(errorMsg, 500);
      m_reset = true;
    } else {
      code = 404;
      transport->sendString("Not Found", 404);
    }
  } else {
    code = 400;
    transport->sendString("Bad Request", 400);
  }
  params.reset();

  transport->onSendEnd();
  ServerStats::LogPage(rpcFunc, code);

  m_context->onShutdownPostSend();
  m_context->restoreSession();
  return !error;
}
bool HttpRequestHandler::executePHPRequest(Transport *transport,
                                           RequestURI &reqURI,
                                           SourceRootInfo &sourceRootInfo,
                                           bool cachableDynamicContent) {
  ExecutionContext *context = hphp_context_init();
  context->setTransport(transport);

  string file = reqURI.absolutePath().c_str();
  {
    ServerStatsHelper ssh("input");
    HttpProtocol::PrepareSystemVariables(transport, reqURI, sourceRootInfo);
    reqURI.clear();
    sourceRootInfo.clear();
  }

  bool error = false;
  std::string errorMsg = "Internal Server Error";
  bool ret = hphp_invoke(context, file, false, Array(), null,
                         RuntimeOption::WarmupDocument,
                         RuntimeOption::RequestInitFunction,
                         error, errorMsg);

  int code;
  if (ret) {
    std::string content = context->getContents();
    if (cachableDynamicContent && !content.empty()) {
      ASSERT(transport->getUrl());
      string key = file + transport->getUrl();
      DynamicContentCache::TheCache.store(key, content.data(), content.size());
    }
    code = 200;
    transport->sendRaw((void*)content.data(), content.size());
  } else if (error) {
    code = 500;

    string errorPage = context->getErrorPage();
    if (errorPage.empty()) {
      errorPage = RuntimeOption::ErrorDocument500;
    }
    if (!errorPage.empty()) {
      context->obEndAll();
      context->obStart();
      context->obProtect(true);
      ret = hphp_invoke(context, errorPage, false, Array(), null,
                        RuntimeOption::WarmupDocument,
                        RuntimeOption::RequestInitFunction,
                        error, errorMsg);
      if (ret) {
        std::string content = context->getContents();
        transport->sendRaw((void*)content.data(), content.size());
      } else {
        errorPage.clear(); // so we fall back to 500 return
      }
    }
    if (errorPage.empty()) {
      if (RuntimeOption::ServerErrorMessage) {
        transport->sendString(errorMsg, 500);
      } else {
        transport->sendString(RuntimeOption::FatalErrorMessage, 500);
      }
    }
  } else {
    code = 404;
    transport->sendString("Not Found", 404);
  }
  transport->onSendEnd();
  ServerStats::LogPage(file, code);
  hphp_context_exit(context, true);
  return ret;
}
示例#10
0
bool HttpRequestHandler::executePHPRequest(Transport *transport,
                                           RequestURI &reqURI,
                                           SourceRootInfo &sourceRootInfo,
                                           bool cachableDynamicContent) {
  ExecutionContext *context = hphp_context_init();
  if (RuntimeOption::ImplicitFlush) {
    context->obSetImplicitFlush(true);
  }
  if (RuntimeOption::EnableOutputBuffering) {
    if (RuntimeOption::OutputHandler.empty()) {
      context->obStart();
    } else {
      context->obStart(String(RuntimeOption::OutputHandler));
    }
  }
  context->setTransport(transport);

  string file = reqURI.absolutePath().c_str();
  {
    ServerStatsHelper ssh("input");
    HttpProtocol::PrepareSystemVariables(transport, reqURI, sourceRootInfo);
    reqURI.clear();
    sourceRootInfo.clear();
  }

  int code;
  bool ret = true;
  if (!RuntimeOption::ForbiddenFileExtensions.empty()) {
    size_t pos = file.rfind('.');
    if (pos != string::npos) {
      const char *ext = file.c_str() + pos + 1;
      if (RuntimeOption::ForbiddenFileExtensions.find(ext) !=
          RuntimeOption::ForbiddenFileExtensions.end()) {
        code = 403;
        transport->sendString("Forbidden", 403);
        ret = false;
      }
    }
  }

  if (ret) {
    if (RuntimeOption::EnableDebugger) {
      Eval::Debugger::InterruptRequestStarted(transport->getUrl());
    }

    bool error = false;
    std::string errorMsg = "Internal Server Error";
    ret = hphp_invoke(context, file, false, Array(), null,
                      RuntimeOption::WarmupDocument,
                      RuntimeOption::RequestInitFunction,
                      RuntimeOption::RequestInitDocument,
                      error, errorMsg);

    if (ret) {
      String content = context->obDetachContents();
      if (cachableDynamicContent && !content.empty()) {
        ASSERT(transport->getUrl());
        string key = file + transport->getUrl();
        DynamicContentCache::TheCache.store(key, content.data(),
                                            content.size());
      }
      code = 200;
      transport->sendRaw((void*)content.data(), content.size(), code);
    } else if (error) {
      code = 500;

      string errorPage = context->getErrorPage().data();
      if (errorPage.empty()) {
        errorPage = RuntimeOption::ErrorDocument500;
      }
      if (!errorPage.empty()) {
        context->obProtect(false);
        context->obEndAll();
        context->obStart();
        context->obProtect(true);
        ret = hphp_invoke(context, errorPage, false, Array(), null,
                          RuntimeOption::WarmupDocument,
                          RuntimeOption::RequestInitFunction,
                          RuntimeOption::RequestInitDocument,
                          error, errorMsg);
        if (ret) {
          String content = context->obDetachContents();
          transport->sendRaw((void*)content.data(), content.size());
        } else {
          errorPage.clear(); // so we fall back to 500 return
        }
      }
      if (errorPage.empty()) {
        if (RuntimeOption::ServerErrorMessage) {
          transport->sendString(errorMsg, 500, false, false, "hphp_invoke");
        } else {
          transport->sendString(RuntimeOption::FatalErrorMessage,
                                500, false, false, "hphp_invoke");
        }
      }
    } else {
      code = 404;
      transport->sendString("Not Found", 404);
    }

    if (RuntimeOption::EnableDebugger) {
      Eval::Debugger::InterruptRequestEnded(transport->getUrl());
    }
  }

  transport->onSendEnd();
  ServerStats::LogPage(file, code);
  hphp_context_exit(context, true, true, transport->getUrl());
  return ret;
}