bool RPCRequestHandler::executePHPFunction(Transport *transport, SourceRootInfo &sourceRootInfo) { ExecutionContext *context = hphp_context_init(); // 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; if (m_serverInfo) { warmupDoc = m_serverInfo->getWarmupDoc(); reqInitFunc = m_serverInfo->getReqInitFunc(); } if (warmupDoc.empty()) { warmupDoc = RuntimeOption::WarmupDocument; reqInitFunc = RuntimeOption::RequestInitFunction; } warmupDoc = canonicalize_path(warmupDoc, "", 0); warmupDoc = get_source_filename(warmupDoc.c_str()); bool ret = hphp_invoke(context, rpcFunc, true, params, ref(funcRet), warmupDoc, reqInitFunc, error, errorMsg); if (ret) { String response; switch (output) { case 0: response = f_json_encode(funcRet); break; case 1: response = context->obGetContents(); break; case 2: response = f_json_encode(CREATE_MAP2("output", context->obGetContents(), "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); hphp_context_exit(context, true, false); return !error; }