+ $oAddr->mailbox = $sEmail;
+ $oAddr->host = false;
+ }
+ $sEmail = '';
+ $aStack = $aComment = array();
+ return $oAddr;
+ }
+
+ /**
+ * recursive function for parsing address strings and storing them in an address stucture object.
+ * personal name: encoded: =?charset?Q|B?string?=
+ * quoted: "string"
+ * normal: string
+ * email : <mailbox@host>
+ * : mailbox@host
+ * 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 string $address
+ * @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) {
+ $aTokens = $this->getAddressTokens($address);
+ $sPersonal = $sEmail = $sGroup = '';
+ $aStack = $aComment = array();
+ foreach ($aTokens as $sToken) {
+ $cChar = $sToken{0};
+ switch ($cChar)
+ {
+ case '=':
+ case '"':
+ case ' ':
+ $aStack[] = $sToken;
+ break;
+ case '(':
+ $aComment[] = substr($sToken,1,-1);
+ break;
+ case ';':
+ if ($sGroup) {
+ $aAddress[] = $this->createAddressObject($aStack,$aComment,$sEmail,$sGroup);
+ $oAddr = end($aAddress);
+ if(!$oAddr || ((isset($oAddr)) && !$oAddr->mailbox && !$oAddr->personal)) {
+ $sEmail = $sGroup . ':;';
+ }
+ $aAddress[] = $this->createAddressObject($aStack,$aComment,$sEmail,$sGroup);
+ $sGroup = '';
+ $aStack = $aComment = array();
+ break;
+ }
+ case ',':
+ $aAddress[] = $this->createAddressObject($aStack,$aComment,$sEmail,$sGroup);
+ break;
+ case ':':
+ $sGroup = trim(implode(' ',$aStack));
+ $sGroup = preg_replace('/\s+/',' ',$sGroup);
+ $aStack = array();
+ break;
+ case '<':
+ $sEmail = trim(substr($sToken,1,-1));
+ break;
+ case '>':
+ /* skip */
+ break;
+ default: $aStack[] = $sToken; break;
+ }
+ }
+ /* now do the action again for the last address */
+ $aAddress[] = $this->createAddressObject($aStack,$aComment,$sEmail);
+ /* try to lookup the addresses in case of invalid email addresses */
+ $aProcessedAddress = array();
+ foreach ($aAddress as $oAddr) {
+ $aAddrBookAddress = array();
+ if (!$oAddr->host) {
+ $grouplookup = false;
+ if ($lookup) {
+ $aAddr = call_user_func_array($lookup,array($oAddr->mailbox));
+ if (isset($aAddr['email'])) {
+ if (strpos($aAddr['email'],',')) {
+ $grouplookup = true;
+ $aAddrBookAddress = $this->parseAddress($aAddr['email'],true);
+ } else {
+ $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'];
+ } else {
+ $oAddr->personal = encodeHeader($sPersonal);
+ }
+ }
+ }