PageRenderTime 59ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/wordfence/vendor/wordfence/wf-waf/src/lib/http.php

https://gitlab.com/edgarze188/sunrise
PHP | 440 lines | 261 code | 57 blank | 122 comment | 30 complexity | 6b59187f731a80951beb86ecb9b17592 MD5 | raw file
  1. <?php
  2. class wfWAFHTTP {
  3. private $url;
  4. private $auth;
  5. private $body;
  6. private $cookies;
  7. // private $fileNames;
  8. // private $files;
  9. private $headers;
  10. private $method;
  11. private $queryString;
  12. /**
  13. * @var wfWAFHTTPTransport
  14. */
  15. private $transport;
  16. /**
  17. * @param string $url
  18. * @param wfWAFHTTP $request
  19. * @return wfWAFHTTPResponse|bool
  20. * @throws wfWAFHTTPTransportException
  21. */
  22. public static function get($url, $request = null) {
  23. if (!$request) {
  24. $request = new self();
  25. }
  26. $request->setUrl($url);
  27. $request->setMethod('GET');
  28. $request->setTransport(wfWAFHTTPTransport::getInstance());
  29. // $request->setCookies("XDEBUG_SESSION=netbeans-xdebug");
  30. return $request->send();
  31. }
  32. /**
  33. * @param string $url
  34. * @param array $post
  35. * @param wfWAFHTTP $request
  36. * @return wfWAFHTTPResponse|bool
  37. * @throws wfWAFHTTPTransportException
  38. */
  39. public static function post($url, $post = array(), $request = null) {
  40. if (!$request) {
  41. $request = new self();
  42. }
  43. $request->setUrl($url);
  44. $request->setMethod('POST');
  45. $request->setBody($post);
  46. $request->setTransport(wfWAFHTTPTransport::getInstance());
  47. return $request->send();
  48. }
  49. /**
  50. * @return wfWAFHTTPResponse|bool
  51. * @throws wfWAFHTTPTransportException
  52. */
  53. public function send() {
  54. if (!$this->getTransport()) {
  55. throw new wfWAFHTTPTransportException('Need to provide a valid HTTP transport before calling ' . __METHOD__);
  56. }
  57. return $this->getTransport()->send($this);
  58. }
  59. /**
  60. * @return mixed
  61. */
  62. public function getUrl() {
  63. return $this->url;
  64. }
  65. /**
  66. * @param mixed $url
  67. */
  68. public function setUrl($url) {
  69. $this->url = $url;
  70. }
  71. /**
  72. * @return mixed
  73. */
  74. public function getAuth() {
  75. return $this->auth;
  76. }
  77. /**
  78. * @param mixed $auth
  79. */
  80. public function setAuth($auth) {
  81. $this->auth = $auth;
  82. }
  83. /**
  84. * @return mixed
  85. */
  86. public function getBody() {
  87. return $this->body;
  88. }
  89. /**
  90. * @param mixed $body
  91. */
  92. public function setBody($body) {
  93. $this->body = $body;
  94. }
  95. /**
  96. * @return mixed
  97. */
  98. public function getCookies() {
  99. return $this->cookies;
  100. }
  101. /**
  102. * @param mixed $cookies
  103. */
  104. public function setCookies($cookies) {
  105. $this->cookies = $cookies;
  106. }
  107. /**
  108. * @return mixed
  109. */
  110. public function getHeaders() {
  111. return $this->headers;
  112. }
  113. /**
  114. * @param mixed $headers
  115. */
  116. public function setHeaders($headers) {
  117. $this->headers = $headers;
  118. }
  119. /**
  120. * @return mixed
  121. */
  122. public function getMethod() {
  123. return $this->method;
  124. }
  125. /**
  126. * @param mixed $method
  127. */
  128. public function setMethod($method) {
  129. $this->method = $method;
  130. }
  131. /**
  132. * @return mixed
  133. */
  134. public function getQueryString() {
  135. return $this->queryString;
  136. }
  137. /**
  138. * @param mixed $queryString
  139. */
  140. public function setQueryString($queryString) {
  141. $this->queryString = $queryString;
  142. }
  143. /**
  144. * @return wfWAFHTTPTransport
  145. */
  146. public function getTransport() {
  147. return $this->transport;
  148. }
  149. /**
  150. * @param wfWAFHTTPTransport $transport
  151. */
  152. public function setTransport($transport) {
  153. $this->transport = $transport;
  154. }
  155. }
  156. class wfWAFHTTPResponse {
  157. private $body;
  158. private $headers;
  159. private $statusCode;
  160. /**
  161. * @return mixed
  162. */
  163. public function getBody() {
  164. return $this->body;
  165. }
  166. /**
  167. * @param mixed $body
  168. */
  169. public function setBody($body) {
  170. $this->body = $body;
  171. }
  172. /**
  173. * @return mixed
  174. */
  175. public function getHeaders() {
  176. return $this->headers;
  177. }
  178. /**
  179. * @param mixed $headers
  180. */
  181. public function setHeaders($headers) {
  182. $this->headers = $headers;
  183. }
  184. /**
  185. * @return mixed
  186. */
  187. public function getStatusCode() {
  188. return $this->statusCode;
  189. }
  190. /**
  191. * @param mixed $statusCode
  192. */
  193. public function setStatusCode($statusCode) {
  194. $this->statusCode = $statusCode;
  195. }
  196. }
  197. abstract class wfWAFHTTPTransport {
  198. private static $instance;
  199. /**
  200. * @return mixed
  201. */
  202. public static function getInstance() {
  203. if (!self::$instance) {
  204. self::$instance = self::getFirstTransport();
  205. }
  206. return self::$instance;
  207. }
  208. /**
  209. * @param mixed $instance
  210. */
  211. public static function setInstance($instance) {
  212. self::$instance = $instance;
  213. }
  214. /**
  215. * @return wfWAFHTTPTransport
  216. * @throws wfWAFHTTPTransportException
  217. */
  218. public static function getFirstTransport() {
  219. if (function_exists('curl_init')) {
  220. return new wfWAFHTTPTransportCurl();
  221. } else if (function_exists('file_get_contents')) {
  222. return new wfWAFHTTPTransportStreams();
  223. }
  224. throw new wfWAFHTTPTransportException('No valid HTTP transport found.');
  225. }
  226. /**
  227. * @param array $cookieArray
  228. * @return string
  229. */
  230. public static function buildCookieString($cookieArray) {
  231. $cookies = '';
  232. foreach ($cookieArray as $cookieName => $value) {
  233. $cookies .= "$cookieName=" . urlencode($value) . '; ';
  234. }
  235. $cookies = rtrim($cookies);
  236. return $cookies;
  237. }
  238. /**
  239. * @param wfWAFHTTP $request
  240. * @return wfWAFHTTPResponse|bool
  241. */
  242. abstract public function send($request);
  243. }
  244. class wfWAFHTTPTransportCurl extends wfWAFHTTPTransport {
  245. /**
  246. * @todo Proxy settings
  247. * @param wfWAFHTTP $request
  248. * @return wfWAFHTTPResponse|bool
  249. */
  250. public function send($request) {
  251. $url = $request->getUrl();
  252. if ($queryString = $request->getQueryString()) {
  253. if (is_array($queryString)) {
  254. $queryString = http_build_query($queryString, null, '&');
  255. }
  256. $url .= (wfWAFUtils::strpos($url, '?') !== false ? '&' : '?') . $queryString;
  257. }
  258. $ch = curl_init($url);
  259. switch (wfWAFUtils::strtolower($request->getMethod())) {
  260. case 'post':
  261. curl_setopt($ch, CURLOPT_POST, 1);
  262. break;
  263. }
  264. if ($body = $request->getBody()) {
  265. curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
  266. }
  267. if ($auth = $request->getAuth()) {
  268. curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']);
  269. }
  270. if ($cookies = $request->getCookies()) {
  271. if (is_array($cookies)) {
  272. $cookies = self::buildCookieString($cookies);
  273. }
  274. curl_setopt($ch, CURLOPT_COOKIE, $cookies);
  275. }
  276. if ($headers = $request->getHeaders()) {
  277. if (is_array($headers)) {
  278. $_headers = array();
  279. foreach ($headers as $header => $value) {
  280. $_headers[] = $header . ': ' . $value;
  281. }
  282. curl_setopt($ch, CURLOPT_HTTPHEADER, $_headers);
  283. }
  284. }
  285. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  286. curl_setopt($ch, CURLOPT_TIMEOUT, 5);
  287. curl_setopt($ch, CURLOPT_HEADER, 1);
  288. curl_setopt($ch, CURLOPT_CAINFO, WFWAF_PATH . 'cacert.pem'); //On some systems curl uses an outdated root certificate chain file
  289. $curlResponse = curl_exec($ch);
  290. if ($curlResponse !== false) {
  291. $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  292. $header = wfWAFUtils::substr($curlResponse, 0, $headerSize);
  293. $body = wfWAFUtils::substr($curlResponse, $headerSize);
  294. $response = new wfWAFHTTPResponse();
  295. $response->setBody($body);
  296. $response->setHeaders($header);
  297. return $response;
  298. }
  299. return false;
  300. }
  301. }
  302. class wfWAFHTTPTransportStreams extends wfWAFHTTPTransport {
  303. /**
  304. * @todo Implement wfWAFHTTPTransportStreams::send.
  305. * @param wfWAFHTTP $request
  306. * @return mixed
  307. * @throws wfWAFHTTPTransportException
  308. */
  309. public function send($request) {
  310. $timeout = 5;
  311. $url = $request->getUrl();
  312. if ($queryString = $request->getQueryString()) {
  313. if (is_array($queryString)) {
  314. $queryString = http_build_query($queryString, null, '&');
  315. }
  316. $url .= (wfWAFUtils::strpos($url, '?') !== false ? '&' : '?') . $queryString;
  317. }
  318. $urlParsed = parse_url($request->getUrl());
  319. $headers = "Host: $urlParsed[host]\r\n";
  320. if ($auth = $request->getAuth()) {
  321. $headers .= 'Authorization: Basic ' . base64_encode($auth['user'] . ':' . $auth['password']) . "\r\n";
  322. }
  323. if ($cookies = $request->getCookies()) {
  324. if (is_array($cookies)) {
  325. $cookies = self::buildCookieString($cookies);
  326. }
  327. $headers .= "Cookie: $cookies\r\n";
  328. }
  329. $hasUA = false;
  330. if ($_headers = $request->getHeaders()) {
  331. if (is_array($_headers)) {
  332. foreach ($_headers as $header => $value) {
  333. if (trim(wfWAFUtils::strtolower($header)) === 'user-agent') {
  334. $hasUA = true;
  335. }
  336. $headers .= $header . ': ' . $value . "\r\n";
  337. }
  338. }
  339. }
  340. if (!$hasUA) {
  341. $headers .= "User-Agent: Wordfence Streams UA\r\n";
  342. }
  343. $httpOptions = array(
  344. 'method' => $request->getMethod(),
  345. 'ignore_errors' => true,
  346. 'timeout' => $timeout,
  347. 'follow_location' => 1,
  348. 'max_redirects' => 5,
  349. );
  350. if (wfWAFUtils::strlen($request->getBody()) > 0) {
  351. $httpOptions['content'] = $request->getBody();
  352. $headers .= 'Content-Length: ' . wfWAFUtils::strlen($httpOptions['content']) . "\r\n";
  353. }
  354. $httpOptions['header'] = $headers;
  355. $options = array(
  356. wfWAFUtils::strtolower($urlParsed['scheme']) => $httpOptions,
  357. );
  358. $context = stream_context_create($options);
  359. $stream = fopen($request->getUrl(), 'r', false, $context);
  360. if (!is_resource($stream)) {
  361. return false;
  362. }
  363. $metaData = stream_get_meta_data($stream);
  364. // Get the HTTP response code
  365. $httpResponse = array_shift($metaData['wrapper_data']);
  366. if (preg_match_all('/(\w+\/\d\.\d) (\d{3})/', $httpResponse, $matches) !== false) {
  367. // $protocol = $matches[1][0];
  368. $status = (int) $matches[2][0];
  369. } else {
  370. // $protocol = null;
  371. $status = null;
  372. }
  373. $responseObj = new wfWAFHTTPResponse();
  374. $responseObj->setHeaders(join("\r\n", $metaData['wrapper_data']));
  375. $responseObj->setBody(stream_get_contents($stream));
  376. $responseObj->setStatusCode($status);
  377. // Close the stream after use
  378. fclose($stream);
  379. return $responseObj;
  380. }
  381. }
  382. class wfWAFHTTPTransportException extends wfWAFException {
  383. }