diff --git a/composer.json b/composer.json index ccde4f890e..a2911726e9 100644 --- a/composer.json +++ b/composer.json @@ -41,6 +41,8 @@ "nanasess/php8-compat": "^1.0", "pear/archive_tar": "^1.4.3", "pear/mail": "*", + "pear/net_smtp": "^1.12", + "pear/net_socket": "^1.2", "pear/pear-core-minimal": "^1.10", "pear/xml_parser": "*", "pear/xml_serializer": "*", diff --git a/composer.lock b/composer.lock index 498aadbf86..4776063e81 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "913b3fad812f8e13e42e3d0e9cbb40d3", + "content-hash": "61103d3a54c8391d2c0c246e909f46f5", "packages": [ { "name": "mobiledetect/mobiledetectlib", @@ -348,6 +348,132 @@ }, "time": "2024-01-15T21:56:23+00:00" }, + { + "name": "pear/net_smtp", + "version": "1.12.1", + "source": { + "type": "git", + "url": "https://github.com/pear/Net_SMTP.git", + "reference": "5d7ba854d75a7c207d8581de1cc6fd2895ae2518" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pear/Net_SMTP/zipball/5d7ba854d75a7c207d8581de1cc6fd2895ae2518", + "reference": "5d7ba854d75a7c207d8581de1cc6fd2895ae2518", + "shasum": "" + }, + "require": { + "pear/net_socket": "@stable", + "pear/pear-core-minimal": "@stable", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "pear/auth_sasl": "Install optionally via your project's composer.json" + }, + "type": "library", + "autoload": { + "psr-0": { + "Net": "./" + } + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "./" + ], + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jon Parise", + "email": "jon@php.net", + "homepage": "https://www.indelible.org", + "role": "Lead" + }, + { + "name": "Chuck Hagenbuch", + "email": "chuck@horde.org", + "role": "Lead" + }, + { + "name": "Armin Graefe", + "email": "schengawegga@gmail.com", + "role": "Lead" + } + ], + "description": "An implementation of the SMTP protocol", + "homepage": "https://pear.github.io/Net_SMTP/", + "keywords": [ + "email", + "mail", + "smtp" + ], + "support": { + "issues": "https://github.com/pear/Net_SMTP/issues", + "source": "https://github.com/pear/Net_SMTP" + }, + "time": "2024-04-15T19:42:15+00:00" + }, + { + "name": "pear/net_socket", + "version": "v1.2.2", + "source": { + "type": "git", + "url": "https://github.com/pear/Net_Socket.git", + "reference": "bbe6a12bb4f7059dba161f6ddd43f369c0ec8d09" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pear/Net_Socket/zipball/bbe6a12bb4f7059dba161f6ddd43f369c0ec8d09", + "reference": "bbe6a12bb4f7059dba161f6ddd43f369c0ec8d09", + "shasum": "" + }, + "require": { + "pear/pear_exception": "*" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Net": "./" + } + }, + "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "./" + ], + "license": [ + "PHP License" + ], + "authors": [ + { + "name": "Chuck Hagenbuch", + "email": "chuck@horde.org", + "role": "Lead" + }, + { + "name": "Aleksander Machniak", + "email": "alec@php.net", + "role": "Lead" + }, + { + "name": "Stig Bakken", + "email": "stig@php.net", + "role": "Lead" + } + ], + "description": "More info available on: http://pear.php.net/package/Net_Socket", + "support": { + "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Net_Socket", + "source": "https://github.com/pear/Net_Socket" + }, + "time": "2015-03-22T15:48:19+00:00" + }, { "name": "pear/pear-core-minimal", "version": "v1.10.15", @@ -5715,5 +5841,5 @@ "platform-overrides": { "php": "7.4.0" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.0.0" } diff --git a/data/module/Net/SMTP.php b/data/module/Net/SMTP.php deleted file mode 100644 index cc043618c6..0000000000 --- a/data/module/Net/SMTP.php +++ /dev/null @@ -1,1210 +0,0 @@ - | -// | Jon Parise | -// | Damian Alejandro Fernandez Sosa | -// +----------------------------------------------------------------------+ -// -// $Id: SMTP.php 304535 2010-10-20 06:48:06Z jon $ - -require_once 'PEAR.php'; -require_once 'Net/Socket.php'; - -/** - * Provides an implementation of the SMTP protocol using PEAR's - * Net_Socket:: class. - * - * @author Chuck Hagenbuch - * @author Jon Parise - * @author Damian Alejandro Fernandez Sosa - * - * @example basic.php A basic implementation of the Net_SMTP package. - */ -class Net_SMTP -{ - /** - * The server to connect to. - * - * @var string - */ - public $host = 'localhost'; - - /** - * The port to connect to. - * - * @var int - */ - public $port = 25; - - /** - * The value to give when sending EHLO or HELO. - * - * @var string - */ - public $localhost = 'localhost'; - - /** - * List of supported authentication methods, in preferential order. - * - * @var array - */ - public $auth_methods = ['DIGEST-MD5', 'CRAM-MD5', 'LOGIN', 'PLAIN']; - - /** - * Use SMTP command pipelining (specified in RFC 2920) if the SMTP - * server supports it. - * - * When pipeling is enabled, rcptTo(), mailFrom(), sendFrom(), - * somlFrom() and samlFrom() do not wait for a response from the - * SMTP server but return immediately. - * - * @var bool - */ - public $pipelining = false; - - /** - * Number of pipelined commands. - * - * @var int - */ - public $_pipelined_commands = 0; - - /** - * Should debugging output be enabled? - * - * @var bool - */ - public $_debug = false; - - /** - * Debug output handler. - * - * @var callable - */ - public $_debug_handler = null; - - /** - * The socket resource being used to connect to the SMTP server. - * - * @var resource - */ - public $_socket = null; - - /** - * The most recent server response code. - * - * @var int - */ - public $_code = -1; - - /** - * The most recent server response arguments. - * - * @var array - */ - public $_arguments = []; - - /** - * Stores the SMTP server's greeting string. - * - * @var string - */ - public $_greeting = null; - - /** - * Stores detected features of the SMTP server. - * - * @var array - */ - public $_esmtp = []; - - /** - * Instantiates a new Net_SMTP object, overriding any defaults - * with parameters that are passed in. - * - * If you have SSL support in PHP, you can connect to a server - * over SSL using an 'ssl://' prefix: - * - * // 465 is a common smtps port. - * $smtp = new Net_SMTP('ssl://mail.host.com', 465); - * $smtp->connect(); - * - * @param string $host The server to connect to. - * @param int $port The port to connect to. - * @param string $localhost The value to give when sending EHLO or HELO. - * @param bool $pipeling Use SMTP command pipelining - * - * @since 1.0 - */ - public function __construct($host = null, $port = null, $localhost = null, $pipelining = false) - { - if (isset($host)) { - $this->host = $host; - } - if (isset($port)) { - $this->port = $port; - } - if (isset($localhost)) { - $this->localhost = $localhost; - } - $this->pipelining = $pipelining; - - $this->_socket = new Net_Socket(); - - /* Include the Auth_SASL package. If the package is not - * available, we disable the authentication methods that - * depend upon it. */ - if ((@include_once 'Auth/SASL.php') === false) { - $pos = array_search('DIGEST-MD5', $this->auth_methods); - unset($this->auth_methods[$pos]); - $pos = array_search('CRAM-MD5', $this->auth_methods); - unset($this->auth_methods[$pos]); - } - } - - /** - * Set the value of the debugging flag. - * - * @param bool $debug New value for the debugging flag. - * - * @since 1.1.0 - */ - public function setDebug($debug, $handler = null) - { - $this->_debug = $debug; - $this->_debug_handler = $handler; - } - - /** - * Write the given debug text to the current debug output handler. - * - * @param string $message Debug mesage text. - * - * @since 1.3.3 - */ - public function _debug($message) - { - if ($this->_debug) { - if ($this->_debug_handler) { - call_user_func_array($this->_debug_handler, - [&$this, $message]); - } else { - echo "DEBUG: $message\n"; - } - } - } - - /** - * Send the given string of data to the server. - * - * @param string $data The string of data to send. - * - * @return mixed True on success or a PEAR_Error object on failure. - * - * @since 1.1.0 - */ - public function _send($data) - { - $this->_debug("Send: $data"); - - $error = $this->_socket->write($data); - if ($error === false || PEAR::isError($error)) { - $msg = ($error) ? $error->getMessage() : 'unknown error'; - - return PEAR::raiseError("Failed to write to socket: $msg"); - } - - return true; - } - - /** - * Send a command to the server with an optional string of - * arguments. A carriage return / linefeed (CRLF) sequence will - * be appended to each command string before it is sent to the - * SMTP server - an error will be thrown if the command string - * already contains any newline characters. Use _send() for - * commands that must contain newlines. - * - * @param string $command The SMTP command to send to the server. - * @param string $args A string of optional arguments to append - * to the command. - * - * @return mixed The result of the _send() call. - * - * @since 1.1.0 - */ - public function _put($command, $args = '') - { - if (!empty($args)) { - $command .= ' '.$args; - } - - if (strcspn($command, "\r\n") !== strlen($command)) { - return PEAR::raiseError('Commands cannot contain newlines'); - } - - return $this->_send($command."\r\n"); - } - - /** - * Read a reply from the SMTP server. The reply consists of a response - * code and a response message. - * - * @param mixed $valid The set of valid response codes. These - * may be specified as an array of integer - * values or as a single integer value. - * @param bool $later Do not parse the response now, but wait - * until the last command in the pipelined - * command group - * - * @return mixed True if the server returned a valid response code or - * a PEAR_Error object is an error condition is reached. - * - * @since 1.1.0 - * @see getResponse - */ - public function _parseResponse($valid, $later = false) - { - $this->_code = -1; - $this->_arguments = []; - - if ($later) { - $this->_pipelined_commands++; - - return true; - } - - for ($i = 0; $i <= $this->_pipelined_commands; $i++) { - while ($line = $this->_socket->readLine()) { - $this->_debug("Recv: $line"); - - /* If we receive an empty line, the connection has been closed. */ - if (empty($line)) { - $this->disconnect(); - - return PEAR::raiseError('Connection was unexpectedly closed'); - } - - /* Read the code and store the rest in the arguments array. */ - $code = substr($line, 0, 3); - $this->_arguments[] = trim(substr($line, 4)); - - /* Check the syntax of the response code. */ - if (is_numeric($code)) { - $this->_code = (int) $code; - } else { - $this->_code = -1; - break; - } - - /* If this is not a multiline response, we're done. */ - if (substr($line, 3, 1) != '-') { - break; - } - } - } - - $this->_pipelined_commands = 0; - - /* Compare the server's response code with the valid code/codes. */ - if (is_int($valid) && ($this->_code === $valid)) { - return true; - } elseif (is_array($valid) && in_array($this->_code, $valid, true)) { - return true; - } - - return PEAR::raiseError('Invalid response code received from server', - $this->_code); - } - - /** - * Return a 2-tuple containing the last response from the SMTP server. - * - * @return array A two-element array: the first element contains the - * response code as an integer and the second element - * contains the response's arguments as a string. - * - * @since 1.1.0 - */ - public function getResponse() - { - return [$this->_code, implode("\n", $this->_arguments)]; - } - - /** - * Return the SMTP server's greeting string. - * - * @return string A string containing the greeting string, or null if a - * greeting has not been received. - * - * @since 1.3.3 - */ - public function getGreeting() - { - return $this->_greeting; - } - - /** - * Attempt to connect to the SMTP server. - * - * @param int $timeout The timeout value (in seconds) for the - * socket connection. - * @param bool $persistent Should a persistent socket connection - * be used? - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - */ - public function connect($timeout = null, $persistent = false) - { - $this->_greeting = null; - $result = $this->_socket->connect($this->host, $this->port, - $persistent, $timeout); - if (PEAR::isError($result)) { - return PEAR::raiseError('Failed to connect socket: '. - $result->getMessage()); - } - - if (PEAR::isError($error = $this->_parseResponse(220))) { - return $error; - } - - /* Extract and store a copy of the server's greeting string. */ - list(, $this->_greeting) = $this->getResponse(); - - if (PEAR::isError($error = $this->_negotiate())) { - return $error; - } - - return true; - } - - /** - * Attempt to disconnect from the SMTP server. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - */ - public function disconnect() - { - if (PEAR::isError($error = $this->_put('QUIT'))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse(221))) { - return $error; - } - if (PEAR::isError($error = $this->_socket->disconnect())) { - return PEAR::raiseError('Failed to disconnect socket: '. - $error->getMessage()); - } - - return true; - } - - /** - * Attempt to send the EHLO command and obtain a list of ESMTP - * extensions available, and failing that just send HELO. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.1.0 - */ - public function _negotiate() - { - if (PEAR::isError($error = $this->_put('EHLO', $this->localhost))) { - return $error; - } - - if (PEAR::isError($this->_parseResponse(250))) { - /* If we receive a 503 response, we're already authenticated. */ - if ($this->_code === 503) { - return true; - } - - /* If the EHLO failed, try the simpler HELO command. */ - if (PEAR::isError($error = $this->_put('HELO', $this->localhost))) { - return $error; - } - if (PEAR::isError($this->_parseResponse(250))) { - return PEAR::raiseError('HELO was not accepted: ', $this->_code); - } - - return true; - } - - foreach ($this->_arguments as $argument) { - $verb = strtok($argument, ' '); - $arguments = substr($argument, strlen($verb) + 1, - strlen($argument) - strlen($verb) - 1); - $this->_esmtp[$verb] = $arguments; - } - - if (!isset($this->_esmtp['PIPELINING'])) { - $this->pipelining = false; - } - - return true; - } - - /** - * Returns the name of the best authentication method that the server - * has advertised. - * - * @return mixed Returns a string containing the name of the best - * supported authentication method or a PEAR_Error object - * if a failure condition is encountered. - * - * @since 1.1.0 - */ - public function _getBestAuthMethod() - { - $available_methods = explode(' ', $this->_esmtp['AUTH']); - - foreach ($this->auth_methods as $method) { - if (in_array($method, $available_methods)) { - return $method; - } - } - - return PEAR::raiseError('No supported authentication methods'); - } - - /** - * Attempt to do SMTP authentication. - * - * @param string The userid to authenticate as. - * @param string The password to authenticate with. - * @param string The requested authentication method. If none is - * specified, the best supported method will be used. - * @param bool Flag indicating whether or not TLS should be attempted. - * @param string An optional authorization identifier. If specified, this - * identifier will be used as the authorization proxy. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - */ - public function auth($uid, $pwd, $method = '', $tls = true, $authz = '') - { - /* We can only attempt a TLS connection if one has been requested, - * we're running PHP 5.1.0 or later, have access to the OpenSSL - * extension, are connected to an SMTP server which supports the - * STARTTLS extension, and aren't already connected over a secure - * (SSL) socket connection. */ - if ($tls && version_compare(PHP_VERSION, '5.1.0', '>=') && - extension_loaded('openssl') && isset($this->_esmtp['STARTTLS']) && - strncasecmp($this->host, 'ssl://', 6) !== 0) { - /* Start the TLS connection attempt. */ - if (PEAR::isError($result = $this->_put('STARTTLS'))) { - return $result; - } - if (PEAR::isError($result = $this->_parseResponse(220))) { - return $result; - } - if (PEAR::isError($result = $this->_socket->enableCrypto(true, STREAM_CRYPTO_METHOD_TLS_CLIENT))) { - return $result; - } elseif ($result !== true) { - return PEAR::raiseError('STARTTLS failed'); - } - - /* Send EHLO again to recieve the AUTH string from the - * SMTP server. */ - $this->_negotiate(); - } - - if (empty($this->_esmtp['AUTH'])) { - return PEAR::raiseError('SMTP server does not support authentication'); - } - - /* If no method has been specified, get the name of the best - * supported method advertised by the SMTP server. */ - if (empty($method)) { - if (PEAR::isError($method = $this->_getBestAuthMethod())) { - /* Return the PEAR_Error object from _getBestAuthMethod(). */ - return $method; - } - } else { - $method = strtoupper($method); - if (!in_array($method, $this->auth_methods)) { - return PEAR::raiseError("$method is not a supported authentication method"); - } - } - - switch ($method) { - case 'DIGEST-MD5': - $result = $this->_authDigest_MD5($uid, $pwd, $authz); - break; - - case 'CRAM-MD5': - $result = $this->_authCRAM_MD5($uid, $pwd); - break; - - case 'LOGIN': - $result = $this->_authLogin($uid, $pwd); - break; - - case 'PLAIN': - $result = $this->_authPlain($uid, $pwd, $authz); - break; - - default: - $result = PEAR::raiseError("$method is not a supported authentication method"); - break; - } - - /* If an error was encountered, return the PEAR_Error object. */ - if (PEAR::isError($result)) { - return $result; - } - - return true; - } - - /** - * Authenticates the user using the DIGEST-MD5 method. - * - * @param string The userid to authenticate as. - * @param string The password to authenticate with. - * @param string The optional authorization proxy identifier. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.1.0 - * @deprecated 本体で使用されていないため非推奨 - */ - public function _authDigest_MD5($uid, $pwd, $authz = '') - { - if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) { - return $error; - } - /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { - /* 503: Error: already authenticated */ - if ($this->_code === 503) { - return true; - } - - return $error; - } - - $challenge = base64_decode($this->_arguments[0]); - $digest = &Auth_SASL::factory('digestmd5'); - $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, - $this->host, 'smtp')); - - if (PEAR::isError($error = $this->_put($auth_str))) { - return $error; - } - /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { - return $error; - } - - /* We don't use the protocol's third step because SMTP doesn't - * allow subsequent authentication, so we just silently ignore - * it. */ - if (PEAR::isError($error = $this->_put(''))) { - return $error; - } - /* 235: Authentication successful */ - if (PEAR::isError($error = $this->_parseResponse(235))) { - return $error; - } - } - - /** - * Authenticates the user using the CRAM-MD5 method. - * - * @param string The userid to authenticate as. - * @param string The password to authenticate with. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.1.0 - * @deprecated 本体で使用されていないため非推奨 - */ - public function _authCRAM_MD5($uid, $pwd) - { - if (PEAR::isError($error = $this->_put('AUTH', 'CRAM-MD5'))) { - return $error; - } - /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { - /* 503: Error: already authenticated */ - if ($this->_code === 503) { - return true; - } - - return $error; - } - - $challenge = base64_decode($this->_arguments[0]); - $cram = &Auth_SASL::factory('crammd5'); - $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge)); - - if (PEAR::isError($error = $this->_put($auth_str))) { - return $error; - } - - /* 235: Authentication successful */ - if (PEAR::isError($error = $this->_parseResponse(235))) { - return $error; - } - } - - /** - * Authenticates the user using the LOGIN method. - * - * @param string The userid to authenticate as. - * @param string The password to authenticate with. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.1.0 - */ - public function _authLogin($uid, $pwd) - { - if (PEAR::isError($error = $this->_put('AUTH', 'LOGIN'))) { - return $error; - } - /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { - /* 503: Error: already authenticated */ - if ($this->_code === 503) { - return true; - } - - return $error; - } - - if (PEAR::isError($error = $this->_put(base64_encode($uid)))) { - return $error; - } - /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { - return $error; - } - - if (PEAR::isError($error = $this->_put(base64_encode($pwd)))) { - return $error; - } - - /* 235: Authentication successful */ - if (PEAR::isError($error = $this->_parseResponse(235))) { - return $error; - } - - return true; - } - - /** - * Authenticates the user using the PLAIN method. - * - * @param string The userid to authenticate as. - * @param string The password to authenticate with. - * @param string The optional authorization proxy identifier. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.1.0 - */ - public function _authPlain($uid, $pwd, $authz = '') - { - if (PEAR::isError($error = $this->_put('AUTH', 'PLAIN'))) { - return $error; - } - /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { - /* 503: Error: already authenticated */ - if ($this->_code === 503) { - return true; - } - - return $error; - } - - $auth_str = base64_encode($authz.chr(0).$uid.chr(0).$pwd); - - if (PEAR::isError($error = $this->_put($auth_str))) { - return $error; - } - - /* 235: Authentication successful */ - if (PEAR::isError($error = $this->_parseResponse(235))) { - return $error; - } - - return true; - } - - /** - * Send the HELO command. - * - * @param string The domain name to say we are. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - */ - public function helo($domain) - { - if (PEAR::isError($error = $this->_put('HELO', $domain))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse(250))) { - return $error; - } - - return true; - } - - /** - * Return the list of SMTP service extensions advertised by the server. - * - * @return array The list of SMTP service extensions. - * - * @since 1.3 - */ - public function getServiceExtensions() - { - return $this->_esmtp; - } - - /** - * Send the MAIL FROM: command. - * - * @param string $sender The sender (reverse path) to set. - * @param string $params String containing additional MAIL parameters, - * such as the NOTIFY flags defined by RFC 1891 - * or the VERP protocol. - * - * If $params is an array, only the 'verp' option - * is supported. If 'verp' is true, the XVERP - * parameter is appended to the MAIL command. If - * the 'verp' value is a string, the full - * XVERP=value parameter is appended. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - */ - public function mailFrom($sender, $params = null) - { - $args = "FROM:<$sender>"; - - /* Support the deprecated array form of $params. */ - if (is_array($params) && isset($params['verp'])) { - /* XVERP */ - if ($params['verp'] === true) { - $args .= ' XVERP'; - - /* XVERP=something */ - } elseif (trim($params['verp'])) { - $args .= ' XVERP='.$params['verp']; - } - } elseif (is_string($params)) { - $args .= ' '.$params; - } - - if (PEAR::isError($error = $this->_put('MAIL', $args))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { - return $error; - } - - return true; - } - - /** - * Send the RCPT TO: command. - * - * @param string $recipient The recipient (forward path) to add. - * @param string $params String containing additional RCPT parameters, - * such as the NOTIFY flags defined by RFC 1891. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - */ - public function rcptTo($recipient, $params = null) - { - $args = "TO:<$recipient>"; - if (is_string($params)) { - $args .= ' '.$params; - } - - if (PEAR::isError($error = $this->_put('RCPT', $args))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse([250, 251], $this->pipelining))) { - return $error; - } - - return true; - } - - /** - * Quote the data so that it meets SMTP standards. - * - * This is provided as a separate public function to facilitate - * easier overloading for the cases where it is desirable to - * customize the quoting behavior. - * - * @param string $data The message text to quote. The string must be passed - * by reference, and the text will be modified in place. - * - * @since 1.2 - */ - public function quotedata(&$data) - { - /* Change Unix (\n) and Mac (\r) linefeeds into - * Internet-standard CRLF (\r\n) linefeeds. */ - $data = preg_replace(['/(?_esmtp['SIZE'])) ? $this->_esmtp['SIZE'] : 0; - if ($limit > 0 && $size >= $limit) { - $this->disconnect(); - - return PEAR::raiseError('Message size exceeds server limit'); - } - - /* Initiate the DATA command. */ - if (PEAR::isError($error = $this->_put('DATA'))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse(354))) { - return $error; - } - - /* If we have a separate headers string, send it first. */ - if (!is_null($headers)) { - $this->quotedata($headers); - if (PEAR::isError($result = $this->_send($headers."\r\n\r\n"))) { - return $result; - } - } - - /* Now we can send the message body data. */ - if (is_resource($data)) { - /* Stream the contents of the file resource out over our socket - * connection, line by line. Each line must be run through the - * quoting routine. */ - while ($line = fgets($data, 1024)) { - $this->quotedata($line); - if (PEAR::isError($result = $this->_send($line))) { - return $result; - } - } - } else { - /* - * Break up the data by sending one chunk (up to 512k) at a time. - * This approach reduces our peak memory usage. - */ - for ($offset = 0; $offset < $size;) { - $end = $offset + 512000; - - /* - * Ensure we don't read beyond our data size or span multiple - * lines. quotedata() can't properly handle character data - * that's split across two line break boundaries. - */ - if ($end >= $size) { - $end = $size; - } else { - for (; $end < $size; $end++) { - if ($data[$end] != "\n") { - break; - } - } - } - - /* Extract our chunk and run it through the quoting routine. */ - $chunk = substr($data, $offset, $end - $offset); - $this->quotedata($chunk); - - /* If we run into a problem along the way, abort. */ - if (PEAR::isError($result = $this->_send($chunk))) { - return $result; - } - - /* Advance the offset to the end of this chunk. */ - $offset = $end; - } - } - - /* Finally, send the DATA terminator sequence. */ - if (PEAR::isError($result = $this->_send("\r\n.\r\n"))) { - return $result; - } - - /* Verify that the data was successfully received by the server. */ - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { - return $error; - } - - return true; - } - - /** - * Send the SEND FROM: command. - * - * @param string The reverse path to send. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.2.6 - */ - public function sendFrom($path) - { - if (PEAR::isError($error = $this->_put('SEND', "FROM:<$path>"))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { - return $error; - } - - return true; - } - - /** - * Backwards-compatibility wrapper for sendFrom(). - * - * @param string The reverse path to send. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - * @deprecated 1.2.6 - */ - public function send_from($path) - { - return self::sendFrom($path); - } - - /** - * Send the SOML FROM: command. - * - * @param string The reverse path to send. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.2.6 - */ - public function somlFrom($path) - { - if (PEAR::isError($error = $this->_put('SOML', "FROM:<$path>"))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { - return $error; - } - - return true; - } - - /** - * Backwards-compatibility wrapper for somlFrom(). - * - * @param string The reverse path to send. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - * @deprecated 1.2.6 - */ - public function soml_from($path) - { - return self::somlFrom($path); - } - - /** - * Send the SAML FROM: command. - * - * @param string The reverse path to send. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.2.6 - */ - public function samlFrom($path) - { - if (PEAR::isError($error = $this->_put('SAML', "FROM:<$path>"))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { - return $error; - } - - return true; - } - - /** - * Backwards-compatibility wrapper for samlFrom(). - * - * @param string The reverse path to send. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - * @deprecated 1.2.6 - */ - public function saml_from($path) - { - return self::samlFrom($path); - } - - /** - * Send the RSET command. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - */ - public function rset() - { - if (PEAR::isError($error = $this->_put('RSET'))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { - return $error; - } - - return true; - } - - /** - * Send the VRFY command. - * - * @param string The string to verify - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - */ - public function vrfy($string) - { - /* Note: 251 is also a valid response code */ - if (PEAR::isError($error = $this->_put('VRFY', $string))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse([250, 252]))) { - return $error; - } - - return true; - } - - /** - * Send the NOOP command. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @since 1.0 - */ - public function noop() - { - if (PEAR::isError($error = $this->_put('NOOP'))) { - return $error; - } - if (PEAR::isError($error = $this->_parseResponse(250))) { - return $error; - } - - return true; - } - - /** - * Backwards-compatibility method. identifySender()'s functionality is - * now handled internally. - * - * @return bool This method always return true. - * - * @since 1.0 - */ - public function identifySender() - { - return true; - } -} diff --git a/data/module/Net/Socket.php b/data/module/Net/Socket.php deleted file mode 100644 index 871ea7cd57..0000000000 --- a/data/module/Net/Socket.php +++ /dev/null @@ -1,657 +0,0 @@ - - * Chuck Hagenbuch - * - * @category Net - * - * @author Stig Bakken - * @author Chuck Hagenbuch - * @copyright 1997-2003 The PHP Group - * @license http://www.php.net/license/2_02.txt PHP 2.02 - * - * @version CVS: $Id$ - * - * @see http://pear.php.net/packages/Net_Socket - */ -require_once 'PEAR.php'; - -define('NET_SOCKET_READ', 1); -define('NET_SOCKET_WRITE', 2); -define('NET_SOCKET_ERROR', 4); - -/** - * Generalized Socket class. - * - * @category Net - * - * @author Stig Bakken - * @author Chuck Hagenbuch - * @copyright 1997-2003 The PHP Group - * @license http://www.php.net/license/2_02.txt PHP 2.02 - * - * @see http://pear.php.net/packages/Net_Socket - */ -class Net_Socket extends PEAR -{ - /** - * Socket file pointer. - * - * @var resource - */ - public $fp = null; - - /** - * Whether the socket is blocking. Defaults to true. - * - * @var bool - */ - public $blocking = true; - - /** - * Whether the socket is persistent. Defaults to false. - * - * @var bool - */ - public $persistent = false; - - /** - * The IP address to connect to. - * - * @var string - */ - public $addr = ''; - - /** - * The port number to connect to. - * - * @var int - */ - public $port = 0; - - /** - * Number of seconds to wait on socket connections before assuming - * there's no more data. Defaults to no timeout. - * - * @var int - */ - public $timeout = false; - - /** - * Number of bytes to read at a time in readLine() and - * readAll(). Defaults to 2048. - * - * @var int - */ - public $lineLength = 2048; - - /** - * The string to use as a newline terminator. Usually "\r\n" or "\n". - * - * @var string - */ - public $newline = "\r\n"; - - /** - * Connect to the specified port. If called when the socket is - * already connected, it disconnects and connects again. - * - * @param string $addr IP address or host name. - * @param int $port TCP port number. - * @param bool $persistent (optional) Whether the connection is - * persistent (kept open between requests - * by the web server). - * @param int $timeout (optional) How long to wait for data. - * @param array $options See options for stream_context_create. - * - * @return bool|PEAR_Error True on success or a PEAR_Error on failure. - */ - public 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 = ''; - - $old_track_errors = @ini_set('track_errors', 1); - - if ($options && function_exists('stream_context_create')) { - if ($this->timeout) { - $timeout = $this->timeout; - } else { - $timeout = 0; - } - $context = stream_context_create($options); - - // Since PHP 5 fsockopen doesn't allow context specification - if (function_exists('stream_socket_client')) { - $flags = STREAM_CLIENT_CONNECT; - - if ($this->persistent) { - $flags = STREAM_CLIENT_PERSISTENT; - } - - $addr = $this->addr.':'.$this->port; - $fp = stream_socket_client($addr, $errno, $errstr, - $timeout, $flags, $context); - } else { - $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) { - $error = error_get_last(); - if ($errno == 0 && !strlen($errstr) && isset($error)) { - $errstr = $error['message']; - } - @ini_set('track_errors', $old_track_errors); - - return $this->raiseError($errstr, $errno); - } - - @ini_set('track_errors', $old_track_errors); - $this->fp = $fp; - - return $this->setBlocking($this->blocking); - } - - /** - * Disconnects from the peer, closes the socket. - * - * @return mixed true on success or a PEAR_Error instance otherwise - */ - public function disconnect() - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - @fclose($this->fp); - $this->fp = null; - - return true; - } - - /** - * Set the newline character/sequence to use. - * - * @param string $newline Newline character(s) - * - * @return bool True - */ - public function setNewline($newline) - { - $this->newline = $newline; - - return true; - } - - /** - * Find out if the socket is in blocking mode. - * - * @return bool The current blocking mode. - */ - public function isBlocking() - { - return $this->blocking; - } - - /** - * Sets whether the socket connection should be blocking or - * not. A read call to a non-blocking socket will return immediately - * if there is no data available, whereas it will block until there - * is data for blocking sockets. - * - * @param bool $mode True for blocking sockets, false for nonblocking. - * - * @return mixed true on success or a PEAR_Error instance otherwise - */ - public function setBlocking($mode) - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - $this->blocking = $mode; - stream_set_blocking($this->fp, (int) $this->blocking); - - return true; - } - - /** - * Sets the timeout value on socket descriptor, - * expressed in the sum of seconds and microseconds - * - * @param int $seconds Seconds. - * @param int $microseconds Microseconds. - * - * @return mixed true on success or a PEAR_Error instance otherwise - */ - public function setTimeout($seconds, $microseconds) - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - return stream_set_timeout($this->fp, $seconds, $microseconds); - } - - /** - * Sets the file buffering size on the stream. - * See php's stream_set_write_buffer for more information. - * - * @param int $size Write buffer size. - * - * @return mixed on success or an PEAR_Error object otherwise - */ - public function setWriteBuffer($size) - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - $returned = stream_set_write_buffer($this->fp, $size); - if ($returned == 0) { - return true; - } - - return $this->raiseError('Cannot set write buffer.'); - } - - /** - * Returns information about an existing socket resource. - * Currently returns four entries in the result array: - * - *

- * timed_out (bool) - The socket timed out waiting for data
- * blocked (bool) - The socket was blocked
- * eof (bool) - Indicates EOF event
- * unread_bytes (int) - Number of bytes left in the socket buffer
- *

- * - * @return mixed Array containing information about existing socket - * resource or a PEAR_Error instance otherwise - */ - public function getStatus() - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - return stream_get_meta_data($this->fp); - } - - /** - * Get a specified line of data - * - * @param int $size ?? - * - * @return $size bytes of data from the socket, or a PEAR_Error if - * not connected. - */ - public function gets($size = null) - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - if (is_null($size)) { - return @fgets($this->fp); - } else { - return @fgets($this->fp, $size); - } - } - - /** - * Read a specified amount of data. This is guaranteed to return, - * and has the added benefit of getting everything in one fread() - * chunk; if you know the size of the data you're getting - * beforehand, this is definitely the way to go. - * - * @param int $size The number of bytes to read from the socket. - * - * @return $size bytes of data from the socket, or a PEAR_Error if - * not connected. - */ - public function read($size) - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - return @fread($this->fp, $size); - } - - /** - * Write a specified amount of data. - * - * @param string $data Data to write. - * @param int $blocksize Amount of data to write at once. - * NULL means all at once. - * - * @return mixed If the socket is not connected, returns an instance of - * PEAR_Error - * If the write succeeds, returns the number of bytes written - * If the write fails, returns false. - */ - public 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) { - return $written; - } - $pos += $written; - } - - return $pos; - } - } - - /** - * Write a line of data to the socket, followed by a trailing newline. - * - * @param string $data Data to write - * - * @return mixed fputs result, or an error - */ - public function writeLine($data) - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - return fwrite($this->fp, $data.$this->newline); - } - - /** - * Tests for end-of-file on a socket descriptor. - * - * Also returns true if the socket is disconnected. - * - * @return bool - */ - public function eof() - { - return !is_resource($this->fp) || feof($this->fp); - } - - /** - * Reads a byte of data - * - * @return 1 byte of data from the socket, or a PEAR_Error if - * not connected. - */ - public function readByte() - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - return ord(@fread($this->fp, 1)); - } - - /** - * Reads a word of data - * - * @return 1 word of data from the socket, or a PEAR_Error if - * not connected. - */ - public 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); - } - - /** - * Reads an int of data - * - * @return int 1 int of data from the socket, or a PEAR_Error if - * not connected. - */ - public 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); - } - - /** - * Reads a zero-terminated string of data - * - * @return string, or a PEAR_Error if - * not connected. - */ - public function readString() - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - $string = ''; - while (($char = @fread($this->fp, 1)) != "\x00") { - $string .= $char; - } - - return $string; - } - - /** - * Reads an IP Address and returns it in a dot formatted string - * - * @return Dot formatted string, or a PEAR_Error if - * not connected. - */ - public function readIPAddress() - { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - - $buf = @fread($this->fp, 4); - - return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]), - ord($buf[2]), ord($buf[3])); - } - - /** - * Read until either the end of the socket or a newline, whichever - * comes first. Strips the trailing newline from the returned data. - * - * @return All available data up to a newline, without that - * newline, or until the end of the socket, or a PEAR_Error if - * not connected. - */ - public 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, $this->newline); - } - } - - return $line; - } - - /** - * Read until the socket closes, or until there is no more data in - * the inner PHP buffer. If the inner buffer is empty, in blocking - * mode we wait for at least 1 byte of data. Therefore, in - * blocking mode, if there is no data at all to be read, this - * function will never exit (unless the socket is closed on the - * remote end). - * - * @return string All data until the socket closes, or a PEAR_Error if - * not connected. - */ - public 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; - } - - /** - * Runs the equivalent of the select() system call on the socket - * with a timeout specified by tv_sec and tv_usec. - * - * @param int $state Which of read/write/error to check for. - * @param int $tv_sec Number of seconds for timeout. - * @param int $tv_usec Number of microseconds for timeout. - * - * @return false if select fails, integer describing which of read/write/error - * are ready, or PEAR_Error if not connected. - */ - public 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; - } - - /** - * Turns encryption on/off on a connected socket. - * - * @param bool $enabled Set this parameter to true to enable encryption - * and false to disable encryption. - * @param int $type Type of encryption. See stream_socket_enable_crypto() - * for values. - * - * @see http://se.php.net/manual/en/function.stream-socket-enable-crypto.php - * - * @return false on error, true on success and 0 if there isn't enough data - * and the user should try again (non-blocking sockets only). - * A PEAR_Error object is returned if the socket is not - * connected - */ - public function enableCrypto($enabled, $type) - { - if (version_compare(PHP_VERSION, '5.1.0', '>=')) { - if (!is_resource($this->fp)) { - return $this->raiseError('not connected'); - } - stream_context_set_option($this->fp, 'ssl', 'verify_peer_name', false); - - return @stream_socket_enable_crypto($this->fp, $enabled, $type); - } else { - $msg = 'Net_Socket::enableCrypto() requires php version >= 5.1.0'; - - return $this->raiseError($msg); - } - } -} diff --git a/phpstan.neon.dist b/phpstan.neon.dist index fedf1b2161..b3f856b60f 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -19,16 +19,9 @@ parameters: message: "#^Call to an undefined static method PEAR\\:\\:raiseError\\(\\)\\.$#" paths: - data/module/HTTP/Request.php - - data/module/Net/SMTP.php - data/module/Calendar/Calendar.php - data/module/Calendar/Decorator.php - data/module/Calendar/Factory.php - - - message: "#^Call to an undefined method Net_Socket\\:\\:raiseError\\(\\)\\.$#" - path: data/module/Net/Socket.php - - - message: "#^Call to static method factory\\(\\) on an unknown class Auth_SASL\\.$#" - path: data/module/Net/SMTP.php - message: "#^Call to static method dayOfWeek\\(\\) on an unknown class Date_Calc\\.#" path: data/module/Calendar/Util/Textual.php @@ -38,9 +31,6 @@ parameters: - message: "#^Variable \\$SJIS_widths might not be defined\\.$#" path: data/class/helper/SC_Helper_FPDI.php - - - message: '#^Path in include_once\(\) "Auth/SASL.php" is not a file or it does not exist.#' - path: data/module/Net/SMTP.php - message: '#^Path in require_once\(\) ".*\.php" is not a file or it does not exist\.$#' paths: