[ Index ] |
PHP Cross Reference of osCMax 2.0.4 |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 $Id: http_client.php,v 1.1 2002/11/01 02:26:03 hpdl Exp $ 4 5 osCommerce, Open Source E-Commerce Solutions 6 http://www.oscommerce.com 7 8 Copyright (c) 2002 osCommerce 9 10 Released under the GNU General Public License 11 12 Copyright 2001 Leo West <[email protected]> Net_HTTP_Client v0.6 13 14 Minimal Example: 15 16 $http = new httpClient(); 17 $http->Connect("somehost", 80) or die("Connect problem"); 18 $status = $http->Get("/index.html"); 19 if ($status != 200) { 20 die("Problem : " . $http->getStatusMessage()); 21 } else { 22 echo $http->getBody(); 23 } 24 $http->Disconnect(); 25 26 Persistent Example: 27 28 $http = new httpClient("dir.yahoo.com", 80); 29 $http->addHeader("Host", "dir.yahoo.com"); 30 $http->addHeader("Connection", "keep-alive"); 31 32 if ($http->Get("/Reference/Libraries/") == 200) $page1 = $http->getBody(); 33 if ($http->Get("/News_and_Media/") == 200 ) $page2 = $http->getBody(); 34 $http->disconnect(); 35 */ 36 37 class httpClient { 38 var $url; // array containg server URL, similar to parseurl() returned array 39 var $reply; // response code 40 var $replyString; // full response 41 var $protocolVersion = '1.1'; 42 var $requestHeaders, $requestBody; 43 var $socket = false; 44 // proxy stuff 45 var $useProxy = false; 46 var $proxyHost, $proxyPort; 47 48 /** 49 * httpClient constructor 50 * Note: when host and port are defined, the connection is immediate 51 * @seeAlso connect 52 **/ 53 function httpClient($host = '', $port = '') { 54 if (tep_not_null($host)) { 55 $this->connect($host, $port); 56 } 57 } 58 59 /** 60 * turn on proxy support 61 * @param proxyHost proxy host address eg "proxy.mycorp.com" 62 * @param proxyPort proxy port usually 80 or 8080 63 **/ 64 function setProxy($proxyHost, $proxyPort) { 65 $this->useProxy = true; 66 $this->proxyHost = $proxyHost; 67 $this->proxyPort = $proxyPort; 68 } 69 70 /** 71 * setProtocolVersion 72 * define the HTTP protocol version to use 73 * @param version string the version number with one decimal: "0.9", "1.0", "1.1" 74 * when using 1.1, you MUST set the mandatory headers "Host" 75 * @return boolean false if the version number is bad, true if ok 76 **/ 77 function setProtocolVersion($version) { 78 if ( ($version > 0) && ($version <= 1.1) ) { 79 $this->protocolVersion = $version; 80 return true; 81 } else { 82 return false; 83 } 84 } 85 86 /** 87 * set a username and password to access a protected resource 88 * Only "Basic" authentication scheme is supported yet 89 * @param username string - identifier 90 * @param password string - clear password 91 **/ 92 function setCredentials($username, $password) { 93 $this->addHeader('Authorization', 'Basic ' . base64_encode($username . ':' . $password)); 94 } 95 96 /** 97 * define a set of HTTP headers to be sent to the server 98 * header names are lowercased to avoid duplicated headers 99 * @param headers hash array containing the headers as headerName => headerValue pairs 100 **/ 101 function setHeaders($headers) { 102 if (is_array($headers)) { 103 reset($headers); 104 while (list($name, $value) = each($headers)) { 105 $this->requestHeaders[$name] = $value; 106 } 107 } 108 } 109 110 /** 111 * addHeader 112 * set a unique request header 113 * @param headerName the header name 114 * @param headerValue the header value, ( unencoded) 115 **/ 116 function addHeader($headerName, $headerValue) { 117 $this->requestHeaders[$headerName] = $headerValue; 118 } 119 120 /** 121 * removeHeader 122 * unset a request header 123 * @param headerName the header name 124 **/ 125 function removeHeader($headerName) { 126 unset($this->requestHeaders[$headerName]); 127 } 128 129 /** 130 * Connect 131 * open the connection to the server 132 * @param host string server address (or IP) 133 * @param port string server listening port - defaults to 80 134 * @return boolean false is connection failed, true otherwise 135 **/ 136 function Connect($host, $port = '') { 137 $this->url['scheme'] = 'http'; 138 $this->url['host'] = $host; 139 if (tep_not_null($port)) $this->url['port'] = $port; 140 141 return true; 142 } 143 144 /** 145 * Disconnect 146 * close the connection to the server 147 **/ 148 function Disconnect() { 149 if ($this->socket) fclose($this->socket); 150 } 151 152 /** 153 * head 154 * issue a HEAD request 155 * @param uri string URI of the document 156 * @return string response status code (200 if ok) 157 * @seeAlso getHeaders() 158 **/ 159 function Head($uri) { 160 $this->responseHeaders = $this->responseBody = ''; 161 162 $uri = $this->makeUri($uri); 163 164 if ($this->sendCommand('HEAD ' . $uri . ' HTTP/' . $this->protocolVersion)) { 165 $this->processReply(); 166 } 167 168 return $this->reply; 169 } 170 171 /** 172 * get 173 * issue a GET http request 174 * @param uri URI (path on server) or full URL of the document 175 * @return string response status code (200 if ok) 176 * @seeAlso getHeaders(), getBody() 177 **/ 178 function Get($url) { 179 $this->responseHeaders = $this->responseBody = ''; 180 181 $uri = $this->makeUri($url); 182 183 if ($this->sendCommand('GET ' . $uri . ' HTTP/' . $this->protocolVersion)) { 184 $this->processReply(); 185 } 186 187 return $this->reply; 188 } 189 190 /** 191 * Post 192 * issue a POST http request 193 * @param uri string URI of the document 194 * @param query_params array parameters to send in the form "parameter name" => value 195 * @return string response status code (200 if ok) 196 * @example 197 * $params = array( "login" => "tiger", "password" => "secret" ); 198 * $http->post( "/login.php", $params ); 199 **/ 200 function Post($uri, $query_params = '') { 201 $uri = $this->makeUri($uri); 202 203 if (is_array($query_params)) { 204 $postArray = array(); 205 reset($query_params); 206 while (list($k, $v) = each($query_params)) { 207 $postArray[] = urlencode($k) . '=' . urlencode($v); 208 } 209 210 $this->requestBody = implode('&', $postArray); 211 } 212 213 // set the content type for post parameters 214 $this->addHeader('Content-Type', 'application/x-www-form-urlencoded'); 215 216 if ($this->sendCommand('POST ' . $uri . ' HTTP/' . $this->protocolVersion)) { 217 $this->processReply(); 218 } 219 220 $this->removeHeader('Content-Type'); 221 $this->removeHeader('Content-Length'); 222 $this->requestBody = ''; 223 224 return $this->reply; 225 } 226 227 /** 228 * Put 229 * Send a PUT request 230 * PUT is the method to sending a file on the server. it is *not* widely supported 231 * @param uri the location of the file on the server. dont forget the heading "/" 232 * @param filecontent the content of the file. binary content accepted 233 * @return string response status code 201 (Created) if ok 234 * @see RFC2518 "HTTP Extensions for Distributed Authoring WEBDAV" 235 **/ 236 function Put($uri, $filecontent) { 237 $uri = $this->makeUri($uri); 238 $this->requestBody = $filecontent; 239 240 if ($this->sendCommand('PUT ' . $uri . ' HTTP/' . $this->protocolVersion)) { 241 $this->processReply(); 242 } 243 244 return $this->reply; 245 } 246 247 /** 248 * getHeaders 249 * return the response headers 250 * to be called after a Get() or Head() call 251 * @return array headers received from server in the form headername => value 252 * @seeAlso get, head 253 **/ 254 function getHeaders() { 255 return $this->responseHeaders; 256 } 257 258 /** 259 * getHeader 260 * return the response header "headername" 261 * @param headername the name of the header 262 * @return header value or NULL if no such header is defined 263 **/ 264 function getHeader($headername) { 265 return $this->responseHeaders[$headername]; 266 } 267 268 /** 269 * getBody 270 * return the response body 271 * invoke it after a Get() call for instance, to retrieve the response 272 * @return string body content 273 * @seeAlso get, head 274 **/ 275 function getBody() { 276 return $this->responseBody; 277 } 278 279 /** 280 * getStatus return the server response's status code 281 * @return string a status code 282 * code are divided in classes (where x is a digit) 283 * - 20x : request processed OK 284 * - 30x : document moved 285 * - 40x : client error ( bad url, document not found, etc...) 286 * - 50x : server error 287 * @see RFC2616 "Hypertext Transfer Protocol -- HTTP/1.1" 288 **/ 289 function getStatus() { 290 return $this->reply; 291 } 292 293 /** 294 * getStatusMessage return the full response status, of the form "CODE Message" 295 * eg. "404 Document not found" 296 * @return string the message 297 **/ 298 function getStatusMessage() { 299 return $this->replyString; 300 } 301 302 /** 303 * @scope only protected or private methods below 304 **/ 305 306 /** 307 * send a request 308 * data sent are in order 309 * a) the command 310 * b) the request headers if they are defined 311 * c) the request body if defined 312 * @return string the server repsonse status code 313 **/ 314 function sendCommand($command) { 315 $this->responseHeaders = array(); 316 $this->responseBody = ''; 317 318 // connect if necessary 319 if ( ($this->socket == false) || (feof($this->socket)) ) { 320 if ($this->useProxy) { 321 $host = $this->proxyHost; 322 $port = $this->proxyPort; 323 } else { 324 $host = $this->url['host']; 325 $port = $this->url['port']; 326 } 327 328 if (!tep_not_null($port)) $port = 80; 329 330 if (!$this->socket = fsockopen($host, $port, $this->reply, $this->replyString)) { 331 return false; 332 } 333 334 if (tep_not_null($this->requestBody)) { 335 $this->addHeader('Content-Length', strlen($this->requestBody)); 336 } 337 338 $this->request = $command; 339 $cmd = $command . "\r\n"; 340 if (is_array($this->requestHeaders)) { 341 reset($this->requestHeaders); 342 while (list($k, $v) = each($this->requestHeaders)) { 343 $cmd .= $k . ': ' . $v . "\r\n"; 344 } 345 } 346 347 if (tep_not_null($this->requestBody)) { 348 $cmd .= "\r\n" . $this->requestBody; 349 } 350 351 // unset body (in case of successive requests) 352 $this->requestBody = ''; 353 354 fputs($this->socket, $cmd . "\r\n"); 355 356 return true; 357 } 358 } 359 360 function processReply() { 361 $this->replyString = trim(fgets($this->socket, 1024)); 362 363 if (preg_match('|^HTTP/\S+ (\d+) |i', $this->replyString, $a )) { 364 $this->reply = $a[1]; 365 } else { 366 $this->reply = 'Bad Response'; 367 } 368 369 //get response headers and body 370 $this->responseHeaders = $this->processHeader(); 371 $this->responseBody = $this->processBody(); 372 373 return $this->reply; 374 } 375 376 /** 377 * processHeader() reads header lines from socket until the line equals $lastLine 378 * @scope protected 379 * @return array of headers with header names as keys and header content as values 380 **/ 381 function processHeader($lastLine = "\r\n") { 382 $headers = array(); 383 $finished = false; 384 385 while ( (!$finished) && (!feof($this->socket)) ) { 386 $str = fgets($this->socket, 1024); 387 $finished = ($str == $lastLine); 388 if (!$finished) { 389 list($hdr, $value) = split(': ', $str, 2); 390 // nasty workaround broken multiple same headers (eg. Set-Cookie headers) @FIXME 391 if (isset($headers[$hdr])) { 392 $headers[$hdr] .= '; ' . trim($value); 393 } else { 394 $headers[$hdr] = trim($value); 395 } 396 } 397 } 398 399 return $headers; 400 } 401 402 /** 403 * processBody() reads the body from the socket 404 * the body is the "real" content of the reply 405 * @return string body content 406 * @scope private 407 **/ 408 function processBody() { 409 $data = ''; 410 $counter = 0; 411 412 do { 413 $status = socket_get_status($this->socket); 414 if ($status['eof'] == 1) { 415 break; 416 } 417 418 if ($status['unread_bytes'] > 0) { 419 $buffer = fread($this->socket, $status['unread_bytes']); 420 $counter = 0; 421 } else { 422 $buffer = fread($this->socket, 128); 423 $counter++; 424 usleep(2); 425 } 426 427 $data .= $buffer; 428 } while ( ($status['unread_bytes'] > 0) || ($counter++ < 10) ); 429 430 return $data; 431 } 432 433 /** 434 * Calculate and return the URI to be sent ( proxy purpose ) 435 * @param the local URI 436 * @return URI to be used in the HTTP request 437 * @scope private 438 **/ 439 function makeUri($uri) { 440 $a = parse_url($uri); 441 442 if ( (isset($a['scheme'])) && (isset($a['host'])) ) { 443 $this->url = $a; 444 } else { 445 unset($this->url['query']); 446 unset($this->url['fragment']); 447 $this->url = array_merge($this->url, $a); 448 } 449 450 if ($this->useProxy) { 451 $requesturi = 'http://' . $this->url['host'] . (empty($this->url['port']) ? '' : ':' . $this->url['port']) . $this->url['path'] . (empty($this->url['query']) ? '' : '?' . $this->url['query']); 452 } else { 453 $requesturi = $this->url['path'] . (empty($this->url['query']) ? '' : '?' . $this->url['query']); 454 } 455 456 return $requesturi; 457 } 458 } 459 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Jan 1 13:43:16 2010 | Cross-referenced by PHPXref 0.7 |