/** * Uses curl or fsock to make a request to a remote server. Returns the * response. * * @param string $Url The full url to the page being requested (including http://) * @param integer $Timeout How long to allow for this request. Default Garden.SocketTimeout or 1, 0 to never timeout * @param boolean $FollowRedirects Whether or not to follow 301 and 302 redirects. Defaults false. * @return string Response (no headers) */ function ProxyRequest($Url, $Timeout = FALSE, $FollowRedirects = FALSE) { $OriginalTimeout = $Timeout; if ($Timeout === FALSE) { $Timeout = C('Garden.SocketTimeout', 1.0); } $UrlParts = parse_url($Url); $Scheme = GetValue('scheme', $UrlParts, 'http'); $Host = GetValue('host', $UrlParts, ''); $Port = GetValue('port', $UrlParts, $Scheme == 'https' ? '443' : '80'); $Path = GetValue('path', $UrlParts, ''); $Query = GetValue('query', $UrlParts, ''); // Get the cookie. $Cookie = ''; $EncodeCookies = C('Garden.Cookie.Urlencode', TRUE); foreach ($_COOKIE as $Key => $Value) { if (strncasecmp($Key, 'XDEBUG', 6) == 0) { continue; } if (strlen($Cookie) > 0) { $Cookie .= '; '; } $EValue = $EncodeCookies ? urlencode($Value) : $Value; $Cookie .= "{$Key}={$EValue}"; } $Response = ''; if (function_exists('curl_init')) { //$Url = $Scheme.'://'.$Host.$Path; $Handler = curl_init(); curl_setopt($Handler, CURLOPT_URL, $Url); curl_setopt($Handler, CURLOPT_PORT, $Port); curl_setopt($Handler, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($Handler, CURLOPT_HEADER, 1); curl_setopt($Handler, CURLOPT_USERAGENT, ArrayValue('HTTP_USER_AGENT', $_SERVER, 'Vanilla/2.0')); curl_setopt($Handler, CURLOPT_RETURNTRANSFER, 1); if ($Cookie != '') { curl_setopt($Handler, CURLOPT_COOKIE, $Cookie); } if ($Timeout > 0) { curl_setopt($Handler, CURLOPT_TIMEOUT, $Timeout); } // TIM @ 2010-06-28: Commented this out because it was forcing all requests with parameters to be POST. Same for the $Url above // //if ($Query != '') { // curl_setopt($Handler, CURLOPT_POST, 1); // curl_setopt($Handler, CURLOPT_POSTFIELDS, $Query); //} $Response = curl_exec($Handler); $Success = TRUE; if ($Response == FALSE) { $Success = FALSE; $Response = ''; throw new Exception(curl_error($Handler)); } curl_close($Handler); } else { if (function_exists('fsockopen')) { $Referer = Gdn_Url::WebRoot(TRUE); // Make the request $Pointer = @fsockopen($Host, $Port, $ErrorNumber, $Error, $Timeout); if (!$Pointer) { throw new Exception(sprintf(T('Encountered an error while making a request to the remote server (%1$s): [%2$s] %3$s'), $Url, $ErrorNumber, $Error)); } stream_set_timeout($Pointer, $Timeout); if (strlen($Cookie) > 0) { $Cookie = "Cookie: {$Cookie}\r\n"; } $HostHeader = $Host . ($Port != 80 ? ":{$Port}" : ''); $Header = "GET {$Path}?{$Query} HTTP/1.1\r\n" . "Host: {$HostHeader}\r\n" . "User-Agent: " . ArrayValue('HTTP_USER_AGENT', $_SERVER, 'Vanilla/2.0') . "\r\n" . "Accept: */*\r\n" . "Accept-Charset: utf-8;\r\n" . "Referer: {$Referer}\r\n" . "Connection: close\r\n"; if ($Cookie != '') { $Header .= $Cookie; } $Header .= "\r\n"; // Send the headers and get the response fputs($Pointer, $Header); while ($Line = fread($Pointer, 4096)) { $Response .= $Line; } @fclose($Pointer); $Bytes = strlen($Response); $Response = trim($Response); $Success = TRUE; $StreamInfo = stream_get_meta_data($Pointer); if (GetValue('timed_out', $StreamInfo, FALSE) === TRUE) { $Success = FALSE; $Response = "Operation timed out after {$Timeout} seconds with {$Bytes} bytes received."; } } else { throw new Exception(T('Encountered an error while making a request to the remote server: Your PHP configuration does not allow curl or fsock requests.')); } } if (!$Success) { return $Response; } $ResponseHeaderData = trim(substr($Response, 0, strpos($Response, "\r\n\r\n"))); $Response = trim(substr($Response, strpos($Response, "\r\n\r\n") + 4)); $ResponseHeaderLines = explode("\n", trim($ResponseHeaderData)); $Status = array_shift($ResponseHeaderLines); $ResponseHeaders = array(); $ResponseHeaders['HTTP'] = trim($Status); /* get the numeric status code. * - trim off excess edge whitespace, * - split on spaces, * - get the 2nd element (as a single element array), * - pop the first (only) element off it... * - return that. */ $ResponseHeaders['StatusCode'] = array_pop(array_slice(explode(' ', trim($Status)), 1, 1)); foreach ($ResponseHeaderLines as $Line) { $Line = explode(':', trim($Line)); $Key = trim(array_shift($Line)); $Value = trim(implode(':', $Line)); $ResponseHeaders[$Key] = $Value; } if ($FollowRedirects) { $Code = GetValue('StatusCode', $ResponseHeaders, 200); if (in_array($Code, array(301, 302))) { if (array_key_exists('Location', $ResponseHeaders)) { $Location = AbsoluteSource(GetValue('Location', $ResponseHeaders), $Url); return ProxyRequest($Location, $OriginalTimeout, $FollowRedirects); } } } return $Response; }
protected static function StaticDomDocumentReplace(&$String) { if (substr(ltrim($String), 0, 5) != '<?xml') { $String = '<?xml version="1.0" encoding="UTF-8"?' . ">\n" . $String; } $DOMDocument = DOMDocument::LoadXML($String, LIBXML_NOERROR); if ($DOMDocument === False) { return $String; } $ImageDimensions = self::ImageDimensions(); $BeforeCount = count($ImageDimensions); $Domain = Gdn::Request()->Domain(); $DomNodeList = $DOMDocument->GetElementsByTagName('img'); for ($i = $DomNodeList->length - 1; $i >= 0; $i--) { $Node = $DomNodeList->Item($i); $Width = $Node->GetAttribute('width'); $Height = $Node->GetAttribute('height'); if ($Width == '' && $Height == '') { $Src = $Node->GetAttribute('src'); if (!$Src) { continue; } $Src = AbsoluteSource($Src, $Domain); $CrcKey = crc32($Src); if (!array_key_exists($CrcKey, $ImageDimensions)) { $ImageSize = getimagesize($Src); $ImageDimensions[$CrcKey] = array($ImageSize[0], $ImageSize[1], '_src' => $Src); } else { $ImageSize = $ImageDimensions[$CrcKey]; } if ($ImageSize[0] && $ImageSize[1]) { $Node->SetAttribute('width', $ImageSize[0]); $Node->SetAttribute('height', $ImageSize[1]); } } } // Save cache. if (count($ImageDimensions) != $BeforeCount) { self::ImageDimensions($ImageDimensions); } $String = $DOMDocument->saveXML(); // LIBXML_NOXMLDECL | LIBXML_NOENT //$DOMDocument->formatOutput = True; //$String = $DOMDocument->saveXML(Null, LIBXML_NOXMLDECL | LIBXML_NOENT); //d($String); }