string& SourceRootInfo::initPhpRoot() { GlobalVariables *g = get_global_variables(); CVarRef server = g->get(s_SERVER); CVarRef 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(); }
bool UrlFile::open(CStrRef url, CStrRef mode) { const char* modestr = mode.c_str(); if (strchr(modestr, '+') || strchr(modestr, 'a') || strchr(modestr, 'w')) { std::string msg = "cannot open a url stream for write/append operation: "; msg += url.c_str(); m_error = msg; return false; } HttpClient http(m_timeout, m_maxRedirect); m_response.reset(); HeaderMap *pHeaders = nullptr; HeaderMap requestHeaders; if (!m_headers.empty()) { pHeaders = &requestHeaders; for (ArrayIter iter(m_headers); iter; ++iter) { requestHeaders[string(iter.first().toString().data())]. push_back(iter.second().toString().data()); } } int code; vector<String> responseHeaders; if (m_get) { code = http.get(url.c_str(), m_response, pHeaders, &responseHeaders); } else { code = http.post(url.c_str(), m_postData.data(), m_postData.size(), m_response, pHeaders, &responseHeaders); } GlobalVariables *g = get_global_variables(); Variant &r = g->getRef(s_http_response_header); r = Array::Create(); for (unsigned int i = 0; i < responseHeaders.size(); i++) { r.append(responseHeaders[i]); } m_responseHeaders = r; if (code == 200) { m_name = (std::string) url; m_data = const_cast<char*>(m_response.data()); m_len = m_response.size(); return true; } else { m_error = http.getLastError().c_str(); return false; } }
Array f_getopt(CStrRef options, CVarRef longopts /* = null_variant */) { opt_struct *opts, *orig_opts; int len = parse_opts(options.data(), options.size(), &opts); if (!longopts.isNull()) { Array arropts = longopts.toArray(); int count = arropts.size(); /* the first <len> slots are filled by the one short ops * we now extend our array and jump to the new added structs */ opts = (opt_struct *)realloc(opts, sizeof(opt_struct) * (len + count + 1)); orig_opts = opts; opts += len; memset(opts, 0, count * sizeof(opt_struct)); for (ArrayIter iter(arropts); iter; ++iter) { String entry = iter.second().toString(); opts->need_param = 0; opts->opt_name = strdup(entry.data()); len = strlen(opts->opt_name); if ((len > 0) && (opts->opt_name[len - 1] == ':')) { opts->need_param++; opts->opt_name[len - 1] = '\0'; if ((len > 1) && (opts->opt_name[len - 2] == ':')) { opts->need_param++; opts->opt_name[len - 2] = '\0'; } } opts->opt_char = 0; opts++; } } else { opts = (opt_struct*) realloc(opts, sizeof(opt_struct) * (len + 1)); orig_opts = opts; opts += len; } /* php_getopt want to identify the last param */ opts->opt_char = '-'; opts->need_param = 0; opts->opt_name = NULL; static const StaticString s_argv("argv"); GlobalVariables *g = get_global_variables(); Array vargv = g->get(s_argv).toArray(); int argc = vargv.size(); char **argv = (char **)malloc((argc+1) * sizeof(char*)); vector<String> holders; int index = 0; for (ArrayIter iter(vargv); iter; ++iter) { String arg = iter.second().toString(); holders.push_back(arg); argv[index++] = (char*)arg.data(); } argv[index] = NULL; Array ret = Array::Create(); /* after our pointer arithmetic jump back to the first element */ opts = orig_opts; int o; char *php_optarg = NULL; int php_optind = 1; Variant val; int optchr = 0; int dash = 0; /* have already seen the - */ char opt[2] = { '\0' }; char *optname; int optname_len = 0; int php_optidx; while ((o = php_getopt(argc, argv, opts, &php_optarg, &php_optind, 0, 1, optchr, dash, php_optidx)) != -1) { /* Skip unknown arguments. */ if (o == '?') { continue; } /* Prepare the option character and the argument string. */ if (o == 0) { optname = opts[php_optidx].opt_name; } else { if (o == 1) { o = '-'; } opt[0] = o; optname = opt; } if (php_optarg != NULL) { /* keep the arg as binary, since the encoding is not known */ val = String(php_optarg, CopyString); } else { val = false; } /* Add this option / argument pair to the result hash. */ optname_len = strlen(optname); if (!(optname_len > 1 && optname[0] == '0') && is_numeric_string(optname, optname_len, NULL, NULL, 0) == KindOfInt64) { /* numeric string */ int optname_int = atoi(optname); if (ret.exists(optname_int)) { Variant &e = ret.lvalAt(optname_int); if (!e.isArray()) { ret.set(optname_int, CREATE_VECTOR2(e, val)); } else { e.append(val); } } else { ret.set(optname_int, val); } } else { /* other strings */ String key(optname, strlen(optname), CopyString); if (ret.exists(key)) { Variant &e = ret.lvalAt(key); if (!e.isArray()) { ret.set(key, CREATE_VECTOR2(e, val)); } else { e.append(val); } } else { ret.set(key, val); } } php_optarg = NULL; } free_longopts(orig_opts); free(orig_opts); free(argv); return ret; }
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 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; }
bool UrlFile::open(const String& input_url, const String& mode) { String url = input_url; const char* modestr = mode.c_str(); if (strchr(modestr, '+') || strchr(modestr, 'a') || strchr(modestr, 'w')) { std::string msg = "cannot open a url stream for write/append operation: "; msg += url.c_str(); m_error = msg; return false; } HttpClient http(m_timeout, m_maxRedirect); m_response.clear(); HeaderMap *pHeaders = nullptr; HeaderMap requestHeaders; if (!m_headers.empty()) { pHeaders = &requestHeaders; for (ArrayIter iter(m_headers); iter; ++iter) { requestHeaders[std::string(iter.first().toString().data())]. push_back(iter.second().toString().data()); } } Variant user = f_parse_url(url, k_PHP_URL_USER); if (user.isString()) { Variant pass = f_parse_url(url, k_PHP_URL_PASS); http.auth(user.toString().c_str(), pass.toString().c_str()); url = HHVM_FN(preg_replace)( s_remove_user_pass_pattern, s_remove_user_pass_replace, url, 1 ); } int code; std::vector<String> responseHeaders; if (m_get) { code = http.get(url.c_str(), m_response, pHeaders, &responseHeaders); } else { code = http.post(url.c_str(), m_postData.data(), m_postData.size(), m_response, pHeaders, &responseHeaders); } GlobalVariables *g = get_global_variables(); Variant &r = g->getRef(s_http_response_header); r = Array::Create(); for (unsigned int i = 0; i < responseHeaders.size(); i++) { r.append(responseHeaders[i]); } m_responseHeaders = r; if (code == 200) { m_name = (std::string) url; m_data = const_cast<char*>(m_response.data()); m_len = m_response.size(); return true; } else { m_error = http.getLastError().c_str(); return false; } }
void init_global_variables() { GlobalVariables *g = get_global_variables(); ThreadInfo::s_threadInfo->m_globals = g; g->initialize(); }
Variant &GlobalVariables::getImpl(CStrRef s) { GlobalVariables *g __attribute__((__unused__)) = this; int64 hash = s->hash(); switch (hash & 31) { case 1: HASH_RETURN_NAMSTR(0x50645ABB5EE07801LL, s_ss5ee07801, g->GV(_POST), 5); break; case 3: HASH_RETURN_NAMSTR(0x3760929554A51DA3LL, s_ss54a51da3, g->GV(_COOKIE), 7); HASH_RETURN_NAMSTR(0x6649184C41356B03LL, s_ss41356b03, g->GV(HTTP_RAW_POST_DATA), 18); break; case 9: HASH_RETURN_NAMSTR(0x0759FB4517508949LL, s_ss17508949, g->GV(_GET), 4); HASH_RETURN_NAMSTR(0x230E7AD147721D89LL, s_ss47721d89, g->GV(end), 3); break; case 10: HASH_RETURN_NAMSTR(0x15F2515C40B2980ALL, s_ss40b2980a, g->GV(elapsed_time), 12); break; case 14: HASH_RETURN_NAMSTR(0x14297F74B68B58EELL, s_ss4974a712, g->GV(_SERVER), 7); HASH_RETURN_NAMSTR(0x516FBD36FC674A0ELL, s_ss0398b5f2, g->GV(_FILES), 6); break; case 15: HASH_RETURN_NAMSTR(0x587FF01B02607E8FLL, s_ss02607e8f, g->GV(argv), 4); break; case 16: HASH_RETURN_NAMSTR(0x7320B4E3FF243290LL, s_ss00dbcd70, g->GV(_ENV), 4); break; case 17: HASH_RETURN_NAMSTR(0x29DFC3A6DC027BD1LL, s_ss23fd842f, g->GV(_SESSION), 8); break; case 25: HASH_RETURN_NAMSTR(0x532E5E517D32FCB9LL, s_ss7d32fcb9, g->GV(argc), 4); break; case 29: HASH_RETURN_NAMSTR(0x35F78B4D0532F99DLL, s_ss0532f99d, g->GV(begin), 5); break; case 31: HASH_RETURN_NAMSTR(0x1F878FB806A18D3FLL, s_ss06a18d3f, g->GV(_REQUEST), 8); HASH_RETURN_NAMSTR(0x6359C77BCA89599FLL, s_ss3576a661, g->GV(http_response_header), 20); break; default: break; } return LVariableTable::getImpl(s); }