<?php
-// $Id: proxy.php,v 1.3 2005/04/10 07:04:13 henoheno Exp $
+// PukiWiki - Yet another WikiWikiWeb clone
+// proxy.php
+// Copyright: 2003-2017 PukiWiki Development Team
+// License: GPL v2 or (at your option) any later version
//
-// HTTP Proxy related functions
+// HTTP-Proxy related functions
// Max number of 'track' redirection message with 301 or 302 response
-define('PKWK_HTTP_REQUEST_URL_REDIRECT_MAX', 10);
-
-// Separate IPv4 network-address and its netmask
-define('PKWK_CIDR_NETWORK_REGEX', '/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?:\/([0-9.]+))?$/');
+define('PKWK_HTTP_REQUEST_URL_REDIRECT_MAX', 2);
+
+// We also define deprecated function 'http_request' for backward compatibility
+if (!function_exists('http_request')) {
+ // pecl_http extension also have the function named 'http_request'
+ function http_request($url, $method = 'GET', $headers = '',
+ $post = array(), $redirect_max = PKWK_HTTP_REQUEST_URL_REDIRECT_MAX,
+ $content_charset = '') {
+ return pkwk_http_request($url, $method, $headers, $post,
+ $redirect_max, $content_charset);
+ }
+}
/*
- * http_request($url)
+ * pkwk_http_request($url)
* Get / Send data via HTTP request
* $url : URI started with http:// (http://user:pass@host:port/path?query)
* $method : GET, POST, or HEAD
* $headers : Additional HTTP headers, ended with "\r\n"
* $post : An array of data to send via POST method ('key'=>'value')
* $redirect_max : Max number of HTTP redirect
+ * $content_charset : Content charset. Use '' or CONTENT_CHARSET
*/
-function http_request($url, $method = 'GET', $headers = '', $post = array(),
- $redirect_max = PKWK_HTTP_REQUEST_URL_REDIRECT_MAX)
+function pkwk_http_request($url, $method = 'GET', $headers = '', $post = array(),
+ $redirect_max = PKWK_HTTP_REQUEST_URL_REDIRECT_MAX, $content_charset = '')
{
- global $proxy_host, $proxy_port;
+ global $use_proxy, $no_proxy, $proxy_host, $proxy_port;
global $need_proxy_auth, $proxy_auth_user, $proxy_auth_pass;
-
$rc = array();
$arr = parse_url($url);
- $via_proxy = via_proxy($arr['host']);
+ $via_proxy = $use_proxy ? ! in_the_net($no_proxy, $arr['host']) : FALSE;
// query
$arr['query'] = isset($arr['query']) ? '?' . $arr['query'] : '';
// port
- $arr['port'] = isset($arr['port']) ? $arr['port'] : 80;
+ if (!isset($arr['port'])) {
+ if ($arr['scheme'] === 'https') {
+ $arr['port'] = 443;
+ } else {
+ $arr['port'] = 80;
+ }
+ }
$url_base = $arr['scheme'] . '://' . $arr['host'] . ':' . $arr['port'];
$url_path = isset($arr['path']) ? $arr['path'] : '/';
$query .= $headers;
if (strtoupper($method) == 'POST') {
+ // 'application/x-www-form-urlencoded', especially for TrackBack ping
$POST = array();
foreach ($post as $name=>$val) $POST[] = $name . '=' . urlencode($val);
$data = join('&', $POST);
- $query .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n";
+
+ if (preg_match('/^[a-zA-Z0-9_-]+$/', $content_charset)) {
+ // Legacy but simple
+ $query .= 'Content-Type: application/x-www-form-urlencoded' . "\r\n";
+ } else {
+ // With charset (NOTE: Some implementation may hate this)
+ $query .= 'Content-Type: application/x-www-form-urlencoded' .
+ '; charset=' . strtolower($content_charset) . "\r\n";
+ }
+
$query .= 'Content-Length: ' . strlen($data) . "\r\n";
$query .= "\r\n";
$query .= $data;
$errno = 0;
$errstr = '';
+ $ssl_prefix = '';
+ if ($arr['scheme'] === 'https') {
+ $ssl_prefix = 'ssl://';
+ }
$fp = fsockopen(
- $via_proxy ? $proxy_host : $arr['host'],
+ $ssl_prefix . ($via_proxy ? $proxy_host : $arr['host']),
$via_proxy ? $proxy_port : $arr['port'],
$errno, $errstr, 30);
if ($fp === FALSE) {
$url = $url_base . $url; // Add sheme, host
}
// Redirect
- return http_request($url, $method, $headers, $post, $redirect_max);
+ return pkwk_http_request($url, $method, $headers, $post, $redirect_max);
}
}
return array(
);
}
-// Check HTTP proxy server is needed or not for the $host
-function via_proxy($host)
+// Separate IPv4 network-address and its netmask
+define('PKWK_CIDR_NETWORK_REGEX', '/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?:\/([0-9.]+))?$/');
+
+// Check if the $host is in the specified network(s)
+function in_the_net($networks = array(), $host = '')
{
- global $use_proxy, $no_proxy;
+ if (empty($networks) || $host == '') return FALSE;
+ if (! is_array($networks)) $networks = array($networks);
- if (! $use_proxy) return FALSE;
+ $matches = array();
- $ip = gethostbyname($host);
+ if (preg_match(PKWK_CIDR_NETWORK_REGEX, $host, $matches)) {
+ $ip = $matches[1];
+ } else {
+ $ip = gethostbyname($host); // May heavy
+ }
$l_ip = ip2long($ip);
- $is_valid = (is_long($l_ip) && long2ip($l_ip) == $ip); // Valid IP address
- $matches = array();
- foreach ($no_proxy as $network) {
- if ($is_valid && preg_match(PKWK_CIDR_NETWORK_REGEX, $network, $matches)) {
+ foreach ($networks as $network) {
+ if (preg_match(PKWK_CIDR_NETWORK_REGEX, $network, $matches) &&
+ is_long($l_ip) && long2ip($l_ip) == $ip) {
+ // $host seems valid IPv4 address
// Sample: '10.0.0.0/8' or '10.0.0.0/255.0.0.0'
$l_net = ip2long($matches[1]); // '10.0.0.0'
$mask = isset($matches[2]) ? $matches[2] : 32; // '8' or '255.0.0.0'
pow(2, 32) - pow(2, 32 - $mask) : // '8' means '8-bit mask'
ip2long($mask); // '255.0.0.0' (the same)
- if (($l_ip & $mask) == $l_net) return FALSE;
+ if (($l_ip & $mask) == $l_net) return TRUE;
} else {
- // Hostname, or a part of hostname
- if (preg_match('/' . preg_quote($network, '/') . '$/', $host))
- return FALSE;
+ // $host seems not IPv4 address. May be a DNS name like 'foobar.example.com'?
+ foreach ($networks as $network)
+ if (preg_match('/\.?\b' . preg_quote($network, '/') . '$/', $host))
+ return TRUE;
}
}
- return TRUE; // Proxy needed
+ return FALSE; // Not found
}
-?>