Add sub-controls for Hack array compat runtime checks
[hiphop-php.git] / hphp / runtime / base / http-stream-wrapper.cpp
blob11e6cf71a168bf51b6cd5ee72b3a49f9861fb691
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/base/http-stream-wrapper.h"
19 #include "hphp/runtime/base/comparisons.h"
20 #include "hphp/runtime/base/ini-setting.h"
21 #include "hphp/runtime/base/runtime-option.h"
22 #include "hphp/runtime/base/string-util.h"
23 #include "hphp/runtime/base/thread-info.h"
24 #include "hphp/runtime/base/url-file.h"
25 #include "hphp/runtime/ext/stream/ext_stream.h"
26 #include "hphp/runtime/ext/url/ext_url.h"
27 #include "hphp/runtime/server/cli-server.h"
28 #include <memory>
30 namespace HPHP {
31 ///////////////////////////////////////////////////////////////////////////////
33 const StaticString
34 s_GET("GET"),
35 s_method("method"),
36 s_http("http"),
37 s_header("header"),
38 s_ignore_errors("ignore_errors"),
39 s_max_redirects("max_redirects"),
40 s_timeout("timeout"),
41 s_proxy("proxy"),
42 s_content("content"),
43 s_user_agent("user_agent"),
44 s_User_Agent("User-Agent");
46 req::ptr<File> HttpStreamWrapper::open(const String& filename,
47 const String& mode, int /*options*/,
48 const req::ptr<StreamContext>& context) {
49 if (RuntimeOption::ServerHttpSafeMode && !is_cli_mode()) {
50 return nullptr;
53 if (strncmp(filename.data(), "http://", sizeof("http://") - 1) &&
54 strncmp(filename.data(), "https://", sizeof("https://") - 1)) {
55 return nullptr;
58 Array headers;
59 String method = s_GET;
60 String post_data = null_string;
61 String proxy_host;
62 String proxy_user;
63 String proxy_pass;
64 int proxy_port = -1;
65 int max_redirs = 20;
66 int timeout = -1;
67 bool ignore_errors = false;
69 if (context && !context->getOptions().isNull() &&
70 !context->getOptions()[s_http].isNull()) {
71 Array opts = context->getOptions()[s_http].toArray();
72 if (opts.exists(s_method)) {
73 method = opts[s_method].toString();
75 if (opts.exists(s_header)) {
76 Array lines;
77 if (opts[s_header].isString()) {
78 lines = StringUtil::Explode(
79 opts[s_header].toString(), "\r\n").toArray();
80 } else if (opts[s_header].isArray()) {
81 lines = opts[s_header];
84 for (ArrayIter it(lines); it; ++it) {
85 Array parts = StringUtil::Explode(
86 it.second().toString(), ":", 2).toArray();
87 headers.set(parts.rvalAt(0).unboxed().tv(), parts.rvalAt(1).tv());
90 if (opts.exists(s_user_agent) && !headers.exists(s_User_Agent)) {
91 headers.set(s_User_Agent, opts[s_user_agent]);
93 if (opts.exists(s_max_redirects)) {
94 max_redirs = opts[s_max_redirects].toInt64();
96 if (opts.exists(s_timeout)) {
97 timeout = opts[s_timeout].toInt64();
99 if (opts.exists(s_ignore_errors)) {
100 ignore_errors = opts[s_ignore_errors].toBoolean();
102 if (opts.exists(s_proxy)) {
103 Variant host = f_parse_url(opts[s_proxy].toString(), k_PHP_URL_HOST);
104 Variant port = f_parse_url(opts[s_proxy].toString(), k_PHP_URL_PORT);
105 if (!same(host, false) && !same(port, false)) {
106 proxy_host = host.toString();
107 proxy_port = port.toInt64();
108 Variant user = f_parse_url(opts[s_proxy].toString(), k_PHP_URL_USER);
109 Variant pass = f_parse_url(opts[s_proxy].toString(), k_PHP_URL_PASS);
110 if (!same(user, false) && !same(pass, false)) {
111 proxy_user = user.toString();
112 proxy_pass = pass.toString();
116 post_data = opts[s_content].toString();
119 if (!headers.exists(s_User_Agent)) {
120 auto default_user_agent = ThreadInfo::s_threadInfo.getNoCheck()
121 ->m_reqInjectionData.getUserAgent();
122 if (!default_user_agent.empty()) {
123 headers.set(s_User_Agent, default_user_agent);
126 auto file = req::make<UrlFile>(method.data(), headers,
127 post_data, max_redirs,
128 timeout, ignore_errors);
129 file->setStreamContext(context);
130 file->setProxy(proxy_host, proxy_port, proxy_user, proxy_pass);
131 bool ret = file->open(filename, mode);
132 if (!ret) {
133 raise_warning("Failed to open %s (%s)", filename.data(),
134 file->getLastError().c_str());
135 return nullptr;
137 return file;
140 ///////////////////////////////////////////////////////////////////////////////