1832 lines
59 KiB
PHP
1832 lines
59 KiB
PHP
<?php
|
|
/**
|
|
* PEAR, HTTP_Request, Net_Socket, Net_URL in one file for Jlog
|
|
*
|
|
* I have deleted all comments please download the PEAR packages to see
|
|
* the comments. I have added all code from the HTTP_Request.php,
|
|
* Net_Socket.php and URL.php into this file so it is easier to handle.
|
|
*/
|
|
|
|
/**
|
|
* PEAR, the PHP Extension and Application Repository
|
|
*
|
|
* PEAR class and PEAR_Error class
|
|
*
|
|
* PHP versions 4 and 5
|
|
*
|
|
* LICENSE: This source file is subject to version 3.0 of the PHP license
|
|
* that is available through the world-wide-web at the following URI:
|
|
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
|
* the PHP License and are unable to obtain it through the web, please
|
|
* send a note to license@php.net so we can mail you a copy immediately.
|
|
*
|
|
* @category pear
|
|
* @package PEAR
|
|
* @author Sterling Hughes <sterling@php.net>
|
|
* @author Stig Bakken <ssb@php.net>
|
|
* @author Tomas V.V.Cox <cox@idecnet.com>
|
|
* @author Greg Beaver <cellog@php.net>
|
|
* @copyright 1997-2005 The PHP Group
|
|
* @license http://www.php.net/license/3_0.txt PHP License 3.0
|
|
* @version CVS: $Id: PEAR.php,v 1.96 2005/09/21 00:12:35 cellog Exp $
|
|
* @link http://pear.php.net/package/PEAR
|
|
* @since File available since Release 0.1
|
|
*/
|
|
|
|
define('PEAR_ERROR_RETURN', 1);
|
|
define('PEAR_ERROR_PRINT', 2);
|
|
define('PEAR_ERROR_TRIGGER', 4);
|
|
define('PEAR_ERROR_DIE', 8);
|
|
define('PEAR_ERROR_CALLBACK', 16);
|
|
|
|
define('PEAR_ERROR_EXCEPTION', 32);
|
|
|
|
define('PEAR_ZE2', (function_exists('version_compare') &&
|
|
version_compare(zend_version(), "2-dev", "ge")));
|
|
|
|
if (substr(PHP_OS, 0, 3) == 'WIN') {
|
|
define('OS_WINDOWS', true);
|
|
define('OS_UNIX', false);
|
|
define('PEAR_OS', 'Windows');
|
|
} else {
|
|
define('OS_WINDOWS', false);
|
|
define('OS_UNIX', true);
|
|
define('PEAR_OS', 'Unix'); // blatant assumption
|
|
}
|
|
|
|
if (!defined('PATH_SEPARATOR')) {
|
|
if (OS_WINDOWS) {
|
|
define('PATH_SEPARATOR', ';');
|
|
} else {
|
|
define('PATH_SEPARATOR', ':');
|
|
}
|
|
}
|
|
|
|
$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN;
|
|
$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE;
|
|
$GLOBALS['_PEAR_destructor_object_list'] = array();
|
|
$GLOBALS['_PEAR_shutdown_funcs'] = array();
|
|
$GLOBALS['_PEAR_error_handler_stack'] = array();
|
|
|
|
@ini_set('track_errors', true);
|
|
|
|
class PEAR
|
|
{
|
|
|
|
var $_debug = false;
|
|
var $_default_error_mode = null;
|
|
var $_default_error_options = null;
|
|
var $_default_error_handler = '';
|
|
var $_error_class = 'PEAR_Error';
|
|
var $_expected_errors = array();
|
|
|
|
function PEAR($error_class = null)
|
|
{
|
|
$classname = strtolower(get_class($this));
|
|
if ($this->_debug) {
|
|
print "PEAR constructor called, class=$classname\n";
|
|
}
|
|
if ($error_class !== null) {
|
|
$this->_error_class = $error_class;
|
|
}
|
|
while ($classname && strcasecmp($classname, "pear")) {
|
|
$destructor = "_$classname";
|
|
if (method_exists($this, $destructor)) {
|
|
global $_PEAR_destructor_object_list;
|
|
$_PEAR_destructor_object_list[] = &$this;
|
|
if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
|
|
register_shutdown_function("_PEAR_call_destructors");
|
|
$GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
|
|
}
|
|
break;
|
|
} else {
|
|
$classname = get_parent_class($classname);
|
|
}
|
|
}
|
|
}
|
|
|
|
function _PEAR() {
|
|
if ($this->_debug) {
|
|
printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
|
|
}
|
|
}
|
|
|
|
function &getStaticProperty($class, $var)
|
|
{
|
|
static $properties;
|
|
return $properties[$class][$var];
|
|
}
|
|
|
|
function registerShutdownFunc($func, $args = array())
|
|
{
|
|
$GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
|
|
}
|
|
|
|
function isError($data, $code = null)
|
|
{
|
|
if (is_a($data, 'PEAR_Error')) {
|
|
if (is_null($code)) {
|
|
return true;
|
|
} elseif (is_string($code)) {
|
|
return $data->getMessage() == $code;
|
|
} else {
|
|
return $data->getCode() == $code;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function setErrorHandling($mode = null, $options = null)
|
|
{
|
|
if (isset($this) && is_a($this, 'PEAR')) {
|
|
$setmode = &$this->_default_error_mode;
|
|
$setoptions = &$this->_default_error_options;
|
|
} else {
|
|
$setmode = &$GLOBALS['_PEAR_default_error_mode'];
|
|
$setoptions = &$GLOBALS['_PEAR_default_error_options'];
|
|
}
|
|
|
|
switch ($mode) {
|
|
case PEAR_ERROR_EXCEPTION:
|
|
case PEAR_ERROR_RETURN:
|
|
case PEAR_ERROR_PRINT:
|
|
case PEAR_ERROR_TRIGGER:
|
|
case PEAR_ERROR_DIE:
|
|
case null:
|
|
$setmode = $mode;
|
|
$setoptions = $options;
|
|
break;
|
|
|
|
case PEAR_ERROR_CALLBACK:
|
|
$setmode = $mode;
|
|
// class/object method callback
|
|
if (is_callable($options)) {
|
|
$setoptions = $options;
|
|
} else {
|
|
trigger_error("invalid error callback", E_USER_WARNING);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
trigger_error("invalid error mode", E_USER_WARNING);
|
|
break;
|
|
}
|
|
}
|
|
|
|
function expectError($code = '*')
|
|
{
|
|
if (is_array($code)) {
|
|
array_push($this->_expected_errors, $code);
|
|
} else {
|
|
array_push($this->_expected_errors, array($code));
|
|
}
|
|
return sizeof($this->_expected_errors);
|
|
}
|
|
|
|
function popExpect()
|
|
{
|
|
return array_pop($this->_expected_errors);
|
|
}
|
|
|
|
function _checkDelExpect($error_code)
|
|
{
|
|
$deleted = false;
|
|
|
|
foreach ($this->_expected_errors AS $key => $error_array) {
|
|
if (in_array($error_code, $error_array)) {
|
|
unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
|
|
$deleted = true;
|
|
}
|
|
|
|
if (0 == count($this->_expected_errors[$key])) {
|
|
unset($this->_expected_errors[$key]);
|
|
}
|
|
}
|
|
return $deleted;
|
|
}
|
|
|
|
function delExpect($error_code)
|
|
{
|
|
$deleted = false;
|
|
|
|
if ((is_array($error_code) && (0 != count($error_code)))) {
|
|
foreach($error_code as $key => $error) {
|
|
if ($this->_checkDelExpect($error)) {
|
|
$deleted = true;
|
|
} else {
|
|
$deleted = false;
|
|
}
|
|
}
|
|
return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
|
|
} elseif (!empty($error_code)) {
|
|
if ($this->_checkDelExpect($error_code)) {
|
|
return true;
|
|
} else {
|
|
return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
|
|
}
|
|
} else {
|
|
return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
|
|
}
|
|
}
|
|
|
|
function &raiseError($message = null,
|
|
$code = null,
|
|
$mode = null,
|
|
$options = null,
|
|
$userinfo = null,
|
|
$error_class = null,
|
|
$skipmsg = false)
|
|
{
|
|
// The error is yet a PEAR error object
|
|
if (is_object($message)) {
|
|
$code = $message->getCode();
|
|
$userinfo = $message->getUserInfo();
|
|
$error_class = $message->getType();
|
|
$message->error_message_prefix = '';
|
|
$message = $message->getMessage();
|
|
}
|
|
|
|
if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
|
|
if ($exp[0] == "*" ||
|
|
(is_int(reset($exp)) && in_array($code, $exp)) ||
|
|
(is_string(reset($exp)) && in_array($message, $exp))) {
|
|
$mode = PEAR_ERROR_RETURN;
|
|
}
|
|
}
|
|
if ($mode === null) {
|
|
if (isset($this) && isset($this->_default_error_mode)) {
|
|
$mode = $this->_default_error_mode;
|
|
$options = $this->_default_error_options;
|
|
} elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
|
|
$mode = $GLOBALS['_PEAR_default_error_mode'];
|
|
$options = $GLOBALS['_PEAR_default_error_options'];
|
|
}
|
|
}
|
|
|
|
if ($error_class !== null) {
|
|
$ec = $error_class;
|
|
} elseif (isset($this) && isset($this->_error_class)) {
|
|
$ec = $this->_error_class;
|
|
} else {
|
|
$ec = 'PEAR_Error';
|
|
}
|
|
if ($skipmsg) {
|
|
$a = new $ec($code, $mode, $options, $userinfo);
|
|
return $a;
|
|
} else {
|
|
$a = new $ec($message, $code, $mode, $options, $userinfo);
|
|
return $a;
|
|
}
|
|
}
|
|
|
|
function &throwError($message = null,
|
|
$code = null,
|
|
$userinfo = null)
|
|
{
|
|
if (isset($this) && is_a($this, 'PEAR')) {
|
|
$a = &$this->raiseError($message, $code, null, null, $userinfo);
|
|
return $a;
|
|
} else {
|
|
$a = &PEAR::raiseError($message, $code, null, null, $userinfo);
|
|
return $a;
|
|
}
|
|
}
|
|
|
|
function staticPushErrorHandling($mode, $options = null)
|
|
{
|
|
$stack = &$GLOBALS['_PEAR_error_handler_stack'];
|
|
$def_mode = &$GLOBALS['_PEAR_default_error_mode'];
|
|
$def_options = &$GLOBALS['_PEAR_default_error_options'];
|
|
$stack[] = array($def_mode, $def_options);
|
|
switch ($mode) {
|
|
case PEAR_ERROR_EXCEPTION:
|
|
case PEAR_ERROR_RETURN:
|
|
case PEAR_ERROR_PRINT:
|
|
case PEAR_ERROR_TRIGGER:
|
|
case PEAR_ERROR_DIE:
|
|
case null:
|
|
$def_mode = $mode;
|
|
$def_options = $options;
|
|
break;
|
|
|
|
case PEAR_ERROR_CALLBACK:
|
|
$def_mode = $mode;
|
|
if (is_callable($options)) {
|
|
$def_options = $options;
|
|
} else {
|
|
trigger_error("invalid error callback", E_USER_WARNING);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
trigger_error("invalid error mode", E_USER_WARNING);
|
|
break;
|
|
}
|
|
$stack[] = array($mode, $options);
|
|
return true;
|
|
}
|
|
|
|
function staticPopErrorHandling()
|
|
{
|
|
$stack = &$GLOBALS['_PEAR_error_handler_stack'];
|
|
$setmode = &$GLOBALS['_PEAR_default_error_mode'];
|
|
$setoptions = &$GLOBALS['_PEAR_default_error_options'];
|
|
array_pop($stack);
|
|
list($mode, $options) = $stack[sizeof($stack) - 1];
|
|
array_pop($stack);
|
|
switch ($mode) {
|
|
case PEAR_ERROR_EXCEPTION:
|
|
case PEAR_ERROR_RETURN:
|
|
case PEAR_ERROR_PRINT:
|
|
case PEAR_ERROR_TRIGGER:
|
|
case PEAR_ERROR_DIE:
|
|
case null:
|
|
$setmode = $mode;
|
|
$setoptions = $options;
|
|
break;
|
|
|
|
case PEAR_ERROR_CALLBACK:
|
|
$setmode = $mode;
|
|
// class/object method callback
|
|
if (is_callable($options)) {
|
|
$setoptions = $options;
|
|
} else {
|
|
trigger_error("invalid error callback", E_USER_WARNING);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
trigger_error("invalid error mode", E_USER_WARNING);
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function pushErrorHandling($mode, $options = null)
|
|
{
|
|
$stack = &$GLOBALS['_PEAR_error_handler_stack'];
|
|
if (isset($this) && is_a($this, 'PEAR')) {
|
|
$def_mode = &$this->_default_error_mode;
|
|
$def_options = &$this->_default_error_options;
|
|
} else {
|
|
$def_mode = &$GLOBALS['_PEAR_default_error_mode'];
|
|
$def_options = &$GLOBALS['_PEAR_default_error_options'];
|
|
}
|
|
$stack[] = array($def_mode, $def_options);
|
|
|
|
if (isset($this) && is_a($this, 'PEAR')) {
|
|
$this->setErrorHandling($mode, $options);
|
|
} else {
|
|
PEAR::setErrorHandling($mode, $options);
|
|
}
|
|
$stack[] = array($mode, $options);
|
|
return true;
|
|
}
|
|
|
|
function popErrorHandling()
|
|
{
|
|
$stack = &$GLOBALS['_PEAR_error_handler_stack'];
|
|
array_pop($stack);
|
|
list($mode, $options) = $stack[sizeof($stack) - 1];
|
|
array_pop($stack);
|
|
if (isset($this) && is_a($this, 'PEAR')) {
|
|
$this->setErrorHandling($mode, $options);
|
|
} else {
|
|
PEAR::setErrorHandling($mode, $options);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function loadExtension($ext)
|
|
{
|
|
if (!extension_loaded($ext)) {
|
|
if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
|
|
return false;
|
|
}
|
|
if (OS_WINDOWS) {
|
|
$suffix = '.dll';
|
|
} elseif (PHP_OS == 'HP-UX') {
|
|
$suffix = '.sl';
|
|
} elseif (PHP_OS == 'AIX') {
|
|
$suffix = '.a';
|
|
} elseif (PHP_OS == 'OSX') {
|
|
$suffix = '.bundle';
|
|
} else {
|
|
$suffix = '.so';
|
|
}
|
|
return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
}
|
|
|
|
function _PEAR_call_destructors()
|
|
{
|
|
global $_PEAR_destructor_object_list;
|
|
if (is_array($_PEAR_destructor_object_list) &&
|
|
sizeof($_PEAR_destructor_object_list))
|
|
{
|
|
reset($_PEAR_destructor_object_list);
|
|
if (@PEAR::getStaticProperty('PEAR', 'destructlifo')) {
|
|
$_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
|
|
}
|
|
while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
|
|
$classname = get_class($objref);
|
|
while ($classname) {
|
|
$destructor = "_$classname";
|
|
if (method_exists($objref, $destructor)) {
|
|
$objref->$destructor();
|
|
break;
|
|
} else {
|
|
$classname = get_parent_class($classname);
|
|
}
|
|
}
|
|
}
|
|
$_PEAR_destructor_object_list = array();
|
|
}
|
|
|
|
if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
|
|
foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
|
|
call_user_func_array($value[0], $value[1]);
|
|
}
|
|
}
|
|
}
|
|
|
|
class PEAR_Error
|
|
{
|
|
|
|
function PEAR_Error($message = 'unknown error', $code = null,
|
|
$mode = null, $options = null, $userinfo = null)
|
|
{
|
|
if ($mode === null) {
|
|
$mode = PEAR_ERROR_RETURN;
|
|
}
|
|
$this->message = $message;
|
|
$this->code = $code;
|
|
$this->mode = $mode;
|
|
$this->userinfo = $userinfo;
|
|
if (function_exists("debug_backtrace")) {
|
|
if (@!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {
|
|
$this->backtrace = debug_backtrace();
|
|
}
|
|
}
|
|
if ($mode & PEAR_ERROR_CALLBACK) {
|
|
$this->level = E_USER_NOTICE;
|
|
$this->callback = $options;
|
|
} else {
|
|
if ($options === null) {
|
|
$options = E_USER_NOTICE;
|
|
}
|
|
$this->level = $options;
|
|
$this->callback = null;
|
|
}
|
|
if ($this->mode & PEAR_ERROR_PRINT) {
|
|
if (is_null($options) || is_int($options)) {
|
|
$format = "%s";
|
|
} else {
|
|
$format = $options;
|
|
}
|
|
printf($format, $this->getMessage());
|
|
}
|
|
if ($this->mode & PEAR_ERROR_TRIGGER) {
|
|
trigger_error($this->getMessage(), $this->level);
|
|
}
|
|
if ($this->mode & PEAR_ERROR_DIE) {
|
|
$msg = $this->getMessage();
|
|
if (is_null($options) || is_int($options)) {
|
|
$format = "%s";
|
|
if (substr($msg, -1) != "\n") {
|
|
$msg .= "\n";
|
|
}
|
|
} else {
|
|
$format = $options;
|
|
}
|
|
die(sprintf($format, $msg));
|
|
}
|
|
if ($this->mode & PEAR_ERROR_CALLBACK) {
|
|
if (is_callable($this->callback)) {
|
|
call_user_func($this->callback, $this);
|
|
}
|
|
}
|
|
if ($this->mode & PEAR_ERROR_EXCEPTION) {
|
|
trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
|
|
eval('$e = new Exception($this->message, $this->code);throw($e);');
|
|
}
|
|
}
|
|
|
|
function getMode() {
|
|
return $this->mode;
|
|
}
|
|
|
|
function getCallback() {
|
|
return $this->callback;
|
|
}
|
|
|
|
function getMessage()
|
|
{
|
|
return ($this->error_message_prefix . $this->message);
|
|
}
|
|
|
|
function getCode()
|
|
{
|
|
return $this->code;
|
|
}
|
|
|
|
function getType()
|
|
{
|
|
return get_class($this);
|
|
}
|
|
|
|
function getUserInfo()
|
|
{
|
|
return $this->userinfo;
|
|
}
|
|
|
|
function getDebugInfo()
|
|
{
|
|
return $this->getUserInfo();
|
|
}
|
|
|
|
function getBacktrace($frame = null)
|
|
{
|
|
if (defined('PEAR_IGNORE_BACKTRACE')) {
|
|
return null;
|
|
}
|
|
if ($frame === null) {
|
|
return $this->backtrace;
|
|
}
|
|
return $this->backtrace[$frame];
|
|
}
|
|
|
|
function addUserInfo($info)
|
|
{
|
|
if (empty($this->userinfo)) {
|
|
$this->userinfo = $info;
|
|
} else {
|
|
$this->userinfo .= " ** $info";
|
|
}
|
|
}
|
|
|
|
function toString() {
|
|
$modes = array();
|
|
$levels = array(E_USER_NOTICE => 'notice',
|
|
E_USER_WARNING => 'warning',
|
|
E_USER_ERROR => 'error');
|
|
if ($this->mode & PEAR_ERROR_CALLBACK) {
|
|
if (is_array($this->callback)) {
|
|
$callback = (is_object($this->callback[0]) ?
|
|
strtolower(get_class($this->callback[0])) :
|
|
$this->callback[0]) . '::' .
|
|
$this->callback[1];
|
|
} else {
|
|
$callback = $this->callback;
|
|
}
|
|
return sprintf('[%s: message="%s" code=%d mode=callback '.
|
|
'callback=%s prefix="%s" info="%s"]',
|
|
strtolower(get_class($this)), $this->message, $this->code,
|
|
$callback, $this->error_message_prefix,
|
|
$this->userinfo);
|
|
}
|
|
if ($this->mode & PEAR_ERROR_PRINT) {
|
|
$modes[] = 'print';
|
|
}
|
|
if ($this->mode & PEAR_ERROR_TRIGGER) {
|
|
$modes[] = 'trigger';
|
|
}
|
|
if ($this->mode & PEAR_ERROR_DIE) {
|
|
$modes[] = 'die';
|
|
}
|
|
if ($this->mode & PEAR_ERROR_RETURN) {
|
|
$modes[] = 'return';
|
|
}
|
|
return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
|
|
'prefix="%s" info="%s"]',
|
|
strtolower(get_class($this)), $this->message, $this->code,
|
|
implode("|", $modes), $levels[$this->level],
|
|
$this->error_message_prefix,
|
|
$this->userinfo);
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* HTTP_Request.php code:
|
|
*/
|
|
|
|
// +-----------------------------------------------------------------------+
|
|
// | Copyright (c) 2002-2003, Richard Heyes |
|
|
// | All rights reserved. |
|
|
// +-----------------------------------------------------------------------+
|
|
|
|
define('HTTP_REQUEST_METHOD_GET', 'GET', true);
|
|
define('HTTP_REQUEST_METHOD_HEAD', 'HEAD', true);
|
|
define('HTTP_REQUEST_METHOD_POST', 'POST', true);
|
|
define('HTTP_REQUEST_METHOD_PUT', 'PUT', true);
|
|
define('HTTP_REQUEST_METHOD_DELETE', 'DELETE', true);
|
|
define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true);
|
|
define('HTTP_REQUEST_METHOD_TRACE', 'TRACE', true);
|
|
|
|
define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true);
|
|
define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true);
|
|
|
|
class HTTP_Request {
|
|
|
|
var $_url;
|
|
var $_method;
|
|
var $_http;
|
|
var $_requestHeaders;
|
|
var $_user;
|
|
var $_pass;
|
|
var $_sock;
|
|
var $_proxy_host;
|
|
var $_proxy_port;
|
|
var $_proxy_user;
|
|
var $_proxy_pass;
|
|
var $_postData;
|
|
var $_body;
|
|
var $_bodyDisallowed = array('TRACE');
|
|
var $_postFiles = array();
|
|
var $_timeout;
|
|
var $_response;
|
|
var $_allowRedirects;
|
|
var $_maxRedirects;
|
|
var $_redirects;
|
|
var $_useBrackets = true;
|
|
var $_listeners = array();
|
|
var $_saveBody = true;
|
|
var $_readTimeout = null;
|
|
var $_socketOptions = null;
|
|
|
|
function HTTP_Request($url = '', $params = array())
|
|
{
|
|
$this->_sock = new Net_Socket();
|
|
$this->_method = HTTP_REQUEST_METHOD_GET;
|
|
$this->_http = HTTP_REQUEST_HTTP_VER_1_1;
|
|
$this->_requestHeaders = array();
|
|
$this->_postData = array();
|
|
$this->_body = null;
|
|
|
|
$this->_user = null;
|
|
$this->_pass = null;
|
|
|
|
$this->_proxy_host = null;
|
|
$this->_proxy_port = null;
|
|
$this->_proxy_user = null;
|
|
$this->_proxy_pass = null;
|
|
|
|
$this->_allowRedirects = false;
|
|
$this->_maxRedirects = 3;
|
|
$this->_redirects = 0;
|
|
|
|
$this->_timeout = null;
|
|
$this->_response = null;
|
|
|
|
foreach ($params as $key => $value) {
|
|
$this->{'_' . $key} = $value;
|
|
}
|
|
|
|
if (!empty($url)) {
|
|
$this->setURL($url);
|
|
}
|
|
|
|
$this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )');
|
|
|
|
$this->addHeader('Connection', 'close');
|
|
|
|
if (!empty($this->_user)) {
|
|
$this->addHeader('Authorization', 'Basic ' . base64_encode($this->_user . ':' . $this->_pass));
|
|
}
|
|
|
|
if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib') &&
|
|
0 == (2 & ini_get('mbstring.func_overload'))) {
|
|
|
|
$this->addHeader('Accept-Encoding', 'gzip');
|
|
}
|
|
}
|
|
|
|
function _generateHostHeader()
|
|
{
|
|
if ($this->_url->port != 80 AND strcasecmp($this->_url->protocol, 'http') == 0) {
|
|
$host = $this->_url->host . ':' . $this->_url->port;
|
|
|
|
} elseif ($this->_url->port != 443 AND strcasecmp($this->_url->protocol, 'https') == 0) {
|
|
$host = $this->_url->host . ':' . $this->_url->port;
|
|
|
|
} elseif ($this->_url->port == 443 AND strcasecmp($this->_url->protocol, 'https') == 0 AND strpos($this->_url->url, ':443') !== false) {
|
|
$host = $this->_url->host . ':' . $this->_url->port;
|
|
|
|
} else {
|
|
$host = $this->_url->host;
|
|
}
|
|
|
|
return $host;
|
|
}
|
|
|
|
function reset($url, $params = array())
|
|
{
|
|
$this->HTTP_Request($url, $params);
|
|
}
|
|
|
|
function setURL($url)
|
|
{
|
|
$this->_url = new Net_URL($url, $this->_useBrackets);
|
|
|
|
if (!empty($this->_url->user) || !empty($this->_url->pass)) {
|
|
$this->setBasicAuth($this->_url->user, $this->_url->pass);
|
|
}
|
|
|
|
if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) {
|
|
$this->addHeader('Host', $this->_generateHostHeader());
|
|
}
|
|
}
|
|
|
|
function setProxy($host, $port = 8080, $user = null, $pass = null)
|
|
{
|
|
$this->_proxy_host = $host;
|
|
$this->_proxy_port = $port;
|
|
$this->_proxy_user = $user;
|
|
$this->_proxy_pass = $pass;
|
|
|
|
if (!empty($user)) {
|
|
$this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
|
|
}
|
|
}
|
|
|
|
function setBasicAuth($user, $pass)
|
|
{
|
|
$this->_user = $user;
|
|
$this->_pass = $pass;
|
|
|
|
$this->addHeader('Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
|
|
}
|
|
|
|
function setMethod($method)
|
|
{
|
|
$this->_method = $method;
|
|
}
|
|
|
|
function setHttpVer($http)
|
|
{
|
|
$this->_http = $http;
|
|
}
|
|
|
|
function addHeader($name, $value)
|
|
{
|
|
$this->_requestHeaders[strtolower($name)] = $value;
|
|
}
|
|
|
|
function removeHeader($name)
|
|
{
|
|
if (isset($this->_requestHeaders[strtolower($name)])) {
|
|
unset($this->_requestHeaders[strtolower($name)]);
|
|
}
|
|
}
|
|
|
|
function addQueryString($name, $value, $preencoded = false)
|
|
{
|
|
$this->_url->addQueryString($name, $value, $preencoded);
|
|
}
|
|
|
|
function addRawQueryString($querystring, $preencoded = true)
|
|
{
|
|
$this->_url->addRawQueryString($querystring, $preencoded);
|
|
}
|
|
|
|
function addPostData($name, $value, $preencoded = false)
|
|
{
|
|
if ($preencoded) {
|
|
$this->_postData[$name] = $value;
|
|
} else {
|
|
$this->_postData[$name] = $this->_arrayMapRecursive('urlencode', $value);
|
|
}
|
|
}
|
|
|
|
function _arrayMapRecursive($callback, $value)
|
|
{
|
|
if (!is_array($value)) {
|
|
return call_user_func($callback, $value);
|
|
} else {
|
|
$map = array();
|
|
foreach ($value as $k => $v) {
|
|
$map[$k] = $this->_arrayMapRecursive($callback, $v);
|
|
}
|
|
return $map;
|
|
}
|
|
}
|
|
|
|
function addFile($inputName, $fileName, $contentType = 'application/octet-stream')
|
|
{
|
|
if (!is_array($fileName) && !is_readable($fileName)) {
|
|
return PEAR::raiseError("File '{$fileName}' is not readable");
|
|
} elseif (is_array($fileName)) {
|
|
foreach ($fileName as $name) {
|
|
if (!is_readable($name)) {
|
|
return PEAR::raiseError("File '{$name}' is not readable");
|
|
}
|
|
}
|
|
}
|
|
$this->addHeader('Content-Type', 'multipart/form-data');
|
|
$this->_postFiles[$inputName] = array(
|
|
'name' => $fileName,
|
|
'type' => $contentType
|
|
);
|
|
return true;
|
|
}
|
|
|
|
function addRawPostData($postdata, $preencoded = true)
|
|
{
|
|
$this->_body = $preencoded ? $postdata : urlencode($postdata);
|
|
}
|
|
|
|
function setBody($body)
|
|
{
|
|
$this->_body = $body;
|
|
}
|
|
|
|
function clearPostData()
|
|
{
|
|
$this->_postData = null;
|
|
}
|
|
|
|
function addCookie($name, $value)
|
|
{
|
|
$cookies = isset($this->_requestHeaders['cookie']) ? $this->_requestHeaders['cookie']. '; ' : '';
|
|
$this->addHeader('Cookie', $cookies . $name . '=' . $value);
|
|
}
|
|
|
|
function clearCookies()
|
|
{
|
|
$this->removeHeader('Cookie');
|
|
}
|
|
|
|
function sendRequest($saveBody = true)
|
|
{
|
|
if (!is_a($this->_url, 'Net_URL')) {
|
|
return PEAR::raiseError('No URL given.');
|
|
}
|
|
|
|
$host = isset($this->_proxy_host) ? $this->_proxy_host : $this->_url->host;
|
|
$port = isset($this->_proxy_port) ? $this->_proxy_port : $this->_url->port;
|
|
|
|
if (strcasecmp($this->_url->protocol, 'https') == 0 AND function_exists('file_get_contents') AND extension_loaded('openssl')) {
|
|
if (isset($this->_proxy_host)) {
|
|
return PEAR::raiseError('HTTPS proxies are not supported.');
|
|
}
|
|
$host = 'ssl://' . $host;
|
|
}
|
|
|
|
$magicQuotes = ini_get('magic_quotes_runtime');
|
|
ini_set('magic_quotes_runtime', false);
|
|
|
|
$err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions);
|
|
PEAR::isError($err) or $err = $this->_sock->write($this->_buildRequest());
|
|
|
|
if (!PEAR::isError($err)) {
|
|
if (!empty($this->_readTimeout)) {
|
|
$this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]);
|
|
}
|
|
|
|
$this->_notify('sentRequest');
|
|
|
|
$this->_response = new HTTP_Response($this->_sock, $this->_listeners);
|
|
$err = $this->_response->process($this->_saveBody && $saveBody);
|
|
}
|
|
|
|
ini_set('magic_quotes_runtime', $magicQuotes);
|
|
|
|
if (PEAR::isError($err)) {
|
|
return $err;
|
|
}
|
|
|
|
if ( $this->_allowRedirects
|
|
AND $this->_redirects <= $this->_maxRedirects
|
|
AND $this->getResponseCode() > 300
|
|
AND $this->getResponseCode() < 399
|
|
AND !empty($this->_response->_headers['location'])) {
|
|
|
|
$redirect = $this->_response->_headers['location'];
|
|
|
|
// Absolute URL
|
|
if (preg_match('/^https?:\/\//i', $redirect)) {
|
|
$this->_url = new Net_URL($redirect);
|
|
$this->addHeader('Host', $this->_generateHostHeader());
|
|
// Absolute path
|
|
} elseif ($redirect{0} == '/') {
|
|
$this->_url->path = $redirect;
|
|
|
|
// Relative path
|
|
} elseif (substr($redirect, 0, 3) == '../' OR substr($redirect, 0, 2) == './') {
|
|
if (substr($this->_url->path, -1) == '/') {
|
|
$redirect = $this->_url->path . $redirect;
|
|
} else {
|
|
$redirect = dirname($this->_url->path) . '/' . $redirect;
|
|
}
|
|
$redirect = Net_URL::resolvePath($redirect);
|
|
$this->_url->path = $redirect;
|
|
|
|
} else {
|
|
if (substr($this->_url->path, -1) == '/') {
|
|
$redirect = $this->_url->path . $redirect;
|
|
} else {
|
|
$redirect = dirname($this->_url->path) . '/' . $redirect;
|
|
}
|
|
$this->_url->path = $redirect;
|
|
}
|
|
|
|
$this->_redirects++;
|
|
return $this->sendRequest($saveBody);
|
|
|
|
} elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) {
|
|
return PEAR::raiseError('Too many redirects');
|
|
}
|
|
|
|
$this->_sock->disconnect();
|
|
|
|
return true;
|
|
}
|
|
|
|
function getResponseCode()
|
|
{
|
|
return isset($this->_response->_code) ? $this->_response->_code : false;
|
|
}
|
|
|
|
function getResponseHeader($headername = null)
|
|
{
|
|
if (!isset($headername)) {
|
|
return isset($this->_response->_headers)? $this->_response->_headers: array();
|
|
} else {
|
|
$headername = strtolower($headername);
|
|
return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false;
|
|
}
|
|
}
|
|
|
|
function getResponseBody()
|
|
{
|
|
return isset($this->_response->_body) ? $this->_response->_body : false;
|
|
}
|
|
|
|
function getResponseCookies()
|
|
{
|
|
return isset($this->_response->_cookies) ? $this->_response->_cookies : false;
|
|
}
|
|
|
|
function _buildRequest()
|
|
{
|
|
$separator = ini_get('arg_separator.output');
|
|
ini_set('arg_separator.output', '&');
|
|
$querystring = ($querystring = $this->_url->getQueryString()) ? '?' . $querystring : '';
|
|
ini_set('arg_separator.output', $separator);
|
|
|
|
$host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : '';
|
|
$port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : '';
|
|
$path = (empty($this->_url->path)? '/': $this->_url->path) . $querystring;
|
|
$url = $host . $port . $path;
|
|
|
|
$request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n";
|
|
|
|
if (in_array($this->_method, $this->_bodyDisallowed) ||
|
|
(HTTP_REQUEST_METHOD_POST != $this->_method && empty($this->_body)) ||
|
|
(HTTP_REQUEST_METHOD_POST != $this->_method && empty($this->_postData) && empty($this->_postFiles))) {
|
|
|
|
$this->removeHeader('Content-Type');
|
|
} else {
|
|
if (empty($this->_requestHeaders['content-type'])) {
|
|
$this->addHeader('Content-Type', 'application/x-www-form-urlencoded');
|
|
} elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) {
|
|
$boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime());
|
|
$this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary);
|
|
}
|
|
}
|
|
|
|
if (!empty($this->_requestHeaders)) {
|
|
foreach ($this->_requestHeaders as $name => $value) {
|
|
$canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
|
|
$request .= $canonicalName . ': ' . $value . "\r\n";
|
|
}
|
|
}
|
|
|
|
if (in_array($this->_method, $this->_bodyDisallowed) ||
|
|
(HTTP_REQUEST_METHOD_POST != $this->_method && empty($this->_body))) {
|
|
|
|
$request .= "\r\n";
|
|
|
|
} elseif (HTTP_REQUEST_METHOD_POST == $this->_method &&
|
|
(!empty($this->_postData) || !empty($this->_postFiles))) {
|
|
|
|
if (!isset($boundary)) {
|
|
$postdata = implode('&', array_map(
|
|
create_function('$a', 'return $a[0] . \'=\' . $a[1];'),
|
|
$this->_flattenArray('', $this->_postData)
|
|
));
|
|
|
|
} else {
|
|
$postdata = '';
|
|
if (!empty($this->_postData)) {
|
|
$flatData = $this->_flattenArray('', $this->_postData);
|
|
foreach ($flatData as $item) {
|
|
$postdata .= '--' . $boundary . "\r\n";
|
|
$postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"';
|
|
$postdata .= "\r\n\r\n" . urldecode($item[1]) . "\r\n";
|
|
}
|
|
}
|
|
foreach ($this->_postFiles as $name => $value) {
|
|
if (is_array($value['name'])) {
|
|
$varname = $name . ($this->_useBrackets? '[]': '');
|
|
} else {
|
|
$varname = $name;
|
|
$value['name'] = array($value['name']);
|
|
}
|
|
foreach ($value['name'] as $key => $filename) {
|
|
$fp = fopen($filename, 'r');
|
|
$data = fread($fp, filesize($filename));
|
|
fclose($fp);
|
|
$basename = basename($filename);
|
|
$type = is_array($value['type'])? @$value['type'][$key]: $value['type'];
|
|
|
|
$postdata .= '--' . $boundary . "\r\n";
|
|
$postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"';
|
|
$postdata .= "\r\nContent-Type: " . $type;
|
|
$postdata .= "\r\n\r\n" . $data . "\r\n";
|
|
}
|
|
}
|
|
$postdata .= '--' . $boundary . "--\r\n";
|
|
}
|
|
$request .= 'Content-Length: ' . strlen($postdata) . "\r\n\r\n";
|
|
$request .= $postdata;
|
|
|
|
// Explicitly set request body
|
|
} elseif (!empty($this->_body)) {
|
|
|
|
$request .= 'Content-Length: ' . strlen($this->_body) . "\r\n\r\n";
|
|
$request .= $this->_body;
|
|
}
|
|
|
|
return $request;
|
|
}
|
|
|
|
function _flattenArray($name, $values)
|
|
{
|
|
if (!is_array($values)) {
|
|
return array(array($name, $values));
|
|
} else {
|
|
$ret = array();
|
|
foreach ($values as $k => $v) {
|
|
if (empty($name)) {
|
|
$newName = $k;
|
|
} elseif ($this->_useBrackets) {
|
|
$newName = $name . '[' . $k . ']';
|
|
} else {
|
|
$newName = $name;
|
|
}
|
|
$ret = array_merge($ret, $this->_flattenArray($newName, $v));
|
|
}
|
|
return $ret;
|
|
}
|
|
}
|
|
|
|
function attach(&$listener)
|
|
{
|
|
if (!is_a($listener, 'HTTP_Request_Listener')) {
|
|
return false;
|
|
}
|
|
$this->_listeners[$listener->getId()] =& $listener;
|
|
return true;
|
|
}
|
|
|
|
function detach(&$listener)
|
|
{
|
|
if (!is_a($listener, 'HTTP_Request_Listener') ||
|
|
!isset($this->_listeners[$listener->getId()])) {
|
|
return false;
|
|
}
|
|
unset($this->_listeners[$listener->getId()]);
|
|
return true;
|
|
}
|
|
|
|
function _notify($event, $data = null)
|
|
{
|
|
foreach (array_keys($this->_listeners) as $id) {
|
|
$this->_listeners[$id]->update($this, $event, $data);
|
|
}
|
|
}
|
|
}
|
|
|
|
class HTTP_Response
|
|
{
|
|
|
|
var $_sock;
|
|
var $_protocol;
|
|
var $_code;
|
|
var $_headers;
|
|
var $_cookies;
|
|
var $_body = '';
|
|
var $_chunkLength = 0;
|
|
var $_listeners = array();
|
|
function HTTP_Response(&$sock, &$listeners)
|
|
{
|
|
$this->_sock =& $sock;
|
|
$this->_listeners =& $listeners;
|
|
}
|
|
|
|
function process($saveBody = true)
|
|
{
|
|
do {
|
|
$line = $this->_sock->readLine();
|
|
if (sscanf($line, 'HTTP/%s %s', $http_version, $returncode) != 2) {
|
|
return PEAR::raiseError('Malformed response.');
|
|
} else {
|
|
$this->_protocol = 'HTTP/' . $http_version;
|
|
$this->_code = intval($returncode);
|
|
}
|
|
while ('' !== ($header = $this->_sock->readLine())) {
|
|
$this->_processHeader($header);
|
|
}
|
|
} while (100 == $this->_code);
|
|
|
|
$this->_notify('gotHeaders', $this->_headers);
|
|
|
|
$chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']);
|
|
$gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']);
|
|
$hasBody = false;
|
|
if (!isset($this->_headers['content-length']) || 0 != $this->_headers['content-length']) {
|
|
while (!$this->_sock->eof()) {
|
|
if ($chunked) {
|
|
$data = $this->_readChunked();
|
|
} else {
|
|
$data = $this->_sock->read(4096);
|
|
}
|
|
if ('' == $data) {
|
|
break;
|
|
} else {
|
|
$hasBody = true;
|
|
if ($saveBody || $gzipped) {
|
|
$this->_body .= $data;
|
|
}
|
|
$this->_notify($gzipped? 'gzTick': 'tick', $data);
|
|
}
|
|
}
|
|
}
|
|
if ($hasBody) {
|
|
if ($gzipped) {
|
|
$this->_body = gzinflate(substr($this->_body, 10));
|
|
$this->_notify('gotBody', $this->_body);
|
|
} else {
|
|
$this->_notify('gotBody');
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function _processHeader($header)
|
|
{
|
|
list($headername, $headervalue) = explode(':', $header, 2);
|
|
$headername = strtolower($headername);
|
|
$headervalue = ltrim($headervalue);
|
|
|
|
if ('set-cookie' != $headername) {
|
|
if (isset($this->_headers[$headername])) {
|
|
$this->_headers[$headername] .= ',' . $headervalue;
|
|
} else {
|
|
$this->_headers[$headername] = $headervalue;
|
|
}
|
|
} else {
|
|
$this->_parseCookie($headervalue);
|
|
}
|
|
}
|
|
|
|
function _parseCookie($headervalue)
|
|
{
|
|
$cookie = array(
|
|
'expires' => null,
|
|
'domain' => null,
|
|
'path' => null,
|
|
'secure' => false
|
|
);
|
|
|
|
if (!strpos($headervalue, ';')) {
|
|
$pos = strpos($headervalue, '=');
|
|
$cookie['name'] = trim(substr($headervalue, 0, $pos));
|
|
$cookie['value'] = trim(substr($headervalue, $pos + 1));
|
|
|
|
} else {
|
|
$elements = explode(';', $headervalue);
|
|
$pos = strpos($elements[0], '=');
|
|
$cookie['name'] = trim(substr($elements[0], 0, $pos));
|
|
$cookie['value'] = trim(substr($elements[0], $pos + 1));
|
|
|
|
for ($i = 1; $i < count($elements); $i++) {
|
|
if (false === strpos($elements[$i], '=')) {
|
|
$elName = trim($elements[$i]);
|
|
$elValue = null;
|
|
} else {
|
|
list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i]));
|
|
}
|
|
$elName = strtolower($elName);
|
|
if ('secure' == $elName) {
|
|
$cookie['secure'] = true;
|
|
} elseif ('expires' == $elName) {
|
|
$cookie['expires'] = str_replace('"', '', $elValue);
|
|
} elseif ('path' == $elName || 'domain' == $elName) {
|
|
$cookie[$elName] = urldecode($elValue);
|
|
} else {
|
|
$cookie[$elName] = $elValue;
|
|
}
|
|
}
|
|
}
|
|
$this->_cookies[] = $cookie;
|
|
}
|
|
|
|
function _readChunked()
|
|
{
|
|
if (0 == $this->_chunkLength) {
|
|
$line = $this->_sock->readLine();
|
|
if (preg_match('/^([0-9a-f]+)/i', $line, $matches)) {
|
|
$this->_chunkLength = hexdec($matches[1]);
|
|
if (0 == $this->_chunkLength) {
|
|
$this->_sock->readLine();
|
|
return '';
|
|
}
|
|
} else {
|
|
return '';
|
|
}
|
|
}
|
|
$data = $this->_sock->read($this->_chunkLength);
|
|
$this->_chunkLength -= strlen($data);
|
|
if (0 == $this->_chunkLength) {
|
|
$this->_sock->readLine();
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
function _notify($event, $data = null)
|
|
{
|
|
foreach (array_keys($this->_listeners) as $id) {
|
|
$this->_listeners[$id]->update($this, $event, $data);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Socket.php
|
|
*/
|
|
|
|
// +----------------------------------------------------------------------+
|
|
// | PHP Version 4 |
|
|
// +----------------------------------------------------------------------+
|
|
// | Copyright (c) 1997-2003 The PHP Group |
|
|
// +----------------------------------------------------------------------+
|
|
// | This source file is subject to version 2.0 of the PHP license, |
|
|
// | that is bundled with this package in the file LICENSE, and is |
|
|
// | available at through the world-wide-web at |
|
|
// | http://www.php.net/license/2_02.txt. |
|
|
// | If you did not receive a copy of the PHP license and are unable to |
|
|
// | obtain it through the world-wide-web, please send a note to |
|
|
// | license@php.net so we can mail you a copy immediately. |
|
|
// +----------------------------------------------------------------------+
|
|
// | Authors: Stig Bakken <ssb@php.net> |
|
|
// | Chuck Hagenbuch <chuck@horde.org> |
|
|
// +----------------------------------------------------------------------+
|
|
//
|
|
// $Id: Socket.php,v 1.24 2005/02/03 20:40:16 chagenbu Exp $
|
|
|
|
|
|
define('NET_SOCKET_READ', 1);
|
|
define('NET_SOCKET_WRITE', 2);
|
|
define('NET_SOCKET_ERROR', 3);
|
|
|
|
class Net_Socket extends PEAR {
|
|
|
|
var $fp = null;
|
|
var $blocking = true;
|
|
var $persistent = false;
|
|
var $addr = '';
|
|
var $port = 0;
|
|
var $timeout = false;
|
|
var $lineLength = 2048;
|
|
|
|
function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null)
|
|
{
|
|
if (is_resource($this->fp)) {
|
|
@fclose($this->fp);
|
|
$this->fp = null;
|
|
}
|
|
|
|
if (!$addr) {
|
|
return $this->raiseError('$addr cannot be empty');
|
|
} elseif (strspn($addr, '.0123456789') == strlen($addr) ||
|
|
strstr($addr, '/') !== false) {
|
|
$this->addr = $addr;
|
|
} else {
|
|
$this->addr = @gethostbyname($addr);
|
|
}
|
|
|
|
$this->port = $port % 65536;
|
|
|
|
if ($persistent !== null) {
|
|
$this->persistent = $persistent;
|
|
}
|
|
|
|
if ($timeout !== null) {
|
|
$this->timeout = $timeout;
|
|
}
|
|
|
|
$openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
|
|
$errno = 0;
|
|
$errstr = '';
|
|
if ($options && function_exists('stream_context_create')) {
|
|
if ($this->timeout) {
|
|
$timeout = $this->timeout;
|
|
} else {
|
|
$timeout = 0;
|
|
}
|
|
$context = stream_context_create($options);
|
|
$fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context);
|
|
} else {
|
|
if ($this->timeout) {
|
|
$fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout);
|
|
} else {
|
|
$fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
|
|
}
|
|
}
|
|
|
|
if (!$fp) {
|
|
return $this->raiseError($errstr, $errno);
|
|
}
|
|
|
|
$this->fp = $fp;
|
|
|
|
return $this->setBlocking($this->blocking);
|
|
}
|
|
|
|
function disconnect()
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
@fclose($this->fp);
|
|
$this->fp = null;
|
|
return true;
|
|
}
|
|
|
|
function isBlocking()
|
|
{
|
|
return $this->blocking;
|
|
}
|
|
|
|
function setBlocking($mode)
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
$this->blocking = $mode;
|
|
socket_set_blocking($this->fp, $this->blocking);
|
|
return true;
|
|
}
|
|
|
|
function setTimeout($seconds, $microseconds)
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
return socket_set_timeout($this->fp, $seconds, $microseconds);
|
|
}
|
|
|
|
function getStatus()
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
return socket_get_status($this->fp);
|
|
}
|
|
|
|
function gets($size)
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
return @fgets($this->fp, $size);
|
|
}
|
|
|
|
function read($size)
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
return @fread($this->fp, $size);
|
|
}
|
|
|
|
function write($data, $blocksize = null)
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
if (is_null($blocksize) && !OS_WINDOWS) {
|
|
return fwrite($this->fp, $data);
|
|
} else {
|
|
if (is_null($blocksize)) {
|
|
$blocksize = 1024;
|
|
}
|
|
|
|
$pos = 0;
|
|
$size = strlen($data);
|
|
while ($pos < $size) {
|
|
$written = @fwrite($this->fp, substr($data, $pos, $blocksize));
|
|
if ($written === false) {
|
|
return false;
|
|
}
|
|
$pos += $written;
|
|
}
|
|
|
|
return $pos;
|
|
}
|
|
}
|
|
|
|
function writeLine($data)
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
return fwrite($this->fp, $data . "\r\n");
|
|
}
|
|
|
|
function eof()
|
|
{
|
|
return (is_resource($this->fp) && feof($this->fp));
|
|
}
|
|
|
|
function readByte()
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
return ord(@fread($this->fp, 1));
|
|
}
|
|
|
|
function readWord()
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
$buf = @fread($this->fp, 2);
|
|
return (ord($buf[0]) + (ord($buf[1]) << 8));
|
|
}
|
|
|
|
function readInt()
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
$buf = @fread($this->fp, 4);
|
|
return (ord($buf[0]) + (ord($buf[1]) << 8) +
|
|
(ord($buf[2]) << 16) + (ord($buf[3]) << 24));
|
|
}
|
|
|
|
function readString()
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
$string = '';
|
|
while (($char = @fread($this->fp, 1)) != "\x00") {
|
|
$string .= $char;
|
|
}
|
|
return $string;
|
|
}
|
|
|
|
function readIPAddress()
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
$buf = @fread($this->fp, 4);
|
|
return sprintf("%s.%s.%s.%s", ord($buf[0]), ord($buf[1]),
|
|
ord($buf[2]), ord($buf[3]));
|
|
}
|
|
|
|
function readLine()
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
$line = '';
|
|
$timeout = time() + $this->timeout;
|
|
while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
|
|
$line .= @fgets($this->fp, $this->lineLength);
|
|
if (substr($line, -1) == "\n") {
|
|
return rtrim($line, "\r\n");
|
|
}
|
|
}
|
|
return $line;
|
|
}
|
|
|
|
function readAll()
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
$data = '';
|
|
while (!feof($this->fp)) {
|
|
$data .= @fread($this->fp, $this->lineLength);
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
function select($state, $tv_sec, $tv_usec = 0)
|
|
{
|
|
if (!is_resource($this->fp)) {
|
|
return $this->raiseError('not connected');
|
|
}
|
|
|
|
$read = null;
|
|
$write = null;
|
|
$except = null;
|
|
if ($state & NET_SOCKET_READ) {
|
|
$read[] = $this->fp;
|
|
}
|
|
if ($state & NET_SOCKET_WRITE) {
|
|
$write[] = $this->fp;
|
|
}
|
|
if ($state & NET_SOCKET_ERROR) {
|
|
$except[] = $this->fp;
|
|
}
|
|
if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) {
|
|
return false;
|
|
}
|
|
|
|
$result = 0;
|
|
if (count($read)) {
|
|
$result |= NET_SOCKET_READ;
|
|
}
|
|
if (count($write)) {
|
|
$result |= NET_SOCKET_WRITE;
|
|
}
|
|
if (count($except)) {
|
|
$result |= NET_SOCKET_ERROR;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* URL.php
|
|
*/
|
|
// +-----------------------------------------------------------------------+
|
|
// | Copyright (c) 2002-2004, Richard Heyes |
|
|
// | All rights reserved. |
|
|
// +-----------------------------------------------------------------------+
|
|
// $Id: URL.php,v 1.36 2004/06/19 18:58:50 richard Exp $
|
|
|
|
class Net_URL
|
|
{
|
|
|
|
var $url;
|
|
var $protocol;
|
|
var $username;
|
|
var $password;
|
|
var $host;
|
|
var $port;
|
|
var $path;
|
|
var $querystring;
|
|
var $anchor;
|
|
var $useBrackets;
|
|
function Net_URL($url = null, $useBrackets = true)
|
|
{
|
|
$this->__construct($url, $useBrackets);
|
|
}
|
|
|
|
function __construct($url = null, $useBrackets = true)
|
|
{
|
|
$HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
|
|
|
|
$this->useBrackets = $useBrackets;
|
|
$this->url = $url;
|
|
$this->user = '';
|
|
$this->pass = '';
|
|
$this->host = '';
|
|
$this->port = 80;
|
|
$this->path = '';
|
|
$this->querystring = array();
|
|
$this->anchor = '';
|
|
|
|
if (!preg_match('/^[a-z0-9]+:\/\//i', $url)) {
|
|
|
|
$this->protocol = (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 'https' : 'http');
|
|
|
|
if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) AND preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) {
|
|
$host = $matches[1];
|
|
if (!empty($matches[3])) {
|
|
$port = $matches[3];
|
|
} else {
|
|
$port = $this->getStandardPort($this->protocol);
|
|
}
|
|
}
|
|
|
|
$this->user = '';
|
|
$this->pass = '';
|
|
$this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
|
|
$this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
|
|
$this->path = !empty($HTTP_SERVER_VARS['SCRIPT_NAME']) ? $HTTP_SERVER_VARS['SCRIPT_NAME'] : '/';
|
|
$this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
|
|
$this->anchor = '';
|
|
}
|
|
|
|
if (!empty($url)) {
|
|
$urlinfo = parse_url($url);
|
|
|
|
$this->querystring = array();
|
|
|
|
foreach ($urlinfo as $key => $value) {
|
|
switch ($key) {
|
|
case 'scheme':
|
|
$this->protocol = $value;
|
|
$this->port = $this->getStandardPort($value);
|
|
break;
|
|
|
|
case 'user':
|
|
case 'pass':
|
|
case 'host':
|
|
case 'port':
|
|
$this->$key = $value;
|
|
break;
|
|
|
|
case 'path':
|
|
if ($value{0} == '/') {
|
|
$this->path = $value;
|
|
} else {
|
|
$path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
|
|
$this->path = sprintf('%s/%s', $path, $value);
|
|
}
|
|
break;
|
|
|
|
case 'query':
|
|
$this->querystring = $this->_parseRawQueryString($value);
|
|
break;
|
|
|
|
case 'fragment':
|
|
$this->anchor = $value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function getURL()
|
|
{
|
|
$querystring = $this->getQueryString();
|
|
|
|
$this->url = $this->protocol . '://'
|
|
. $this->user . (!empty($this->pass) ? ':' : '')
|
|
. $this->pass . (!empty($this->user) ? '@' : '')
|
|
. $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
|
|
. $this->path
|
|
. (!empty($querystring) ? '?' . $querystring : '')
|
|
. (!empty($this->anchor) ? '#' . $this->anchor : '');
|
|
|
|
return $this->url;
|
|
}
|
|
|
|
function addQueryString($name, $value, $preencoded = false)
|
|
{
|
|
if ($preencoded) {
|
|
$this->querystring[$name] = $value;
|
|
} else {
|
|
$this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);
|
|
}
|
|
}
|
|
|
|
function removeQueryString($name)
|
|
{
|
|
if (isset($this->querystring[$name])) {
|
|
unset($this->querystring[$name]);
|
|
}
|
|
}
|
|
|
|
function addRawQueryString($querystring)
|
|
{
|
|
$this->querystring = $this->_parseRawQueryString($querystring);
|
|
}
|
|
|
|
function getQueryString()
|
|
{
|
|
if (!empty($this->querystring)) {
|
|
foreach ($this->querystring as $name => $value) {
|
|
if (is_array($value)) {
|
|
foreach ($value as $k => $v) {
|
|
$querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
|
|
}
|
|
} elseif (!is_null($value)) {
|
|
$querystring[] = $name . '=' . $value;
|
|
} else {
|
|
$querystring[] = $name;
|
|
}
|
|
}
|
|
$querystring = implode(ini_get('arg_separator.output'), $querystring);
|
|
} else {
|
|
$querystring = '';
|
|
}
|
|
|
|
return $querystring;
|
|
}
|
|
|
|
function _parseRawQuerystring($querystring)
|
|
{
|
|
$parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
|
|
$return = array();
|
|
|
|
foreach ($parts as $part) {
|
|
if (strpos($part, '=') !== false) {
|
|
$value = substr($part, strpos($part, '=') + 1);
|
|
$key = substr($part, 0, strpos($part, '='));
|
|
} else {
|
|
$value = null;
|
|
$key = $part;
|
|
}
|
|
if (substr($key, -2) == '[]') {
|
|
$key = substr($key, 0, -2);
|
|
if (@!is_array($return[$key])) {
|
|
$return[$key] = array();
|
|
$return[$key][] = $value;
|
|
} else {
|
|
$return[$key][] = $value;
|
|
}
|
|
} elseif (!$this->useBrackets AND !empty($return[$key])) {
|
|
$return[$key] = (array)$return[$key];
|
|
$return[$key][] = $value;
|
|
} else {
|
|
$return[$key] = $value;
|
|
}
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
function resolvePath($path)
|
|
{
|
|
$path = explode('/', str_replace('//', '/', $path));
|
|
|
|
for ($i=0; $i<count($path); $i++) {
|
|
if ($path[$i] == '.') {
|
|
unset($path[$i]);
|
|
$path = array_values($path);
|
|
$i--;
|
|
|
|
} elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {
|
|
unset($path[$i]);
|
|
unset($path[$i-1]);
|
|
$path = array_values($path);
|
|
$i -= 2;
|
|
|
|
} elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
|
|
unset($path[$i]);
|
|
$path = array_values($path);
|
|
$i--;
|
|
|
|
} else {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return implode('/', $path);
|
|
}
|
|
|
|
function getStandardPort($scheme)
|
|
{
|
|
switch (strtolower($scheme)) {
|
|
case 'http': return 80;
|
|
case 'https': return 443;
|
|
case 'ftp': return 21;
|
|
case 'imap': return 143;
|
|
case 'imaps': return 993;
|
|
case 'pop3': return 110;
|
|
case 'pop3s': return 995;
|
|
default: return null;
|
|
}
|
|
}
|
|
|
|
function setProtocol($protocol, $port = null)
|
|
{
|
|
$this->protocol = $protocol;
|
|
$this->port = is_null($port) ? $this->getStandardPort() : $port;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
?>
|