phpDocumentor pond
[ class tree: pond ] [ index: pond ] [ all elements ]

Source for file rfc822_addresses.php

Documentation is available at rfc822_addresses.php

  1. <?php
  2. /**
  3.  * rfc822_addresses.php
  4.  *
  5.  * @package pond
  6.  */
  7.  
  8. /**
  9.  * {metadocument}<?xml version="1.0" encoding="ISO-8859-1" ?>
  10.  * <class>
  11.  *
  12.  *     <package>net.manuellemos.mimeparser</package>
  13.  *
  14.  *     <copyright>Copyright © (C) Manuel Lemos 2006 - 2008</copyright>
  15.  *     <title>RFC 822 e-mail addresses parser</title>
  16.  *     <author>Manuel Lemos</author>
  17.  *     <authoraddress>mlemos-at-acm.org</authoraddress>
  18.  *
  19.  *     <documentation>
  20.  *         <idiom>en</idiom>
  21.  *         <purpose>Parse e-mail addresses from headers of <link>
  22.  *                 <url>http://www.ietf.org/rfc/rfc822.txt</url>
  23.  *                 <data>RFC 822</data>
  24.  *             </link> compliant e-mail messages.</purpose>
  25.  *         <usage>Use the function <functionlink>ParseAddressList</functionlink>
  26.  *             function to retrieve the list of e-mail addresses contained in
  27.  *             e-mail message headers like <tt>From</tt>, <tt>To</tt>, <tt>Cc</tt>
  28.  *             or <tt>Bcc</tt>.</usage>
  29.  *     </documentation>
  30.  *
  31.  * {/metadocument}
  32.  *
  33.  * @package pond
  34.  */
  35. {
  36.     /* Private variables */
  37.  
  38.     var $v = '';
  39.  
  40.     /* Public variables */
  41.  
  42. /*
  43. {metadocument}
  44.     <variable>
  45.         <name>error</name>
  46.         <type>STRING</type>
  47.         <value></value>
  48.         <documentation>
  49.             <purpose>Store the message that is returned when an error
  50.                 occurs.</purpose>
  51.             <usage>Check this variable to understand what happened when a call to
  52.                 any of the class functions has failed.<paragraphbreak />
  53.                 This class uses cumulative error handling. This means that if one
  54.                 class functions that may fail is called and this variable was
  55.                 already set to an error message due to a failure in a previous call
  56.                 to the same or other function, the function will also fail and does
  57.                 not do anything.<paragraphbreak />
  58.                 This allows programs using this class to safely call several
  59.                 functions that may fail and only check the failure condition after
  60.                 the last function call.<paragraphbreak />
  61.                 Just set this variable to an empty string to clear the error
  62.                 condition.</usage>
  63.         </documentation>
  64.     </variable>
  65. {/metadocument}
  66. */
  67.     var $error = '';
  68.  
  69. /*
  70. {metadocument}
  71.     <variable>
  72.         <name>error_position</name>
  73.         <type>INTEGER</type>
  74.         <value>-1</value>
  75.         <documentation>
  76.             <purpose>Point to the position of the message data or file that
  77.                 refers to the last error that occurred.</purpose>
  78.             <usage>Check this variable to determine the relevant position of the
  79.                 message when a parsing error occurs.</usage>
  80.         </documentation>
  81.     </variable>
  82. {/metadocument}
  83. */
  84.     var $error_position = -1;
  85.  
  86. /*
  87. {metadocument}
  88.     <variable>
  89.         <name>ignore_syntax_errors</name>
  90.         <type>BOOLEAN</type>
  91.         <value>1</value>
  92.         <documentation>
  93.             <purpose>Specify whether the class should ignore syntax errors in
  94.                 malformed addresses.</purpose>
  95.             <usage>Set this variable to <booleanvalue>0</booleanvalue> if it is
  96.                 necessary to verify whether message data may be corrupted due to
  97.                 to eventual bugs in the program that generated the
  98.                 message.<paragraphbreak />
  99.                 Currently the class only ignores some types of syntax errors.
  100.                 Other syntax errors may still cause the
  101.                 <functionlink>ParseAddressList</functionlink> to fail.</usage>
  102.         </documentation>
  103.     </variable>
  104. {/metadocument}
  105. */
  106.     var $ignore_syntax_errors=1;
  107.  
  108. /*
  109. {metadocument}
  110.     <variable>
  111.         <name>warnings</name>
  112.         <type>HASH</type>
  113.         <value></value>
  114.         <documentation>
  115.             <purpose>Return a list of positions of the original message that
  116.                 contain syntax errors.</purpose>
  117.             <usage>Check this variable to retrieve eventual message syntax
  118.                 errors that were ignored when the
  119.                 <variablelink>ignore_syntax_errors</variablelink> is set to
  120.                 <booleanvalue>1</booleanvalue>.<paragraphbreak />
  121.                 The indexes of this array are the positions of the errors. The
  122.                 array values are the corresponding syntax error messages.</usage>
  123.         </documentation>
  124.     </variable>
  125. {/metadocument}
  126. */
  127.     var $warnings=array();
  128.  
  129.     /* Private functions */
  130.  
  131. /**
  132.  * dummy docblock makes error-free autodocs
  133.  */
  134.     Function SetError($error)
  135.     {
  136.         $this->error = $error;
  137.         return(0);
  138.     }
  139.  
  140. /**
  141.  * dummy docblock makes error-free autodocs
  142.  */
  143.     Function SetPositionedError($error$position)
  144.     {
  145.         $this->error_position = $position;
  146.         return($this->SetError($error));
  147.     }
  148.  
  149. /**
  150.  * dummy docblock makes error-free autodocs
  151.  */
  152.     Function SetWarning($warning$position)
  153.     {
  154.         $this->warnings[$position]=$warning;
  155.         return(1);
  156.     }
  157.  
  158. /**
  159.  * dummy docblock makes error-free autodocs
  160.  */
  161.     Function SetPositionedWarning($error$position)
  162.     {
  163.         if(!$this->ignore_syntax_errors)
  164.             return($this->SetPositionedError($error$position));
  165.         return($this->SetWarning($error$position));
  166.     }
  167.  
  168. /**
  169.  * dummy docblock makes error-free autodocs
  170.  */
  171.     Function QDecode($p&$value&$encoding)
  172.     {
  173.         $encoding $charset null;
  174.         $s 0;
  175.         $decoded '';
  176.         $l strlen($value);
  177.         while($s $l)
  178.         {
  179.             if(GetType($q strpos($value'=?'$s)) != 'integer')
  180.             {
  181.                 if($s == 0)
  182.                     return(1);
  183.                 if($s $l)
  184.                     $decoded .= substr($value$s);
  185.                 break;
  186.             }
  187.             if($s $q)
  188.                 $decoded .= substr($value$s$q $s);
  189.             $q += 2;
  190.             if(GetType($c strpos($value'?'$q)) != 'integer'
  191.             || $q == $c)
  192.                 return($this->SetPositionedWarning('invalid Q-encoding character set'$p $q));
  193.             if(IsSet($charset))
  194.             {
  195.                 $another_charset strtolower(substr($value$q$c $q));
  196.                 if(strcmp($charset$another_charset)
  197.                 && strcmp($another_charset'ascii'))
  198.                     return($this->SetWarning('it is not possible to decode an encoded value using mixed character sets into a single value'$p $q));
  199.             }
  200.             else
  201.             {
  202.                 $charset strtolower(substr($value$q$c $q));
  203.                 if(!strcmp($charset'ascii'))
  204.                     $charset null;
  205.             }
  206.             ++$c;
  207.             if(GetType($t strpos($value'?'$c)) != 'integer'
  208.             || $c==$t)
  209.                 return($this->SetPositionedWarning('invalid Q-encoding type'$p $c));
  210.             $type strtolower(substr($value$c$t $c));
  211.             ++$t;
  212.             if(GetType($e strpos($value'?='$t)) != 'integer')
  213.                 return($this->SetPositionedWarning('invalid Q-encoding encoded data'$p $e));
  214.             switch($type)
  215.             {
  216.                 case 'q':
  217.                     for($s $t$s<$e;)
  218.                     {
  219.                         switch($b $value[$s])
  220.                         {
  221.                             case '=':
  222.                                 $h HexDec($hex strtolower(substr($value$s 12)));
  223.                                 if($s $e
  224.                                 || strcmp(sprintf('%02x'$h)$hex))
  225.                                     return($this->SetPositionedWarning('invalid Q-encoding q encoded data'$p $s));
  226.                                 $decoded .= chr($h);
  227.                                 $s += 3;
  228.                                 break;
  229.  
  230.                             case '_':
  231.                                 $decoded .= ' ';
  232.                                 ++$s;
  233.                                 break;
  234.  
  235.                             default:
  236.                                 $decoded .= $b;
  237.                                 ++$s;
  238.                         }
  239.                     }
  240.                     break;
  241.  
  242.                 case 'b':
  243.                     if($e <= $t
  244.                     || strlen($binary base64_decode($data substr($value$t$e $t))) == 0
  245.                     || GetType($binary!= 'string')
  246.                         return($this->SetPositionedWarning('invalid Q-encoding b encoded data'$p $t));
  247.                     $decoded .= $binary;
  248.                     $s $e;
  249.                     break;
  250.  
  251.                 default:
  252.                     return($this->SetPositionedWarning('Q-encoding '.$type.' is not yet supported'$p $c));
  253.             }
  254.             $s += 2;
  255.         }
  256.         $value $decoded;
  257.         $encoding $charset;
  258.         return(1);
  259.     }
  260.  
  261. /**
  262.  * dummy docblock makes error-free autodocs
  263.  */
  264.     Function ParseCText(&$p&$c_text)
  265.     {
  266.         $c_text null;
  267.         $v $this->v;
  268.         if($p<strlen($v)
  269.         && GetType(strchr("\t\r\n ()\\\0"$c $v[$p])) != 'string'
  270.         && Ord($c)<128)
  271.         {
  272.             $c_text $c;
  273.             ++$p;
  274.         }
  275.         return(1);
  276.     }
  277.  
  278. /**
  279.  * dummy docblock makes error-free autodocs
  280.  */
  281.     Function ParseQText(&$p&$q_text)
  282.     {
  283.         $q_text null;
  284.         $v $this->v;
  285.         if($p>strlen($v)
  286.         || GetType(strchr("\t\r\n \"\\\0"$c $v[$p])) == 'string')
  287.             return(1);
  288.         if(Ord($c>= 128)
  289.         {
  290.             if(!$this->ignore_syntax_errors)
  291.                 return(1);
  292.             $this->SetPositionedWarning('it was used an unencoded 8 bit character'$p);
  293.         }
  294.         $q_text $c;
  295.         ++$p;
  296.         return(1);
  297.     }
  298.  
  299. /**
  300.  * dummy docblock makes error-free autodocs
  301.  */
  302.     Function ParseQuotedPair(&$p&$quoted_pair)
  303.     {
  304.         $quoted_pair null;
  305.         $v $this->v;
  306.         $l strlen($v);
  307.         if($p+$l
  308.         && !strcmp($v[$p]'\\')
  309.         && GetType(strchr("\r\n\0"$c $v[$p 1])) != 'string'
  310.         && Ord($c)<128)
  311.         {
  312.             $quoted_pair $c;
  313.             $p += 2;
  314.         }
  315.         return(1);
  316.     }
  317.  
  318. /**
  319.  * dummy docblock makes error-free autodocs
  320.  */
  321.     Function ParseCContent(&$p&$c_content)
  322.     {
  323.         $c_content null;
  324.         $c $p;
  325.         if(!$this->ParseQuotedPair($c$content))
  326.             return(0);
  327.         if(!IsSet($content))
  328.         {
  329.             if(!$this->ParseCText($c$content))
  330.                 return(0);
  331.             if(!IsSet($content))
  332.             {
  333.                 if(!$this->ParseComment($c$content))
  334.                     return(0);
  335.                 if(!IsSet($content))
  336.                     return(1);
  337.             }
  338.         }
  339.         $c_content $content;
  340.         $p $c;
  341.         return(1);
  342.     }
  343.  
  344. /**
  345.  * dummy docblock makes error-free autodocs
  346.  */
  347.     Function SkipWhiteSpace(&$p)
  348.     {
  349.         $v $this->v;
  350.         $l strlen($v);
  351.         for(;$p<$l++$p)
  352.         {
  353.             switch($v[$p])
  354.             {
  355.                 case ' ':
  356.                 case "\n":
  357.                 case "\r":
  358.                 case "\t":
  359.                     break;
  360.                 default:
  361.                     return(1);
  362.             }
  363.         }
  364.         return(1);
  365.     }
  366.  
  367. /**
  368.  * dummy docblock makes error-free autodocs
  369.  */
  370.     Function ParseComment(&$p&$comment)
  371.     {
  372.         $comment null;
  373.         $v $this->v;
  374.         $l strlen($v);
  375.         $c $p;
  376.         if($c >= $l
  377.         || strcmp($v[$c]'('))
  378.             return(1);
  379.         ++$c;
  380.         for($c $l;)
  381.         {
  382.             if(!$this->SkipWhiteSpace($c))
  383.                 return(0);
  384.             if(!$this->ParseCContent($c$c_content))
  385.                 return(0);
  386.             if(!IsSet($c_content))
  387.                 break;
  388.         }
  389.         if(!$this->SkipWhiteSpace($c))
  390.             return(0);
  391.         if($c >= $l
  392.         || strcmp($v[$c]')'))
  393.             return(1);
  394.         ++$c;
  395.         $comment substr($v$p$c $p);
  396.         $p $c;
  397.         return(1);
  398.     }
  399.  
  400. /**
  401.  * dummy docblock makes error-free autodocs
  402.  */
  403.     Function SkipCommentWhiteSpace(&$p)
  404.     {
  405.         $v $this->v;
  406.         $l strlen($v);
  407.         for(;$p<$l;)
  408.         {
  409.             switch($v[$p])
  410.             {
  411.                 case ' ':
  412.                 case "\n":
  413.                 case "\r":
  414.                 case "\t":
  415.                     ++$p;
  416.                     break;
  417.                 case '(':
  418.                     if(!$this->ParseComment($p$comment))
  419.                         return(0);
  420.                 default:
  421.                     return(1);
  422.             }
  423.         }
  424.         return(1);
  425.     }
  426.  
  427. /**
  428.  * dummy docblock makes error-free autodocs
  429.  */
  430.     Function ParseQContent(&$p&$q_content)
  431.     {
  432.         $q_content null;
  433.         $q $p;
  434.         if(!$this->ParseQuotedPair($q$content))
  435.             return(0);
  436.         if(!IsSet($content))
  437.         {
  438.             if(!$this->ParseQText($q$content))
  439.                 return(0);
  440.             if(!IsSet($content))
  441.                 return(1);
  442.         }
  443.         $q_content $content;
  444.         $p $q;
  445.         return(1);
  446.     }
  447.  
  448. /**
  449.  * dummy docblock makes error-free autodocs
  450.  */
  451.     Function ParseAtom(&$p&$atom$dot)
  452.     {
  453.         $atom null;
  454.         $v $this->v;
  455.         $l strlen($v);
  456.         $a $p;
  457.         if(!$this->SkipCommentWhiteSpace($a))
  458.             return(0);
  459.         for($s $a;$a $l;)
  460.         {
  461.             if(preg_match('/^([-'.($dot '.' '').'A-Za-z0-9!#$&\'*+\\/=?^_{|}~]+)/'substr($this->v$a)$m))
  462.                 $a += strlen($m[1]);
  463.             elseif(Ord($v[$a]128)
  464.                 break;
  465.             elseif(!$this->SetPositionedWarning('it was used an unencoded 8 bit character'$a))
  466.                 return(0);
  467.             else
  468.                 ++$a;
  469.         }
  470.         if($s == $a)
  471.             return(1);
  472.         if(!$this->SkipCommentWhiteSpace($a))
  473.             return(0);
  474.         $atom substr($this->v$p$a $p);
  475.         $p $a;
  476.         return(1);
  477.     }
  478.  
  479. /**
  480.  * dummy docblock makes error-free autodocs
  481.  */
  482.     Function ParseQuotedString(&$p&$quoted_string)
  483.     {
  484.         $quoted_string null;
  485.         $v $this->v;
  486.         $l strlen($v);
  487.         $s $p;
  488.         if(!$this->SkipCommentWhiteSpace($s))
  489.             return(0);
  490.         if($s >= $l
  491.         || strcmp($v[$s]'"'))
  492.             return(1);
  493.         ++$s;
  494.         for($string '';$s $l;)
  495.         {
  496.             $w $s;
  497.             if(!$this->SkipWhiteSpace($s))
  498.                 return(0);
  499.             if($w != $s)
  500.                 $string .= substr($v$w$s $w);
  501.             if(!$this->ParseQContent($s$q_content))
  502.                 return(0);
  503.             if(!IsSet($q_content))
  504.                 break;
  505.             $string .= $q_content;
  506.         }
  507.             $w $s;
  508.         if(!$this->SkipWhiteSpace($s))
  509.             return(0);
  510.         if($w != $s)
  511.             $string .= substr($v$w$s $w);
  512.         if($s >= $l
  513.         || strcmp($v[$s]'"'))
  514.             return(1);
  515.         ++$s;
  516.         if(!$this->SkipCommentWhiteSpace($s))
  517.             return(0);
  518.         $quoted_string $string;
  519.         $p $s;
  520.         return(1);
  521.     }
  522.  
  523. /**
  524.  * dummy docblock makes error-free autodocs
  525.  */
  526.     Function ParseWord(&$p&$word)
  527.     {
  528.         $word null;
  529.         if(!$this->ParseQuotedString($p$word))
  530.             return(0);
  531.         if(IsSet($word))
  532.             return(1);
  533.         if(!$this->ParseAtom($p$word0))
  534.             return(0);
  535.         return(1);
  536.     }
  537.  
  538. /**
  539.  * dummy docblock makes error-free autodocs
  540.  */
  541.     Function ParseObsPhrase(&$p&$obs_phrase)
  542.     {
  543.         $obs_phrase null;
  544.         $v $this->v;
  545.         $l strlen($v);
  546.         $ph $p;
  547.         if(!$this->ParseWord($ph$word))
  548.             return(0);
  549.         $string $word;
  550.         for(;;)
  551.         {
  552.             if(!$this->ParseWord($ph$word))
  553.                 return(0);
  554.             if(IsSet($word))
  555.             {
  556.                 $string .= $word;
  557.                 continue;
  558.             }
  559.             $w $ph;
  560.             if(!$this->SkipCommentWhiteSpace($ph))
  561.                 return(0);
  562.             if($w != $ph)
  563.             {
  564.                 $string .= substr($v$w$ph $w);
  565.                 continue;
  566.             }
  567.             if($ph >= $l
  568.             || strcmp($v[$ph]'.'))
  569.                 break;
  570.             $string .= '.';
  571.             ++$ph;
  572.         }
  573.         $obs_phrase $string;
  574.         $p $ph;
  575.         return(1);
  576.     }
  577.  
  578. /**
  579.  * dummy docblock makes error-free autodocs
  580.  */
  581.     Function ParsePhrase(&$p&$phrase)
  582.     {
  583.         $phrase null;
  584.         if(!$this->ParseObsPhrase($p$phrase))
  585.             return(0);
  586.         if(IsSet($phrase))
  587.             return(1);
  588.         $ph $p;
  589.         if(!$this->ParseWord($ph$word))
  590.             return(0);
  591.         $string $word;
  592.         for(;;)
  593.         {
  594.             if(!$this->ParseWord($ph$word))
  595.                 return(0);
  596.             if(!IsSet($word))
  597.                 break;
  598.             $string .= $word;
  599.         }
  600.         $phrase $string;
  601.         $p $ph;
  602.         return(1);
  603.     }
  604.  
  605. /**
  606.  * dummy docblock makes error-free autodocs
  607.  */
  608.     Function ParseAddrSpec(&$p&$addr_spec)
  609.     {
  610.         $addr_spec null;
  611.         $v $this->v;
  612.         $l strlen($v);
  613.         $a $p;
  614.         if(!$this->ParseQuotedString($a$local_part))
  615.             return(0);
  616.         if(!IsSet($local_part))
  617.         {
  618.             if(!$this->ParseAtom($a$local_part1))
  619.                 return(0);
  620.             $local_part trim($local_part);
  621.         }
  622.         if($a >= $l
  623.         || strcmp($v[$a]'@'))
  624.             return(1);
  625.         ++$a;
  626.         if(!$this->ParseAtom($a$domain1))
  627.             return(0);
  628.         if(!IsSet($domain))
  629.             return(1);
  630.         $addr_spec $local_part.'@'.$domain;
  631.         $p $a;
  632.         return(1);
  633.     }
  634.  
  635. /**
  636.  * dummy docblock makes error-free autodocs
  637.  */
  638.     Function ParseAngleAddr(&$p&$addr)
  639.     {
  640.         $addr null;
  641.         $v $this->v;
  642.         $l strlen($v);
  643.         $a $p;
  644.         if(!$this->SkipCommentWhiteSpace($a))
  645.             return(0);
  646.         if($a >= $l
  647.         || strcmp($v[$a]'<'))
  648.             return(1);
  649.         ++$a;
  650.         if(!$this->ParseAddrSpec($a$addr_spec))
  651.             return(0);
  652.         if($a >= $l
  653.         || strcmp($v[$a]'>'))
  654.             return(1);
  655.         ++$a;
  656.         if(!$this->SkipCommentWhiteSpace($a))
  657.             return(0);
  658.         $addr $addr_spec;
  659.         $p $a;
  660.         return(1);
  661.     }
  662.  
  663. /**
  664.  * dummy docblock makes error-free autodocs
  665.  */
  666.     Function ParseNameAddr(&$p&$address)
  667.     {
  668.         $address null;
  669.         $a $p;
  670.         if(!$this->ParsePhrase($a$display_name))
  671.             return(0);
  672.         if(!$this->ParseAngleAddr($a$addr))
  673.             return(0);
  674.         if(!IsSet($addr))
  675.             return(1);
  676.         $address array('address'=>$addr);
  677.         if(IsSet($display_name))
  678.         {
  679.             if(!$this->QDecode($p$display_name$encoding))
  680.                 return(0);
  681.             $address['name'trim($display_name);
  682.             if(IsSet($encoding))
  683.                 $address['encoding'$encoding;
  684.         }
  685.         $p $a;
  686.         return(1);
  687.     }
  688.  
  689. /**
  690.  * dummy docblock makes error-free autodocs
  691.  */
  692.     Function ParseAddrNameAddr(&$p&$address)
  693.     {
  694.         $address null;
  695.         $a $p;
  696.         if(!$this->ParseAddrSpec($a$display_name))
  697.             return(0);
  698.         if(!IsSet($display_name))
  699.             return(1);
  700.         if(!$this->ParseAngleAddr($a$addr))
  701.             return(0);
  702.         if(!IsSet($addr))
  703.             return(1);
  704.         if(!$this->QDecode($p$display_name$encoding))
  705.             return(0);
  706.         $address array(
  707.             'address'=>$addr,
  708.             'name' => trim($display_name)
  709.         );
  710.         if(IsSet($encoding))
  711.             $address['encoding'$encoding;
  712.         $p $a;
  713.         return(1);
  714.     }
  715.  
  716. /**
  717.  * dummy docblock makes error-free autodocs
  718.  */
  719.     Function ParseMailbox(&$p&$address)
  720.     {
  721.         $address null;
  722.         if($this->ignore_syntax_errors)
  723.         {
  724.             $a $p;
  725.             if(!$this->ParseAddrNameAddr($p$address))
  726.                 return(0);
  727.             if(IsSet($address))
  728.                 return($this->SetPositionedWarning('it was an unquoted address as name'$a));
  729.         }
  730.         if(!$this->ParseNameAddr($p$address))
  731.             return(0);
  732.         if(IsSet($address))
  733.             return(1);
  734.         if(!$this->ParseAddrSpec($p$addr_spec))
  735.             return(0);
  736.         if(IsSet($addr_spec))
  737.             $address array('address'=>$addr_spec);
  738.         return(1);
  739.     }
  740.  
  741. /**
  742.  * dummy docblock makes error-free autodocs
  743.  */
  744.     Function ParseMailboxGroup(&$p&$mailbox_group)
  745.     {
  746.         $v $this->v;
  747.         $l strlen($v);
  748.         $g $p;
  749.         if(!$this->ParseMailbox($g$address))
  750.             return(0);
  751.         if(!IsSet($address))
  752.             return(1);
  753.         $addresses array($address);
  754.         for(;$g $l;)
  755.         {
  756.             if(strcmp($v[$g]','))
  757.                 break;
  758.             ++$g;
  759.             if(!$this->ParseMailbox($g$address))
  760.                 return(0);
  761.             if(!IsSet($address))
  762.                 return(1);
  763.             $addresses[$address;
  764.         }
  765.         $mailbox_group $addresses;
  766.         $p $g;
  767.         return(1);
  768.     }
  769.  
  770. /**
  771.  * dummy docblock makes error-free autodocs
  772.  */
  773.     Function ParseGroup(&$p&$address)
  774.     {
  775.         $address null;
  776.         $v $this->v;
  777.         $l strlen($v);
  778.         $g $p;
  779.         if(!$this->ParsePhrase($g$display_name))
  780.             return(0);
  781.         if(!IsSet($display_name)
  782.         || $g >= $l
  783.         || strcmp($v[$g]':'))
  784.             return(1);
  785.         ++$g;
  786.         if(!$this->ParseMailboxGroup($g$mailbox_group))
  787.             return(0);
  788.         if(!IsSet($mailbox_group))
  789.         {
  790.             if(!$this->SkipCommentWhiteSpace($g))
  791.                 return(0);
  792.             $mailbox_group array();
  793.         }
  794.         if($g >= $l
  795.         || strcmp($v[$g]';'))
  796.             return(1);
  797.         $c = ++$g;
  798.         if($this->SkipCommentWhiteSpace($g)
  799.         && $g $c
  800.         && !$this->SetPositionedWarning('it were used invalid comments after a group of addresses'$c))
  801.             return(0);
  802.         if(!$this->QDecode($p$display_name$encoding))
  803.             return(0);
  804.         $address array(
  805.             'name'=>$display_name,
  806.             'group'=>$mailbox_group
  807.         );
  808.         if(IsSet($encoding))
  809.             $address['encoding'$encoding;
  810.         $p $g;
  811.         return(1);
  812.     }
  813.  
  814. /**
  815.  * dummy docblock makes error-free autodocs
  816.  */
  817.     Function ParseAddress(&$p&$address)
  818.     {
  819.         $address null;
  820.         if(!$this->ParseGroup($p$address))
  821.             return(0);
  822.         if(!IsSet($address))
  823.         {
  824.             if(!$this->ParseMailbox($p$address))
  825.                 return(0);
  826.         }
  827.         return(1);
  828.     }
  829.  
  830.     /* Public functions */
  831.  
  832. /*
  833. {metadocument}
  834.     <function>
  835.         <name>ParseAddressList</name>
  836.         <type>BOOLEAN</type>
  837.         <documentation>
  838.             <purpose>Parse and extract e-mail addresses eventually from headers
  839.                 of an e-mail message.</purpose>
  840.             <usage>Pass a string value with a list of e-mail addresses to the
  841.                 <argumentlink>
  842.                     <function>ParseAddressList</function>
  843.                     <argument>value</argument>
  844.                 </argumentlink>. The <argumentlink>
  845.                     <function>ParseAddressList</function>
  846.                     <argument>addresses</argument>
  847.                 </argumentlink> returns the list of e-mail addresses found.</usage>
  848.             <returnvalue>This function returns <booleanvalue>1</booleanvalue> if
  849.                 the specified value is parsed successfully. Otherwise,
  850.                 check the variables <variablelink>error</variablelink> and
  851.                 <variablelink>error_position</variablelink> to determine what
  852.                 error occurred and the relevant value position.</returnvalue>
  853.         </documentation>
  854.         <argument>
  855.             <name>value</name>
  856.             <type>STRING</type>
  857.             <documentation>
  858.                 <purpose>String with a list of e-mail addresses to parse.</purpose>
  859.             </documentation>
  860.         </argument>
  861.         <argument>
  862.             <name>addresses</name>
  863.             <type>ARRAY</type>
  864.             <out />
  865.             <documentation>
  866.                 <purpose>Return the list of parsed e-mail addresses.
  867.                     Each entry in the list is an associative array.<paragraphbreak />
  868.                     For normal addresses, this associative array has the entry
  869.                     <stringvalue>address</stringvalue> set to the e-mail address.
  870.                     If the address has an associated name, it is stored in the
  871.                     entry <stringvalue>name</stringvalue>.<paragraphbreak />
  872.                     For address groups, there is the entry
  873.                     <stringvalue>name</stringvalue>.
  874.                     The group addresses list are stored in the entry
  875.                     <stringvalue>group</stringvalue> as an array. The structure of
  876.                     the group addresses list array is the same as this addresses
  877.                     list array argument.</purpose>
  878.             </documentation>
  879.         </argument>
  880.         <do>
  881. {/metadocument}
  882. */
  883. /**
  884.  * dummy docblock makes error-free autodocs
  885.  */
  886.     Function ParseAddressList($value&$addresses)
  887.     {
  888.         $this->warnings = array();
  889.         $addresses array();
  890.         $this->v = $v $value;
  891.         $l strlen($v);
  892.         $p 0;
  893.         if(!$this->ParseAddress($p$address))
  894.             return(0);
  895.         if(!IsSet($address))
  896.             return($this->SetPositionedError('it was not specified a valid address'$p));
  897.         $addresses[$address;
  898.         while($p $l)
  899.         {
  900.             if(strcmp($v[$p]','))
  901.                 return($this->SetPositionedError('multiple addresses must be separated by commas: '$p));
  902.             ++$p;
  903.             if(!$this->ParseAddress($p$address))
  904.                 return(0);
  905.             if(!IsSet($address))
  906.                 return($this->SetPositionedError('it was not specified a valid address after comma'$p));
  907.             $addresses[$address;
  908.         }
  909.         return(1);
  910.     }
  911. /*
  912. {metadocument}
  913.         </do>
  914.     </function>
  915. {/metadocument}
  916. */
  917.  
  918. };
  919.  
  920. /*
  921.  
  922. {metadocument}
  923. </class>
  924. {/metadocument}
  925.  
  926. */
  927.  
  928. ?>