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); auto ctx = this->getStreamContext(); if (ctx) { http.setStreamContextOptions(ctx->getOptions()); } m_response.clear(); if (!m_proxyHost.empty()) { http.proxy(m_proxyHost, m_proxyPort, m_proxyUsername, m_proxyPassword); } 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 ).toString(); } int code; std::vector<String> responseHeaders; if (m_get) { code = http.get(url.c_str(), m_response, pHeaders, &responseHeaders); } else { code = http.request(m_method, url.c_str(), m_postData.data(), m_postData.size(), m_response, pHeaders, &responseHeaders); } m_responseHeaders.reset(); for (unsigned int i = 0; i < responseHeaders.size(); i++) { m_responseHeaders.append(responseHeaders[i]); } VMRegAnchor vra; ActRec* fp = vmfp(); while (fp->skipFrame()) { fp = g_context->getPrevVMState(fp); } auto id = fp->func()->lookupVarId(s_http_response_header.get()); if (id != kInvalidId) { auto tvTo = frame_local(fp, id); Variant varFrom(m_responseHeaders); const auto tvFrom(varFrom.asTypedValue()); if (tvTo->m_type == KindOfRef) { tvTo = tvTo->m_data.pref->tv(); } tvDup(*tvFrom, *tvTo); } else if ((fp->func()->attrs() & AttrMayUseVV) && fp->hasVarEnv()) { fp->getVarEnv()->set(s_http_response_header.get(), Variant(m_responseHeaders).asTypedValue()); } /* * If code == 0, Curl failed to connect; per PHP5, ignore_errors just means * to not worry if we get an http resonse code that isn't between 200 and 400, * but we shouldn't ignore other errors. * all status codes in the 2xx range are defined by the specification as * successful; * all status codes in the 3xx range are for redirection, and so also should * never fail. */ if ((code >= 200 && code < 400) || (m_ignoreErrors && code != 0)) { setName(url.toCppString()); m_data = const_cast<char*>(m_response.data()); m_len = m_response.size(); return true; } else { m_error = http.getLastError().c_str(); return false; } }