': /* skip */ break; default: $aStack[] = $sToken; break; } } /* now do the action again for the last address */ $aAddress[] = _createAddressElement($aStack,$aComment,$sEmail); return $aAddress; } /** * Do the address array to string translation * * @param array $aAddressList list with email address arrays * @param array $aProps associative array with properties * @return string * @public * @see parseRFC822Address * @author Marc Groot Koerkamp * **/ function getAddressString($aAddressList,$aProps) { $aPropsDefault = array ( 'separator' => ', ', // address separator 'limit' => 0, // limits returned addresses 'personal' => true, // show persnal part 'email' => true, // show email part 'best' => false, // show personal if available 'encode' => false, // encode the personal part 'unique' => false, // make email addresses unique. 'exclude' => array() // array with exclude addresses // format of address: mailbox@host ); $aProps = is_array($aProps) ? array_merge($aPropsDefault,$aProps) : $aPropsDefault; $aNewAddressList = array(); $aEmailUnique = array(); foreach ($aAddressList as $aAddr) { if ($aProps['limit'] && count($aNewAddressList) == $aProps['limit']) { break; } $sPersonal = (isset($aAddr[SQM_ADDR_PERSONAL])) ? $aAddr[SQM_ADDR_PERSONAL] : ''; $sMailbox = (isset($aAddr[SQM_ADDR_MAILBOX])) ? $aAddr[SQM_ADDR_MAILBOX] : ''; $sHost = (isset($aAddr[SQM_ADDR_HOST])) ? $aAddr[SQM_ADDR_HOST] : ''; $sEmail = ($sHost) ? "$sMailbox@$sHost": $sMailbox; if (in_array($sEmail,$aProps['exclude'],true)) { continue; } if ($aProps['unique']) { if (in_array($sEmail,$aEmailUnique,true)) { continue; } else { $aEmailUnique[] = $sEmail; } } $s = ''; if ($aProps['best']) { $s .= ($sPersonal) ? $sPersonal : $sEmail; } else { if ($aProps['personal'] && $sPersonal) { if ($aProps['encode']) { $sPersonal = encodeHeader($sPersonal); } $s .= $sPersonal; } if ($aProps['email'] && $sEmail) { $s.= ($s) ? ' <'.$sEmail.'>': '<'.$sEmail.'>'; } } if ($s) { $aNewAddressList[] = $s; } } return implode($aProps['separator'],$aNewAddressList); } /** * Do after address parsing handling. This is used by compose.php and should * be moved to compose.php. * The AddressStructure objetc is now obsolete and dependent parts of that will * be adapted so that it can make use of this function * After that we can remove the parseAddress method from the Rfc822Header class completely * so we achieved 1 single instance of parseAddress instead of two like we have now. * * @param array $aAddressList list with email address arrays * @param array $aProps associative array with properties * @return string * @public * @see parseRFC822Address * @see Rfc822Header * @author Marc Groot Koerkamp * **/ function processAddressArray($aAddresses,$aProps) { $aPropsDefault = array ( 'domain' => '', 'limit' => 0, 'abooklookup' => false); $aProps = is_array($aProps) ? array_merge($aPropsDefault,$aProps) : $aPropsDefault; $aProcessedAddress = array(); foreach ($aAddresses as $aEntry) { /* * if the emailaddress does not contain the domainpart it can concern * an alias or local (in the same domain as the user is) email * address. In that case we try to look it up in the addressbook or add * the local domain part */ if (!$aEntry[SQM_ADDR_HOST]) { if ($cbLookup) { $aAddr = call_user_func_array($cbLookup,array($aEntry[SQM_ADDR_MAILBOX])); if (isset($aAddr['email'])) { /* * if the returned email address concerns multiple email * addresses we have to process those as well */ if (strpos($aAddr['email'],',')) { /* multiple addresses */ /* add the parsed addresses to the processed address array */ $aProcessedAddress = array_merge($aProcessedAddress,parseAddress($aAddr['email'])); /* skip to next address, all processing is done */ continue; } else { /* single address */ $iPosAt = strpos($aAddr['email'], '@'); $aEntry[SQM_ADDR_MAILBOX] = substr($aAddr['email'], 0, $iPosAt); $aEntry[SQM_ADDR_HOST] = substr($aAddr['email'], $iPosAt+1); if (isset($aAddr['name'])) { $aEntry[SQM_ADDR_PERSONAL] = $aAddr['name']; } else { $aEntry[SQM_ADDR_PERSONAL] = encodeHeader($sPersonal); } } } } /* * append the domain * */ if (!$aEntry[SQM_ADDR_MAILBOX]) { $aEntry[SQM_ADDR_MAILBOX] = trim($sEmail); } if ($sDomain && !$aEntry[SQM_ADDR_HOST]) { $aEntry[SQM_ADDR_HOST] = $sDomain; } } if ($aEntry[SQM_ADDR_MAILBOX]) { $aProcessedAddress[] = $aEntry; } } return $aProcessedAddress; } /** * Internal function for creating an address array * * @param array $aStack * @param array $aComment * @param string $sEmail * @return array $aAddr array with personal (0), adl(1), mailbox(2) and host(3) info * @private * @author Marc Groot Koerkamp * **/ function _createAddressElement(&$aStack,&$aComment,&$sEmail) { if (!$sEmail) { while (count($aStack) && !$sEmail) { $sEmail = trim(array_pop($aStack)); } } if (count($aStack)) { $sPersonal = trim(implode('',$aStack)); } else { $sPersonal = ''; } if (!$sPersonal && count($aComment)) { $sComment = trim(implode(' ',$aComment)); $sPersonal .= $sComment; } $aAddr = array(); // if ($sPersonal && substr($sPersonal,0,2) == '=?') { // $aAddr[SQM_ADDR_PERSONAL] = encodeHeader($sPersonal); // } else { $aAddr[SQM_ADDR_PERSONAL] = $sPersonal; // } $iPosAt = strpos($sEmail,'@'); if ($iPosAt) { $aAddr[SQM_ADDR_MAILBOX] = substr($sEmail, 0, $iPosAt); $aAddr[SQM_ADDR_HOST] = substr($sEmail, $iPosAt+1); } else { $aAddr[SQM_ADDR_MAILBOX] = $sEmail; $aAddr[SQM_ADDR_HOST] = false; } $sEmail = ''; $aStack = $aComment = array(); return $aAddr; } /** * Tokenizer function for parsing the RFC822 email address string * * @param string $address The email address string to parse * @return array $aTokens * @private * @author Marc Groot Koerkamp * **/ function _getAddressTokens($address) { $aTokens = array(); $aSpecials = array('(' ,'<' ,',' ,';' ,':'); $aReplace = array(' (',' <',' ,',' ;',' :'); $address = str_replace($aSpecials,$aReplace,$address); $iCnt = strlen($address); $i = 0; while ($i < $iCnt) { $cChar = $address[$i]; switch($cChar) { case '<': $iEnd = strpos($address,'>',$i+1); if (!$iEnd) { $sToken = substr($address,$i); $i = $iCnt; } else { $sToken = substr($address,$i,$iEnd - $i +1); $i = $iEnd; } $sToken = str_replace($aReplace, $aSpecials,$sToken); if ($sToken) $aTokens[] = $sToken; break; case '"': $iEnd = strpos($address,$cChar,$i+1); if ($iEnd) { // skip escaped quotes $prev_char = $address[$iEnd-1]; while ($prev_char === '\\' && substr($address,$iEnd-2,2) !== '\\\\') { $iEnd = strpos($address,$cChar,$iEnd+1); if ($iEnd) { $prev_char = $address[$iEnd-1]; } else { $prev_char = false; } } } if (!$iEnd) { $sToken = substr($address,$i); $i = $iCnt; } else { // also remove the surrounding quotes $sToken = substr($address,$i+1,$iEnd - $i -1); $i = $iEnd; } $sToken = str_replace($aReplace, $aSpecials,$sToken); if ($sToken) $aTokens[] = $sToken; break; case '(': array_pop($aTokens); //remove inserted space $iEnd = strpos($address,')',$i); if (!$iEnd) { $sToken = substr($address,$i); $i = $iCnt; } else { $iDepth = 1; $iComment = $i; while (($iDepth > 0) && (++$iComment < $iCnt)) { $cCharComment = $address[$iComment]; switch($cCharComment) { case '\\': ++$iComment; break; case '(': ++$iDepth; break; case ')': --$iDepth; break; default: break; } } if ($iDepth == 0) { $sToken = substr($address,$i,$iComment - $i +1); $i = $iComment; } else { $sToken = substr($address,$i,$iEnd - $i + 1); $i = $iEnd; } } // 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