http_class.php
上传用户:yttaitong
上传日期:2009-05-10
资源大小:128k
文件大小:14k
源码类别:

WEB源码(ASP,PHP,...)

开发平台:

PHP

  1. <?php
  2. /*
  3.     [BBWPS!] (C)2006-2010 小蜜蜂版权所有.
  4. This is NOT a freeware, use is subject to license terms
  5.     时间:2007年12月
  6.     描述:模拟客户端,实现HTTP协议(翻译)
  7. */
  8. class HttpClient {
  9.     var $host;                      //服务器
  10.     var $port;                      //端口
  11.     var $path;                      //路径
  12.     var $method;                    //请求方式
  13.     var $postdata = '';             //请求数据参数
  14.     var $cookies = array();         //COOKIE
  15.     var $referer;                   //上一级访问的URL
  16.     var $etag;
  17.     var $accept = 'text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,image/jpeg,image/gif,*/*';
  18.     var $accept_encoding = 'gzip';  //接受的压缩编码
  19.     var $accept_language = 'en-us'; //接受的语言
  20.     var $user_agent = 'HttpClient'; //用户代理
  21.     // 下边的是可选变量
  22.     var $timeout = 20;             //请求的时间
  23.     var $use_gzip = true;           //是否下载
  24.     var $persist_cookies = true;    //是否让COOKIE保持永久有效
  25.     var $persist_referers = true;   //是否每次请求都要写上最后一次请求的URL
  26.     var $debug = false;             //调试是否开启 
  27.     var $handle_redirects = true;   //自动跳转URL是否开启
  28.     var $max_redirects = 5;         //最大的跳转次数
  29.     var $headers_only = false;      //是否只接受头信息
  30.     //基本的授权变量
  31.     var $username;                  //用户名
  32.     var $password;                  //密码
  33.     //响应的变量
  34.     var $status;                    //状态
  35.     var $headers = array();         //头信息 
  36.     var $content = '';              //内容
  37.     var $errormsg;                  //错误
  38.     //跟踪变量
  39.     var $redirect_count = 2;        //跳转的次数
  40.     var $cookie_host = '';          //COOKIE服务器
  41.     //构造函数
  42.     function HttpClient($host, $port=80) {
  43.         $this->host = $host;
  44.         $this->port = $port;
  45.     }
  46.     //用GET方法进行请求,data参数是附加的请求时候的参数
  47.     function get($path, $data = false) {
  48.         $this->path = $path;
  49.         $this->method = 'GET';
  50.         if ($data) {
  51.             $this->path .= '?'.$this->buildQueryString($data); //给URL增加了参数
  52.         }
  53.         return $this->doRequest();
  54.     }
  55.     //用POST方法进行请求,data参数的是提交的内容
  56.     function post($path, $data) {
  57.         $this->path = $path;
  58.         $this->method = 'POST';
  59.         $this->postdata = $this->buildQueryString($data);    //增加提交参数
  60.      return $this->doRequest();
  61.     }
  62.     //设置请求时候的附加参数
  63.     function buildQueryString($data) {
  64.         $querystring = '';
  65.         if (is_array($data)) {
  66.             //改变参数数组的内容
  67.      foreach ($data as $key => $val) {
  68.      if (is_array($val)) {
  69.      foreach ($val as $val2) {
  70.          //将变量进行URL编码,多个参数用&分开
  71.      $querystring .= urlencode($key).'='.urlencode($val2).'&';
  72.      }
  73.      } 
  74.      else {
  75.      $querystring .= urlencode($key).'='.urlencode($val).'&';
  76.      }
  77.      }
  78.      $querystring = substr($querystring, 0, -1); //消除最后边的一个&
  79.      } 
  80.      else {
  81.          $querystring = $data;
  82.      }
  83.      return $querystring;
  84.     }
  85.     //HTTP请求
  86.     function doRequest() { 
  87.         //创建并打开一个SOCKET
  88. if (!$fp = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout)) {
  89.     //判断是不是连接上服务器
  90.             switch($errno) {
  91. case -3:
  92. $this->errormsg = 'Socket创建失败(-3)';
  93. case -4:
  94. $this->errormsg = 'DNS没有解析到该域名(-4)';
  95. case -5:
  96. $this->errormsg = '不能匿名连接或者是超时(-5)';
  97. default:
  98. $this->errormsg = '连接失败('.$errno.')';
  99.     $this->errormsg .= ' '.$errstr;
  100.     $this->debug($this->errormsg);
  101. }
  102. return false;
  103.         }
  104.         //设置SOCKET的超时时间
  105.         socket_set_timeout($fp, $this->timeout);
  106.         //设置请求的头信息
  107.         $request = $this->buildRequest();
  108.         $this->debug('Request', $request);
  109.         fwrite($fp, $request);    //将请求的信息写入SOCKET模拟HTTP请求
  110.      //将所有的变量清空,以等待响应
  111.      $this->headers = array();  //保存响应的头信息
  112.      $this->content = '';       //保存响应的内容
  113.      $this->errormsg = '';      //保存响应的错误编号
  114.      //设置两个标志变量
  115.      $inHeaders = true;
  116.      $atStart = true;
  117.      //现在开始读取响应的信息和读文件的操作是一样的
  118.      while (!feof($fp)) {
  119.          $line = fgets($fp, 4096);  //读去一行信息
  120.          if ($atStart) {
  121.              //开始处理信息
  122.              $atStart = false;     //设置标志信息进行临界数据保护
  123.              if (!preg_match('/HTTP/(\d\.\d)\s*(\d+)\s*(.*)/is', $line, $m)) { //字符串剖析
  124.                  $this->errormsg = "响应的状态不完整: ".htmlentities($line);
  125.                  $this->debug($this->errormsg);
  126.                  return false;
  127.              }
  128.              $http_version = $m[1]; //保存HTTP协议的版本
  129.              $this->status = $m[2]; //保存响应的状态号
  130.              $status_string = $m[3]; //保存状态信息
  131.              $this->debug(trim($line));
  132.              continue;             //读去下一行的内容
  133.          }
  134.          if ($inHeaders) {
  135.              if (trim($line) == '') {
  136.                  $inHeaders = false;
  137.                  $this->debug('Received Headers', $this->headers);
  138.                  if ($this->headers_only) {//判断是否每次请求只是需求头信息
  139.                      break; //
  140.                  }
  141.                  continue;
  142.              }
  143.              if (!preg_match('/([^:]+):\s*(.*)/is', $line, $m)) {
  144.                  continue;        //读去下一行的内容,本次循环结束
  145.              }
  146.              $key = strtolower(trim($m[1]));
  147.              $val = trim($m[2]);
  148.              //处理头信息,有可能是嵌套
  149.              if (isset($this->headers[$key])) {
  150.                  if (is_array($this->headers[$key])) {
  151.                      $this->headers[$key][] = $val;
  152.                  } else {
  153.                      $this->headers[$key] = array($this->headers[$key], $val);
  154.                  }
  155.              } else {
  156.                  $this->headers[$key] = $val;
  157.              }
  158.              continue;
  159.          }
  160.          //将头信息附加到内容中
  161.          $this->content .= $line;
  162.         }
  163.         fclose($fp);
  164.         //如果数据是被压缩,判断是否可以接受压缩类型的文件
  165.         if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] == 'gzip') {
  166.             $this->debug('接受的内容是压缩类型, 正在解压');
  167.             $this->content = substr($this->content, 10); //
  168.             $this->content = gzinflate($this->content);  //解压数据
  169.         }
  170.         $this->etag=$this->headers["etag"];
  171.         //如是需要有长时间的COOKIE有效,把COOKIE的内容保存起来,这里没有关心COOKIE的目录,在实际操作中有可能是无效的,在这里的时候COOKIE的服务器和服务器并不一定相同
  172.         if ($this->persist_cookies && isset($this->headers['set-cookie'])) { 
  173.             $cookies = $this->headers['set-cookie'];
  174.             if (!is_array($cookies)) {
  175.                 $cookies = array($cookies);
  176.             }
  177.             foreach ($cookies as $cookie) {
  178.                 if (preg_match('/([^=]+)=([^;]+);/is', $cookie, $m)) { //原来的代码有点问题,在上面分析之后COOKIE之间就没有了;所以以;结束的话不能找到值
  179.                    $this->cookies[$m[1]] = $m[2];
  180.                 }
  181.                 else{
  182.                  if(preg_match('/([^=]+)=([^;]+)/is', $cookie, $m)){
  183.                     $this->cookies[$m[1]] = $m[2];
  184.                  }
  185.                 }
  186.             }
  187.             //记录COOKIE的域,避免混淆和个服务器的COOKIE
  188.             $this->cookie_host = $this->host;
  189.         }
  190.         //为下一次的提交做准备,一般都是没有什么用处的
  191.         if ($this->persist_referers) {
  192.             //$this->debug('Persisting referer: '.$this->getRequestURL());
  193.             //$this->debug('Persisting referer: '.'http://www.yesho.com/');
  194.             $this->referer = $this->getRequestURL();
  195.         }
  196.         //如果支持自动转向的
  197.         if ($this->handle_redirects) {
  198.             if (++$this->redirect_count >= $this->max_redirects) {
  199.                 $this->errormsg = 'Number of redirects exceeded maximum ('.$this->max_redirects.')';
  200.                 $this->debug($this->errormsg);
  201.                 $this->redirect_count = 0;
  202.                 return false;
  203.             }
  204.             //分析转向的地址,并从新发出请求
  205.             $location = isset($this->headers['location']) ? $this->headers['location'] : '';
  206.             $uri = isset($this->headers['uri']) ? $this->headers['uri'] : '';
  207.             if ($location || $uri) {
  208.                 $url = parse_url($location.$uri);
  209.                 $this->host=$url["host"];
  210.                 return $this->get($url['path']);
  211.             }
  212.         }
  213.         return true;
  214.     }
  215.     //设置请求的头信息,必须遵守HTTP协议
  216.     function buildRequest() {
  217.         $headers = array();
  218.         //设置HTTP协议的版本
  219.         $headers[] = "{$this->method} {$this->path} HTTP/1.0";
  220.         //设置请求的服务器
  221.         $headers[] = "Host: {$this->host}";
  222.         //设置代理用户,一般有浏览器或者是其他的应用程序,这里就是这个HTTPCLIENT这个程序
  223.         $headers[] = "User-Agent: {$this->user_agent}";
  224.         //设置可以接受的文件类型
  225.         $headers[] = "Accept: {$this->accept}";
  226.         //设置编码
  227.         if ($this->use_gzip) {
  228.             $headers[] = "Accept-encoding: {$this->accept_encoding}";
  229.         }
  230.         //设置语言
  231.         $headers[] = "Accept-language: {$this->accept_language}";
  232.         if ($this->referer) {
  233.             $headers[] = "Referer: {$this->referer}";
  234.             
  235.         }
  236.         //测试语句
  237.         //$headers[] = "Referer: {http://count.skycn.com/softdownload.php?id=22620&url=http%3A%2F%2Fgztt.driversky.com%2Fdown%2FMOVDemo.exe}";
  238.         //$headers[] = "Etag: {$this->etag}";
  239.      // 设置Cookies
  240.      if ($this->cookies) {
  241.          $cookie = 'Cookie: ';
  242.          foreach ($this->cookies as $key => $value) {
  243.              $cookie .= "$key=$value; ";
  244.          }
  245.          $headers[] = $cookie;
  246.      }
  247.      // 设置基本的授权认可,在一般的WEB服务器都是接受WWW的匿名用户,所以用处不是很大
  248.      if ($this->username && $this->password) {
  249.          $headers[] = 'Authorization: BASIC '.base64_encode($this->username.':'.$this->password);
  250.      }
  251.      // 如果是POST请求设置内容的类型和长度
  252.      if ($this->postdata) {
  253.          $headers[] = 'Content-Type: application/x-www-form-urlencoded';
  254.          $headers[] = 'Content-Length: '.strlen($this->postdata);
  255.      }
  256.      $request = implode("rn", $headers)."rnrn".$this->postdata;
  257.      return $request;
  258.     }
  259.     //获得请求的状态
  260.     function getStatus() {
  261.         return $this->status;
  262.     }
  263.     //获得请求返回的内容
  264.     function getContent() {
  265.         return $this->content;
  266.     }
  267.     //获得请求返回的头信息
  268.     function getHeaders() {
  269.         return $this->headers;
  270.     }
  271.     //获得某一项的头信息
  272.     function getHeader($header) {
  273.         $header = strtolower($header);
  274.         if (isset($this->headers[$header])) {
  275.             return $this->headers[$header];
  276.         } else {
  277.             return false;
  278.         }
  279.     }
  280.     //获得错误报告
  281.     function getError() {
  282.         return $this->errormsg;
  283.     }
  284.     //获得COOKIE
  285.     function getCookies() {
  286.         return $this->cookies;
  287.     }
  288.     //获得请求的URL
  289.     function getRequestURL() {
  290.         $url = 'http://'.$this->host;
  291.         if ($this->port != 80) {
  292.             $url .= ':'.$this->port;
  293.         }            
  294.         $url .= $this->path;
  295.         return $url;
  296.     }
  297.     // 设置用户
  298.     function setUserAgent($string) {
  299.         $this->user_agent = $string;
  300.     }
  301.     //设置证书
  302.     function setAuthorization($username, $password) {
  303.         $this->username = $username;
  304.         $this->password = $password;
  305.     }
  306.     //设置COOKIE
  307.     function setCookies($array) {
  308.         $this->cookies = $array;
  309.     }
  310.     function setHost($string){
  311.      $this->host=$string;
  312.     }
  313.     function setPath($string){
  314.      $this->path=$string;
  315.     }
  316.     //可选
  317.     function useGzip($boolean) {
  318.         $this->use_gzip = $boolean;
  319.     }
  320.     //设置长期保存的COOKIE
  321.     function setPersistCookies($boolean) {
  322.         $this->persist_cookies = $boolean;
  323.     }
  324.     //设置是否保持最后一次的请求
  325.     function setPersistReferers($boolean) {
  326.         $this->persist_referers = $boolean;
  327.     }
  328.     //设置是否重定向
  329.     function setHandleRedirects($boolean) {
  330.         $this->handle_redirects = $boolean;
  331.     }
  332.     //设置重定向的次数
  333.     function setMaxRedirects($num) {
  334.         $this->max_redirects = $num;
  335.     }
  336.     function setHeadersOnly($boolean) {
  337.         $this->headers_only = $boolean;
  338.     }
  339.     //是否打开调试的状态
  340.     function setDebug($boolean) {
  341.         $this->debug = $boolean;
  342.     }
  343.     function setTimePara($time){
  344.      $this->timeout=$time;
  345.     }
  346.     //快速,简单的GET方法请求
  347.     function quickGet($url) {
  348.         $bits = parse_url($url);
  349.         $host = $bits['host'];
  350.         $port = isset($bits['port']) ? $bits['port'] : 80;
  351.         $path = isset($bits['path']) ? $bits['path'] : '/';
  352.         if (isset($bits['query'])) {
  353.             $path .= '?'.$bits['query'];
  354.         }
  355.         $client = new HttpClient($host, $port);
  356.         if (!$client->get($path)) {
  357.             return false;
  358.         } else {
  359.             return $client->getContent();
  360.         }
  361.     }
  362.     //快速,简单的POST方法请求
  363.     function quickPost($url, $data) {
  364.         $bits = parse_url($url);
  365.         $host = $bits['host'];
  366.         $port = isset($bits['port']) ? $bits['port'] : 80;
  367.         $path = isset($bits['path']) ? $bits['path'] : '/';
  368.         $client = new HttpClient($host, $port);
  369.         if (!$client->post($path, $data)) {
  370.             return false;
  371.         } else {
  372.             return $client->getContent();
  373.         }
  374.     }
  375.     //调试代码
  376.     function debug($msg, $object = false) {
  377.         if ($this->debug) {
  378.             print '<div style="border: 1px solid red; padding: 0.5em; margin: 0.5em;"><strong>HttpClient Debug:</strong> '.$msg;
  379.             if ($object) {
  380.                 ob_start();
  381.              print_r($object);
  382.              $content = htmlentities(ob_get_contents());
  383.              ob_end_clean();
  384.              print '<pre>'.$content.'</pre>';
  385.          }
  386.          print '</div>';
  387.         }
  388.     }   
  389. }
  390. ?>