[ Index ]

PHP Cross Reference of osCMax 2.0.4

title

Body

[close]

/includes/classes/ -> http_client.php (source)

   1  <?php
   2  /*

   3  $Id: http_client.php 3 2006-05-27 04:59:07Z user $

   4  

   5    osCMax Power E-Commerce

   6    http://oscdox.com

   7  

   8    Copyright 2006 osCMax2005 osCMax, 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  ?>


Generated: Fri Jan 1 13:43:16 2010 Cross-referenced by PHPXref 0.7