$value) { $url .= $sep . $key .'='. urlencode($value); $sep = '&'; } // Send back the right method $method = $_SERVER['REQUEST_METHOD']; /* * Common awaited Content-Type header values: * - Content-Type: text/html * - Content-Type: application/x-www-form-urlencoded * - Content-Type: multipart/form-data * - Content-Type: application/xml * The fact is, whatever sends the remote client, if this header is present we * must send back data, which we get back. */ if (isset($_SERVER['CONTENT_TYPE']) && ! empty($_SERVER['CONTENT_LENGTH'])) { // Get back the correct data $headers['Content-Type'] = $_SERVER['CONTENT_TYPE']; $headers['Content-Length'] = $_SERVER['CONTENT_LENGTH']; $data = @file_get_contents('php://input'); //$data = @$GLOBALS["HTTP_RAW_POST_DATA"]; } else { $data = NULL; } /* * Additional request headers present in $_SERVER with prefix HTTP_. * E.g. HTTP_ACCEPT etc. */ foreach ($_SERVER as $key => $value) { if (strpos($key, 'HTTP_') === 0 && !in_array($key, $ignore_headers)) { $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($key, 5))))); $headers[$key] = $value; } } // Signal that the connection will be closed after completion of the response $headers['Connection'] = 'close'; // Proxy request should pass on cookie headers to prevent Drupal from // ending a session. Note: only if same host as this site! if (!empty($_COOKIE) && $_SERVER['HTTP_HOST'] == parse_url($url, PHP_URL_HOST)) { $cookies = ''; $sep = ''; foreach ($_COOKIE as $key => $value) { $cookies .= $sep . $key .'='. $value; $sep = '; '; } $headers['Cookie'] = $cookies; } // Now make request to target //$response = drupal_http_request($url, $headers, $method, $data); $result = new stdClass(); // Parse the URL and make sure we can handle the schema. $uri = parse_url($url); switch ($uri['scheme']) { case 'http': $port = isset($uri['port']) ? $uri['port'] : 80; $host = $uri['host'] . ($port != 80 ? ':'. $port : ''); $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15); break; case 'https': // Note: Only works for PHP 4.3 compiled with OpenSSL. $port = isset($uri['port']) ? $uri['port'] : 443; $host = $uri['host'] . ($port != 443 ? ':'. $port : ''); $fp = @fsockopen('ssl://'. $uri['host'], $port, $errno, $errstr, 20); break; default: header('HTTP/1.1 400 Bad Request'); die('Invalid schema'); } // Make sure the socket opened properly. if (!$fp) { // When a network error occurs, we use a negative number so it does not // clash with the HTTP status codes. // @todo: return code for network error? // header() die('Network error: '. $errstr .' ('. $errno . ')'); } // Construct the path to act on. $path = isset($uri['path']) ? $uri['path'] : '/'; if (isset($uri['query'])) { $path .= '?'. $uri['query']; } // Create HTTP request. $defaults = array( // RFC 2616: "non-standard ports MUST, default ports MAY be included". // We don't add the port to prevent from breaking rewrite rules checking the // host that do not take into account the port number. 'Host' => "Host: $host", 'User-Agent' => 'User-Agent: Proxy (+http://aardbodem.nl/)', 'Content-Length' => 'Content-Length: '. strlen($data) ); // If the server url has a user then attempt to use basic authentication if (isset($uri['user'])) { $defaults['Authorization'] = 'Authorization: Basic '. base64_encode($uri['user'] . (!empty($uri['pass']) ? ":". $uri['pass'] : '')); } foreach ($headers as $header => $value) { $defaults[$header] = $header .': '. $value; } $request = $method .' '. $path ." HTTP/1.0\r\n"; $request .= implode("\r\n", $defaults); $request .= "\r\n\r\n"; if ($data) { $request .= $data ."\r\n"; } $result->request = $request; fwrite($fp, $request); // Fetch response. $response = ''; $count = 0; while (!feof($fp) && $chunk = fread($fp, 1024)) { //echo 'chunk '. ++$count .'
'; if (! $result->data) { $response .= $chunk; list($split, $result->data) = explode("\r\n\r\n", $response, 2); //echo var_export($result, true) . '
'; } else { //$result->data .= $chunk; if (! $result->headers) { //echo 'header was received
'; // process header in $split $split = preg_split("/\r\n|\n|\r/", $split); list($protocol, $code, $text) = explode(' ', trim(array_shift($split)), 3); // Parse headers $result->headers = array(); while ($line = trim(array_shift($split))) { list($header, $value) = explode(':', $line, 2); if (isset($result->headers[$header]) && $header == 'Set-Cookie') { // RFC 2109: the Set-Cookie response header comprises the token Set- // Cookie:, followed by a comma-separated list of one or more cookies. $result->headers[$header] .= ','. trim($value); } else { $result->headers[$header] = trim($value); } } // Check headers if (! empty($permitted_content_types)) { $lowercase_headers = array_change_key_case($result->headers, CASE_LOWER); if (0 == preg_match($permitted_content_types, $lowercase_headers['content-type'])) { header('HTTP/1.1 403 Forbidden'); die('Content type not permitted'); } } // Return headers to caller foreach ($result->headers as $key => $value) { header($key .': '. $value, true); } // Echo first part of data echo $result->data; } // Echo chunk of data echo $chunk; } } fclose($fp); exit();