1. <?php
  2. /////////////////////////////////////////////////
  3. // PukiWiki - Yet another WikiWikiWeb clone.
  4. //
  5. // $Id: proxy.php,v 1.4 2003/10/01 05:38:47 arino Exp $
  6. //
  7. /*
  8.  * http_request($url)
  9.  *   HTTPリクエストを発行し、データを取得する
  10.  * $url     : http://から始まるURL(http://user:pass@host:port/path?query)
  11.  * $method  : GET, POST, HEADのいずれか(デフォルトはGET)
  12.  * $headers : 任意の追加ヘッダ
  13.  * $post    : POSTの時に送信するデータを格納した配列('変数名'=>'値')
  14.  * $redirect_max : HTTP redirectの回数制限
  15. */
  16. // リダイレクト回数制限の初期値
  17. define('HTTP_REQUEST_URL_REDIRECT_MAX',10);
  18. function http_request($url,$method='GET',$headers='',$post=array(),
  19.     $redirect_max=HTTP_REQUEST_URL_REDIRECT_MAX)
  20. {
  21.     global $use_proxy,$proxy_host,$proxy_port;
  22.     global $need_proxy_auth,$proxy_auth_user,$proxy_auth_pass;
  23.     
  24.     $rc = array();
  25.     $arr parse_url($url);
  26.     
  27.     $via_proxy $use_proxy and via_proxy($arr['host']);
  28.     
  29.     // query
  30.     $arr['query'] = isset($arr['query']) ? '?'.$arr['query'] : '';
  31.     // port
  32.     $arr['port'] = isset($arr['port']) ? $arr['port'] : 80;
  33.     
  34.     $url_base $arr['scheme'].'://'.$arr['host'].':'.$arr['port'];
  35.     $url_path = isset($arr['path']) ? $arr['path'] : '/';
  36.     $url = ($via_proxy $url_base '').$url_path.$arr['query'];
  37.     
  38.     $query $method.' '.$url." HTTP/1.0\r\n";
  39.     $query .= "Host: ".$arr['host']."\r\n";
  40.     $query .= "User-Agent: PukiWiki/".S_VERSION."\r\n";
  41.     // proxyのBasic認証
  42.     if ($need_proxy_auth and isset($proxy_auth_user) and isset($proxy_auth_pass))
  43.     {
  44.         $query .= 'Proxy-Authorization: Basic '.
  45.             base64_encode($proxy_auth_user.':'.$proxy_auth_pass)."\r\n";
  46.     }
  47.     // Basic 認証用
  48.     if (isset($arr['user']) and isset($arr['pass']))
  49.     {
  50.         $query .= 'Authorization: Basic '.
  51.             base64_encode($arr['user'].':'.$arr['pass'])."\r\n";
  52.     }
  53.     
  54.     $query .= $headers;
  55.     
  56.     // POST 時は、urlencode したデータとする
  57.     if (strtoupper($method) == 'POST')
  58.     {
  59.         $POST = array();
  60.         foreach ($post as $name=>$val)
  61.         {
  62.             $POST[] = $name.'='.urlencode($val);
  63.         }
  64.         $data join('&',$POST);
  65.         $query .= "Content-Type: application/x-www-form-urlencoded\r\n";
  66.         $query .= 'Content-Length: '.strlen($data)."\r\n";
  67.         $query .= "\r\n";
  68.         $query .= $data;
  69.     }
  70.     else
  71.     {
  72.         $query .= "\r\n";
  73.     }
  74.     
  75.     $fp fsockopen(
  76.         $via_proxy $proxy_host $arr['host'],
  77.         $via_proxy $proxy_port $arr['port'],
  78.         $errno,$errstr,30);
  79.     if (!$fp)
  80.     {
  81.         return array(
  82.             'query'  => $query// Query String
  83.             'rc'     => $errno// エラー番号
  84.             'header' => '',     // Header
  85.             'data'   => $errstr // エラーメッセージ
  86.         );
  87.     }
  88.     
  89.     fputs($fp$query);
  90.     
  91.     $response '';
  92.     while (!feof($fp))
  93.     {
  94.         $response .= fread($fp,4096);
  95.     }
  96.     fclose($fp);
  97.     
  98.     $resp explode("\r\n\r\n",$response,2);
  99.     $rccd explode(' ',$resp[0],3); // array('HTTP/1.1','200','OK\r\n...')
  100.     $rc = (integer)$rccd[1];
  101.     
  102.     // Redirect
  103.     switch ($rc)
  104.     {
  105.         case 302// Moved Temporarily
  106.         case 301// Moved Permanently
  107.             if (preg_match('/^Location: (.+)$/m',$resp[0],$matches)
  108.                 and --$redirect_max 0)
  109.             {
  110.                 $url trim($matches[1]);
  111.                 if (!preg_match('/^https?:\//',$url)) // no scheme
  112.                 {
  113.                     if ($url{0} != '/'// Relative path
  114.                     {
  115.                         // to Absolute path
  116.                         $url substr($url_path,0,strrpos($url_path,'/')).'/'.$url;
  117.                     }
  118.                     // add sheme,host
  119.                     $url $url_base.$url;
  120.                 } 
  121.                 return http_request($url,$method,$headers,$post,$redirect_max);
  122.             }
  123.     }
  124.     
  125.     return array(
  126.         'query'  => $query,   // Query String
  127.         'rc'     => $rc,      // Response Code
  128.         'header' => $resp[0], // Header
  129.         'data'   => $resp[1]  // Data
  130.     );
  131. }
  132. // プロキシを経由する必要があるかどうか判定
  133. function via_proxy($host)
  134. {
  135.     global $use_proxy,$no_proxy;
  136.     static $ip_pattern '/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?:\/(.+))?$/';
  137.     
  138.     if (!$use_proxy)
  139.     {
  140.         return FALSE;
  141.     }
  142.     $ip gethostbyname($host);
  143.     $l_ip ip2long($ip);
  144.     $valid = (is_long($l_ip) and long2ip($l_ip) == $ip); // valid ip address
  145.     
  146.     foreach ($no_proxy as $network)
  147.     {
  148.         if ($valid and preg_match($ip_pattern,$network,$matches))
  149.         {
  150.             $l_net ip2long($matches[1]);
  151.             $mask array_key_exists(2,$matches) ? $matches[2] : 32;
  152.             $mask is_numeric($mask) ?
  153.                 pow(2,32) - pow(2,32 $mask) : // "10.0.0.0/8"
  154.                 ip2long($mask);                 // "10.0.0.0/255.0.0.0"
  155.             if (($l_ip $mask) == $l_net)
  156.             {
  157.                 return FALSE;
  158.             }
  159.         }
  160.         else
  161.         {
  162.             if (preg_match('/'.preg_quote($network,'/').'/',$host))
  163.             {
  164.                 return FALSE;
  165.             }
  166.         }
  167.     }
  168.     return TRUE;
  169. }
  170. ?>