📄 rfc822.php
字号:
<?php// +-----------------------------------------------------------------------+// | Copyright (c) 2001-2002, Richard Heyes |// | All rights reserved. |// | |// | Redistribution and use in source and binary forms, with or without |// | modification, are permitted provided that the following conditions |// | are met: |// | |// | o Redistributions of source code must retain the above copyright |// | notice, this list of conditions and the following disclaimer. |// | o Redistributions in binary form must reproduce the above copyright |// | notice, this list of conditions and the following disclaimer in the |// | documentation and/or other materials provided with the distribution.|// | o The names of the authors may not be used to endorse or promote |// | products derived from this software without specific prior written |// | permission. |// | |// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |// | |// +-----------------------------------------------------------------------+// | Authors: Richard Heyes <richard@phpguru.org> |// | Chuck Hagenbuch <chuck@horde.org> |// +-----------------------------------------------------------------------+/** * RFC 822 Email address list validation Utility * * What is it? * * This class will take an address string, and parse it into it's consituent * parts, be that either addresses, groups, or combinations. Nested groups * are not supported. The structure it returns is pretty straight forward, * and is similar to that provided by the imap_rfc822_parse_adrlist(). Use * print_r() to view the structure. * * How do I use it? * * $address_string = 'My Group: "Richard" <richard@localhost> (A comment), ted@example.com (Ted Bloggs), Barney;'; * $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', true) * print_r($structure); * * @author Richard Heyes <richard@phpguru.org> * @author Chuck Hagenbuch <chuck@horde.org> * @version $Revision: 1.23 $ * @license BSD * @package Mail */class Mail_RFC822 { /** * The address being parsed by the RFC822 object. * @var string $address */ var $address = ''; /** * The default domain to use for unqualified addresses. * @var string $default_domain */ var $default_domain = 'localhost'; /** * Should we return a nested array showing groups, or flatten everything? * @var boolean $nestGroups */ var $nestGroups = true; /** * Whether or not to validate atoms for non-ascii characters. * @var boolean $validate */ var $validate = true; /** * The array of raw addresses built up as we parse. * @var array $addresses */ var $addresses = array(); /** * The final array of parsed address information that we build up. * @var array $structure */ var $structure = array(); /** * The current error message, if any. * @var string $error */ var $error = null; /** * An internal counter/pointer. * @var integer $index */ var $index = null; /** * The number of groups that have been found in the address list. * @var integer $num_groups * @access public */ var $num_groups = 0; /** * A variable so that we can tell whether or not we're inside a * Mail_RFC822 object. * @var boolean $mailRFC822 */ var $mailRFC822 = true; /** * A limit after which processing stops * @var int $limit */ var $limit = null; /** * Sets up the object. The address must either be set here or when * calling parseAddressList(). One or the other. * * @access public * @param string $address The address(es) to validate. * @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost. * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. * * @return object Mail_RFC822 A new Mail_RFC822 object. */ function Mail_RFC822($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) { if (isset($address)) $this->address = $address; if (isset($default_domain)) $this->default_domain = $default_domain; if (isset($nest_groups)) $this->nestGroups = $nest_groups; if (isset($validate)) $this->validate = $validate; if (isset($limit)) $this->limit = $limit; } /** * Starts the whole process. The address must either be set here * or when creating the object. One or the other. * * @access public * @param string $address The address(es) to validate. * @param string $default_domain Default domain/host etc. * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. * * @return array A structured array of addresses. */ function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) { if (!isset($this) || !isset($this->mailRFC822)) { $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit); return $obj->parseAddressList(); } if (isset($address)) $this->address = $address; if (isset($default_domain)) $this->default_domain = $default_domain; if (isset($nest_groups)) $this->nestGroups = $nest_groups; if (isset($validate)) $this->validate = $validate; if (isset($limit)) $this->limit = $limit; $this->structure = array(); $this->addresses = array(); $this->error = null; $this->index = null; // Unfold any long lines in $this->address. $this->address = preg_replace('/\r?\n/', "\r\n", $this->address); $this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address); while ($this->address = $this->_splitAddresses($this->address)); if ($this->address === false || isset($this->error)) { require_once 'PEAR.php'; return PEAR::raiseError($this->error); } // Validate each address individually. If we encounter an invalid // address, stop iterating and return an error immediately. foreach ($this->addresses as $address) { $valid = $this->_validateAddress($address); if ($valid === false || isset($this->error)) { require_once 'PEAR.php'; return PEAR::raiseError($this->error); } if (!$this->nestGroups) { $this->structure = array_merge($this->structure, $valid); } else { $this->structure[] = $valid; } } return $this->structure; } /** * Splits an address into separate addresses. * * @access private * @param string $address The addresses to split. * @return boolean Success or failure. */ function _splitAddresses($address) { if (!empty($this->limit) && count($this->addresses) == $this->limit) { return ''; } if ($this->_isGroup($address) && !isset($this->error)) { $split_char = ';'; $is_group = true; } elseif (!isset($this->error)) { $split_char = ','; $is_group = false; } elseif (isset($this->error)) { return false; } // Split the string based on the above ten or so lines. $parts = explode($split_char, $address); $string = $this->_splitCheck($parts, $split_char); // If a group... if ($is_group) { // If $string does not contain a colon outside of // brackets/quotes etc then something's fubar. // First check there's a colon at all: if (strpos($string, ':') === false) { $this->error = 'Invalid address: ' . $string; return false; } // Now check it's outside of brackets/quotes: if (!$this->_splitCheck(explode(':', $string), ':')) { return false; } // We must have a group at this point, so increase the counter: $this->num_groups++; } // $string now contains the first full address/group. // Add to the addresses array. $this->addresses[] = array( 'address' => trim($string), 'group' => $is_group ); // Remove the now stored address from the initial line, the +1 // is to account for the explode character. $address = trim(substr($address, strlen($string) + 1)); // If the next char is a comma and this was a group, then // there are more addresses, otherwise, if there are any more // chars, then there is another address. if ($is_group && substr($address, 0, 1) == ','){ $address = trim(substr($address, 1)); return $address; } elseif (strlen($address) > 0) { return $address; } else { return ''; } // If you got here then something's off return false; } /** * Checks for a group at the start of the string. * * @access private * @param string $address The address to check. * @return boolean Whether or not there is a group at the start of the string. */ function _isGroup($address) { // First comma not in quotes, angles or escaped: $parts = explode(',', $address); $string = $this->_splitCheck($parts, ','); // Now we have the first address, we can reliably check for a // group by searching for a colon that's not escaped or in // quotes or angle brackets. if (count($parts = explode(':', $string)) > 1) { $string2 = $this->_splitCheck($parts, ':'); return ($string2 !== $string); } else { return false; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -