Source for file Rfc822Header.class.php
Documentation is available at Rfc822Header.class.php
* This file contains functions needed to handle headers in mime messages.
* @copyright © 2003-2006 The SquirrelMail Project Team
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @version $Id: Rfc822Header.class.php,v 1.55 2006/09/15 19:31:32 stevetruckstuff Exp $
* input: header_string or array
* You must call parseHeader() function after creating object in order to fill object's
* @todo FIXME: there is no constructor function and class should ignore all input args.
* Mail-Followup-To header
* Disposition notification for requesting message delivery notification (MDN)
* Delivery notification (DR)
* only needed for constructing headers in delivery class
* @param mixed $hdr string or array with message headers
/* First we replace \r\n by \n and unfold the header */
/* FIXME: unfolding header with multiple spaces "\n( +)" */
$hdr =
trim(str_replace(array("\r\n", "\n\t", "\n "),array("\n", ' ', ' '), $hdr));
/* Now we can make a new header array with */
/* each element representing a headerline */
foreach ($hdr as $line) {
$field =
substr($line, 0, $pos);
if (!strstr($field,' ')) { /* valid field */
for ($i =
0; $i <
$cnt; ++
$i) {
while ((++
$i <
$cnt) &&
($value{$i} !=
'"')) {
if ($value{$i} ==
'\\') {
while (($depth >
0) &&
(++
$i <
$cnt)) {
* Parse header field according to field type
* @param string $field field name
* @param string $value field value
$d =
strtr($value, array(' ' =>
' '));
case 'x-confirm-reading-to':
case 'disposition-notification-to':
case 'return-receipt-to':
$this->mime =
($value ==
'1.0' ?
true :
$this->mime);
case 'content-disposition':
case 'content-transfer-encoding':
case 'content-description':
$this->mlist('post', $value);
$this->mlist('reply', $value);
$this->mlist('subscribe', $value);
$this->mlist('unsubscribe', $value);
$this->mlist('archive', $value);
$this->mlist('owner', $value);
$this->mlist('help', $value);
$this->mlist('id', $value);
$aSpecials =
array('(' ,'<' ,',' ,';' ,':');
$aReplace =
array(' (',' <',' ,',' ;',' :');
$iEnd =
strpos($address,'>',$i+
1);
$sToken =
substr($address,$i);
$sToken =
substr($address,$i,$iEnd -
$i +
1);
if ($sToken) $aTokens[] =
$sToken;
$iEnd =
strpos($address,$cChar,$i+
1);
$prev_char =
$address{$iEnd-
1};
while ($prev_char ===
'\\' &&
substr($address,$iEnd-
2,2) !==
'\\\\') {
$iEnd =
strpos($address,$cChar,$iEnd+
1);
$prev_char =
$address{$iEnd-
1};
$sToken =
substr($address,$i);
// also remove the surrounding quotes
$sToken =
substr($address,$i+
1,$iEnd -
$i -
1);
if ($sToken) $aTokens[] =
$sToken;
$iEnd =
strpos($address,')',$i);
$sToken =
substr($address,$i);
while (($iDepth >
0) &&
(++
$iComment <
$iCnt)) {
$cCharComment =
$address{$iComment};
$sToken =
substr($address,$i,$iComment -
$i +
1);
$sToken =
substr($address,$i,$iEnd -
$i +
1);
// check the next token in case comments appear in the middle of email addresses
$prevToken =
end($aTokens);
if (!in_array($prevToken,$aSpecials,true)) {
if ($i+
1<
strlen($address) &&
!in_array($address{$i+
1},$aSpecials,true)) {
$iEnd =
strpos($address,' ',$i+
1);
$sNextToken =
trim(substr($address,$i+
1,$iEnd -
$i -
1));
// create token and add it again
$sNewToken =
$prevToken .
$sNextToken;
if($sNewToken) $aTokens[] =
$sNewToken;
if ($sToken) $aTokens[] =
$sToken;
$iEnd =
strpos($address,' ',$i+
1);
if ($sToken) $aTokens[] =
$sToken;
* @return object AddressStructure object
//$aStack=explode(' ',implode('',$aStack));
while (count($aStack) &&
!$sEmail) {
if (!$sPersonal &&
count($aComment)) {
if ($sPersonal &&
substr($sPersonal,0,2) ==
'=?') {
$oAddr->personal =
$sPersonal;
// $oAddr->group = $sGroup;
$iPosAt =
strpos($sEmail,'@');
$oAddr->mailbox =
substr($sEmail, 0, $iPosAt);
$oAddr->host =
substr($sEmail, $iPosAt+
1);
$oAddr->mailbox =
$sEmail;
$aStack =
$aComment =
array();
* recursive function for parsing address strings and storing them in an address stucture object.
* personal name: encoded: =?charset?Q|B?string?=
* This function is also used for validating addresses returned from compose
* That's also the reason that the function became a little bit huge
* @param boolean $ar return array instead of only the first element
* @param array $addr_ar (obsolete) array with parsed addresses
* @param string $group (obsolete)
* @param string $host default domainname in case of addresses without a domainname
* @param string $lookup (since) callback function for lookup of address strings which are probably nicks (without @)
* @return mixed array with AddressStructure objects or only one address_structure object.
function parseAddress($address,$ar=
false,$aAddress=
array(),$sGroup=
'',$sHost=
'',$lookup=
false) {
$sPersonal =
$sEmail =
$sGroup =
'';
$aStack =
$aComment =
array();
foreach ($aTokens as $sToken) {
$aComment[] =
substr($sToken,1,-
1);
if(!$oAddr ||
((isset
($oAddr)) &&
!$oAddr->mailbox &&
!$oAddr->personal)) {
$sEmail =
$sGroup .
':;';
$aStack =
$aComment =
array();
default:
$aStack[] =
$sToken; break;
/* now do the action again for the last address */
/* try to lookup the addresses in case of invalid email addresses */
$aProcessedAddress =
array();
foreach ($aAddress as $oAddr) {
$aAddrBookAddress =
array();
if (isset
($aAddr['email'])) {
if (strpos($aAddr['email'],',')) {
$aAddrBookAddress =
$this->parseAddress($aAddr['email'],true);
$iPosAt =
strpos($aAddr['email'], '@');
$oAddr->mailbox =
substr($aAddr['email'], 0, $iPosAt);
$oAddr->host =
substr($aAddr['email'], $iPosAt+
1);
if (isset
($aAddr['name'])) {
$oAddr->personal =
$aAddr['name'];
if (!$grouplookup &&
!$oAddr->mailbox) {
$oAddr->mailbox =
trim($sEmail);
if ($sHost &&
$oAddr->mailbox) {
} else if (!$grouplookup &&
!$oAddr->host) {
if ($sHost &&
$oAddr->mailbox) {
if (!$aAddrBookAddress &&
$oAddr->mailbox) {
$aProcessedAddress[] =
$oAddr;
$aProcessedAddress =
array_merge($aProcessedAddress,$aAddrBookAddress);
return $aProcessedAddress;
return $aProcessedAddress[0];
* Normalise the different Priority headers into a uniform value,
* namely that of the X-Priority header (1, 3, 5). Supports:
* Priority, X-Priority, Importance.
* X-MS-Mail-Priority is not parsed because it always coincides
* with one of the other headers.
* NOTE: this is actually a duplicate from the function in
* functions/imap_messages. I'm not sure if it's ok here to call
* @param string $sValue literal priority name
// don't use function call inside array_shift.
if ( $value ==
'urgent' ||
$value ==
'high' ) {
} elseif ( $value ==
'non-urgent' ||
$value ==
'low' ) {
// default is normal priority
* @param string $value content type header
if (!isset
($properties['charset'])) {
$properties['charset'] =
'us-ascii';
* @param array $aParameters
// handle multiline parameters
foreach($aParameters as $key =>
$value) {
if ($iPos =
strpos($key,'*')) {
if (!isset
($aResults[$sKey])) {
$aResults[$sKey] =
$value;
if (substr($key,-
1) ==
'*') { // parameter contains language/charset info
$aResults[$sKey] .=
$value;
$aResults[$key] =
$value;
foreach ($aCharset as $key) {
$value =
$aResults[$key];
// extract the charset & language
/* FIXME: What's the status of charset decode with language information ????
* Maybe language information contains only ascii text and charset_decode()
* only runs htmlspecialchars() on it. If it contains 8bit information, you
* get html encoded text in charset used by selected translation.
$aResults[$key] =
$value;
$propResultArray =
array();
foreach ($propArray as $prop) {
if (strlen($val) >
0 &&
$val{0} ==
'"') {
$propResultArray[$key] =
$val;
* Fills disposition object in rfc822Header object
$disp->properties =
$props_a;
* Fills mlist array keys in rfc822Header object
function mlist($field, $value) {
foreach ($value_a as $val) {
if (substr($val, 0, 7) ==
'mailto:') {
$res_a['mailto'] =
substr($val, 7);
$this->mlist[$field] =
$res_a;
* function to get the address strings out of the header.
* example1: header->getAddr_s('to').
* example2: header->getAddr_s(array('to', 'cc', 'bcc'))
* @param mixed $arr string or array of strings
* @param string $separator
* @param boolean $encoded (since 1.4.0) return encoded or plain text addresses
function getAddr_s($arr, $separator =
',',$encoded=
false) {
if ($this->getAddr_s($arg, $separator, $encoded)) {
$s =
($s ?
substr($s, 2) :
$s);
foreach ($addr as $addr_o) {
$s .=
$addr_o->getEncodedAddress() .
$separator;
$s .=
$addr_o->getAddress() .
$separator;
$s .=
$addr->getEncodedAddress();
$s .=
$addr->getAddress();
* function to get the array of addresses out of the header.
* @param mixed $arg string or array of strings
* @param array $excl_arr array of excluded email addresses
* @param array $arr array of added email addresses
function getAddr_a($arg, $excl_arr =
array(), $arr =
array()) {
foreach($arg as $argument) {
$arr =
$this->getAddr_a($argument, $excl_arr, $arr);
foreach ($addr as $next_addr) {
if (isset
($next_addr->host) &&
($next_addr->host !=
'')) {
$email =
$next_addr->mailbox .
'@' .
$next_addr->host;
$email =
$next_addr->mailbox;
if ($email &&
!isset
($arr[$email]) &&
!isset
($excl_arr[$email])) {
$arr[$email] =
$next_addr->personal;
$email .=
(isset
($addr->host) ?
'@' .
$addr->host :
'');
if ($email &&
!isset
($arr[$email]) &&
!isset
($excl_arr[$email])) {
$arr[$email] =
$addr->personal;
* @param mixed $address array or string
* @return mixed array, boolean
foreach($address as $argument) {
if (count($match[0]) &&
!$result) {
foreach ($this->to as $to) {
if ($to->host ==
$srch_addr->host) {
if ($to->mailbox ==
$srch_addr->mailbox) {
if ($to->personal ==
$srch_addr->personal) {
return array($results, true);
foreach ($this->cc as $cc) {
if ($cc->host ==
$srch_addr->host) {
if ($cc->mailbox ==
$srch_addr->mailbox) {
if ($cc->personal ==
$srch_addr->personal) {
return array($results, true);
return array($results, false);
} elseif (count($result)) {
* @param string $type0 media type
* @param string $type1 media subtype
* @return array media properties
* @todo check use of media type arguments
Documentation generated on Sat, 07 Oct 2006 16:13:21 +0300 by phpDocumentor 1.3.0RC6