- $aTokens = array();
- $aAddress = array();
- $iCnt = strlen($address);
- $aSpecials = array('(' ,'<' ,',' ,';' ,':');
- $aReplace = array(' (',' <',' ,',' ;',' :');
- $address = str_replace($aSpecials,$aReplace,$address);
- $i = $iAddrFound = $bGroup = 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);
- $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 '(':
- $iEnd = strpos($address,')',$i);
- if (!$iEnd) {
- $sToken = substr($address,$i);
- $i = $iCnt;
- } else {
- $sToken = substr($address,$i,$iEnd - $i + 1);
- $i = $iEnd;
- }
- $sToken = str_replace($aReplace, $aSpecials,$sToken);
- $aTokens[] = $sToken;
- break;
- case ',':
- ++$iAddrFound;
- case ';':
- if (!$bGroup) {
- ++$iAddrFound;
- } else {
- $bGroup = false;
- }
- if ($max && $max == $iAddrFound) {
- break 2;
- } else {
- $aTokens[] = $cChar;
- break;
- }
- case ':':
- $bGroup = true;
- case ' ':
- $aTokens[] = $cChar;
- break;
- default:
- $iEnd = strpos($address,' ',$i+1);
- if ($iEnd) {
- $sToken = trim(substr($address,$i,$iEnd - $i));
- $i = $iEnd-1;
- } else {
- $sToken = trim(substr($address,$i));
- $i = $iCnt;
- }
- if ($sToken) $aTokens[] = $sToken;
- }
- ++$i;
- }
- $sPersonal = $sEmail = $sComment = $sGroup = '';
- $aStack = $aComment = array();
- foreach ($aTokens as $sToken) {
- if ($max && $max == count($aAddress)) {
- return $aAddress;
- }
- $cChar = $sToken{0};
- switch ($cChar)
- {
- case '=':
- case '"':
- case ' ':
- $aStack[] = $sToken;
- break;
- case '(':
- $aComment[] = substr($sToken,1,-1);
- break;
- case ';':
- if ($sGroup) {
- $sEmail = trim(implode(' ',$aStack));
- $aAddress[] = array($sGroup,$sEmail);
- $aStack = $aComment = array();
- $sGroup = '';
- break;
- }
- case ',':
- 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 = implode(' ',$aComment);
- $sPersonal .= $sComment;
- }
- $aAddress[] = array($sEmail,$sPersonal);
- $sPersonal = $sComment = $sEmail = '';
- $aStack = $aComment = array();
- break;
- case ':':
- $sGroup = implode(' ',$aStack); break;
- $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 */
- 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 = implode(' ',$aComment);
- $sPersonal .= $sComment;
- }
- $aAddress[] = array($sEmail,$sPersonal);
- return $aAddress;
-}
-