* @copyright 2005 Janrain, Inc. * @license http://www.gnu.org/copyleft/lesser.html LGPL */ /** * Interface import */ require_once "Auth/OpenID/HTTPFetcher.php"; /** * This class implements a plain, hand-built socket-based fetcher * which will be used in the event that CURL is unavailable. * * @package OpenID */ class Auth_OpenID_PlainHTTPFetcher extends Auth_OpenID_HTTPFetcher { function get($url) { if (!$this->allowedURL($url)) { trigger_error("Bad URL scheme in url: " . $url, E_USER_WARNING); return null; } $redir = true; $stop = time() + $this->timeout; $off = $this->timeout; while ($redir && ($off > 0)) { $parts = parse_url($url); // Set a default port. if (!array_key_exists('port', $parts)) { if ($parts['scheme'] == 'http') { $parts['port'] = 80; } elseif ($parts['scheme'] == 'https') { $parts['port'] = 443; } else { trigger_error("fetcher post method doesn't support " . " scheme '" . $parts['scheme'] . "', no default port available", E_USER_WARNING); return null; } } $host = $parts['host']; if ($parts['scheme'] == 'https') { $host = 'ssl://' . $host; } $user_agent = $this->user_agent; $headers = array( "GET ".$parts['path']." HTTP/1.0", "User-Agent: $user_agent", "Host: ".$parts['host'].":".$parts['port'], "Port: ".$parts['port'], "Cache-Control: no-cache"); $errno = 0; $errstr = ''; $sock = fsockopen($host, $parts['port'], $errno, $errstr, $this->timeout); if ($sock === false) { return false; } stream_set_timeout($sock, $this->timeout); fputs($sock, implode("\r\n", $headers) . "\r\n\r\n"); $data = ""; while (!feof($sock)) { $data .= fgets($sock, 1024); } fclose($sock); // Split response into header and body sections list($headers, $body) = explode("\r\n\r\n", $data, 2); $headers = explode("\r\n", $headers); $http_code = explode(" ", $headers[0]); $code = $http_code[1]; if (in_array($code, array('301', '302'))) { $url = $this->_findRedirect($headers); $redir = true; } else { $redir = false; } $off = $stop - time(); } return array($code, $url, $body); } function post($url, $body) { if (!$this->allowedURL($url)) { trigger_error("Bad URL scheme in url: " . $url, E_USER_WARNING); return null; } $parts = parse_url($url); $headers = array(); $headers[] = "POST ".$parts['path']." HTTP/1.1"; $headers[] = "Host: " . $parts['host']; $headers[] = "Content-type: application/x-www-form-urlencoded"; $headers[] = "Content-length: " . strval(strlen($body)); // Join all headers together. $all_headers = implode("\r\n", $headers); // Add headers, two newlines, and request body. $request = $all_headers . "\r\n\r\n" . $body; // Set a default port. if (!array_key_exists('port', $parts)) { if ($parts['scheme'] == 'http') { $parts['port'] = 80; } elseif ($parts['scheme'] == 'https') { $parts['port'] = 443; } else { trigger_error("fetcher post method doesn't support scheme '" . $parts['scheme'] . "', no default port available", E_USER_WARNING); return null; } } if ($parts['scheme'] == 'https') { $parts['host'] = sprintf("ssl://%s", $parts['host']); } // Connect to the remote server. $errno = 0; $errstr = ''; $sock = fsockopen($parts['host'], $parts['port'], $errno, $errstr, $this->timeout); if ($sock === false) { trigger_error("Could not connect to " . $parts['host'] . " port " . $parts['port'], E_USER_WARNING); return null; } stream_set_timeout($sock, $this->timeout); // Write the POST request. fputs($sock, $request); // Get the response from the server. $response = ""; while (!feof($sock)) { if ($data = fgets($sock, 128)) { $response .= $data; } else { break; } } // Split the request into headers and body. list($headers, $response_body) = explode("\r\n\r\n", $response, 2); $headers = explode("\r\n", $headers); // Expect the first line of the headers data to be something // like HTTP/1.1 200 OK. Split the line on spaces and take // the second token, which should be the return code. $http_code = explode(" ", $headers[0]); $code = $http_code[1]; return array($code, $url, $response_body); } } ?>