Source for file Message.class.php

Documentation is available at Message.class.php

  1. <?php
  2.  
  3. /**
  4.  * Message.class.php
  5.  *
  6.  * This file contains functions needed to handle mime messages.
  7.  *
  8.  * @copyright &copy; 2003-2006 The SquirrelMail Project Team
  9.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  10.  * @version $Id: Message.class.php,v 1.17.2.14 2006/02/03 22:27:46 jervfors Exp $
  11.  * @package squirrelmail
  12.  * @subpackage mime
  13.  * @since 1.3.2
  14.  */
  15.  
  16. /**
  17.  * The object that contains a message.
  18.  *
  19.  * message is the object that contains messages. It is a recursive object in
  20.  * that through the $entities variable, it can contain more objects of type
  21.  * message. See documentation in mime.txt for a better description of how this
  22.  * works.
  23.  * @package squirrelmail
  24.  * @subpackage mime
  25.  * @since 1.3.0
  26.  */
  27. class Message {
  28.     /**
  29.      * rfc822header object
  30.      * @var object 
  31.      */
  32.     var $rfc822_header = '';
  33.     /**
  34.      * MessageHeader object
  35.      * @var object 
  36.      */
  37.     var $mime_header = '';
  38.     /**
  39.      * @var mixed 
  40.      */
  41.     var $flags = '';
  42.     /**
  43.      * Media type
  44.      * @var string 
  45.      */
  46.     var $type0='';
  47.     /**
  48.      * Media subtype
  49.      * @var string 
  50.      */
  51.     var $type1='';
  52.     /**
  53.      * Nested mime parts
  54.      * @var array 
  55.      */
  56.     var $entities = array();
  57.     /**
  58.      * Message part id
  59.      * @var string 
  60.      */
  61.     var $entity_id = '';
  62.     /**
  63.      * Parent message part id
  64.      * @var string 
  65.      */
  66.     var $parent_ent;
  67.     /**
  68.      * @var mixed 
  69.      */
  70.     var $entity;
  71.     /**
  72.      * @var mixed 
  73.      */
  74.     var $parent = '';
  75.     /**
  76.      * @var string 
  77.      */
  78.     var $decoded_body='';
  79.     /**
  80.      * Message \seen status
  81.      * @var boolean 
  82.      */
  83.     var $is_seen = 0;
  84.     /**
  85.      * Message \answered status
  86.      * @var boolean 
  87.      */
  88.     var $is_answered = 0;
  89.     /**
  90.      * Message \deleted status
  91.      * @var boolean 
  92.      */
  93.     var $is_deleted = 0;
  94.     /**
  95.      * Message \flagged status
  96.      * @var boolean 
  97.      */
  98.     var $is_flagged = 0;
  99.     /**
  100.      * Message mdn status
  101.      * @var boolean 
  102.      */
  103.     var $is_mdnsent = 0;
  104.     /**
  105.      * Message text body
  106.      * @var string 
  107.      */
  108.     var $body_part = '';
  109.     /**
  110.      * Message part offset
  111.      * for fetching body parts out of raw messages
  112.      * @var integer 
  113.      */
  114.     var $offset = 0;
  115.     /**
  116.      * Message part length
  117.      * for fetching body parts out of raw messages
  118.      * @var integer 
  119.      */
  120.     var $length = 0;
  121.     /**
  122.      * Local attachment filename location where the tempory attachment is
  123.      * stored. For use in delivery class.
  124.      * @var string 
  125.      */
  126.     var $att_local_name = '';
  127.  
  128.     /**
  129.      * @param string $ent entity id
  130.      */
  131.     function setEnt($ent{
  132.         $this->entity_id$ent;
  133.     }
  134.  
  135.     /**
  136.      * Add nested message part
  137.      * @param object $msg 
  138.      */
  139.     function addEntity ($msg{
  140.         $this->entities[$msg;
  141.     }
  142.  
  143.     /**
  144.      * Get file name used for mime part
  145.      * @return string file name
  146.      * @since 1.3.2
  147.      */
  148.     function getFilename({
  149.         $filename '';
  150.         $filename $this->header->getParameter('filename');
  151.         if (!$filename{
  152.             $filename $this->header->getParameter('name');
  153.         }
  154.  
  155.         if (!$filename{
  156.             $filename 'untitled-'.$this->entity_id;
  157.         }
  158.         return $filename;
  159.     }
  160.  
  161.     /**
  162.      * Add header object to message object.
  163.      * WARNING: Unfinished code. Don't expect it to work in older sm versions.
  164.      * @param mixed $read array or string with message headers
  165.      * @todo FIXME: rfc822header->parseHeader() does not return rfc822header object
  166.      */
  167.     function addRFC822Header($read{
  168.         $header new Rfc822Header();
  169.         $this->rfc822_header = $header->parseHeader($read);
  170.     }
  171.  
  172.     /**
  173.      * @param string $ent 
  174.      * @return mixed (object or string?)
  175.      */
  176.     function getEntity($ent{
  177.         $cur_ent $this->entity_id;
  178.         $msg $this;
  179.         if (($cur_ent == ''|| ($cur_ent == '0')) {
  180.             $cur_ent_a array();
  181.         else {
  182.             $cur_ent_a explode('.'$this->entity_id);
  183.         }
  184.         $ent_a explode('.'$ent);
  185.  
  186.         for ($i 0,$entCount count($ent_a1$i $entCount++$i{
  187.             if (isset($cur_ent_a[$i]&& ($cur_ent_a[$i!= $ent_a[$i])) {
  188.                 $msg $msg->parent;
  189.                 $cur_ent_a explode('.'$msg->entity_id);
  190.                 --$i;
  191.             else if (!isset($cur_ent_a[$i])) {
  192.                 if (isset($msg->entities[($ent_a[$i]-1)])) {
  193.                     $msg $msg->entities[($ent_a[$i]-1)];
  194.                 else {
  195.                     $msg $msg->entities[0];
  196.                 }
  197.             }
  198.             if (($msg->type0 == 'message'&& ($msg->type1 == 'rfc822')) {
  199.                 /*this is a header for a message/rfc822 entity */
  200.                 $msg $msg->entities[0];
  201.             }
  202.         }
  203.  
  204.         if (($msg->type0 == 'message'&& ($msg->type1 == 'rfc822')) {
  205.             /*this is a header for a message/rfc822 entity */
  206.             $msg $msg->entities[0];
  207.         }
  208.  
  209.         if (isset($msg->entities[($ent_a[$entCount])-1])) {
  210.             if (is_object($msg->entities[($ent_a[$entCount])-1])) {
  211.                 $msg $msg->entities[($ent_a[$entCount]-1)];
  212.             }
  213.         }
  214.  
  215.         return $msg;
  216.     }
  217.  
  218.     /**
  219.      * Set message body
  220.      * @param string $s message body
  221.      */
  222.     function setBody($s{
  223.         $this->body_part = $s;
  224.     }
  225.  
  226.     /**
  227.      * Clean message object
  228.      */
  229.     function clean_up({
  230.         $msg $this;
  231.         $msg->body_part '';
  232.  
  233.         foreach ($msg->entities as $m{
  234.             $m->clean_up();
  235.         }
  236.     }
  237.  
  238.     /**
  239.      * @return string 
  240.      */
  241.     function getMailbox({
  242.         $msg $this;
  243.         while (is_object($msg->parent)) {
  244.             $msg $msg->parent;
  245.         }
  246.         return $msg->mailbox;
  247.     }
  248.  
  249.     /*
  250.      * Bodystructure parser, a recursive function for generating the
  251.      * entity-tree with all the mime-parts.
  252.      *
  253.      * It follows RFC2060 and stores all the described fields in the
  254.      * message object.
  255.      *
  256.      * Question/Bugs:
  257.      *
  258.      * Ask for me (Marc Groot Koerkamp, [email protected])
  259.      * @param string $read
  260.      * @param integer $i
  261.      * @param mixed $sub_msg
  262.      * @return object Message object
  263.      * @todo define argument and return types
  264.      */
  265.     function parseStructure($read&$i$sub_msg ''{
  266.         $msg Message::parseBodyStructure($read$i$sub_msg);
  267.         if($msg$msg->setEntIds($msg,false,0);
  268.         return $msg;
  269.     }
  270.  
  271.     /**
  272.      * @param object $msg 
  273.      * @param mixed $init 
  274.      * @param integer $i 
  275.      * @todo document me
  276.      * @since 1.4.0
  277.      */
  278.     function setEntIds(&$msg,$init=false,$i=0{
  279.         $iCnt count($msg->entities);
  280.         if ($init !==false{
  281.             $iEntSub $i+1;
  282.             if ($msg->parent->type0 == 'message' &&
  283.                 $msg->parent->type1 == 'rfc822' &&
  284.                 $msg->type0 == 'multipart'{
  285.                 $iEntSub '0';
  286.             }
  287.             if ($init{
  288.                 $msg->entity_id "$init.$iEntSub";
  289.             else {
  290.                 $msg->entity_id $iEntSub;
  291.             }
  292.         else if ($iCnt{
  293.             $msg->entity_id='0';
  294.         else {
  295.             $msg->entity_id='1';
  296.         }
  297.         for ($i=0;$i<$iCnt;++$i{
  298.             $msg->entities[$i]->parent =$msg;
  299.             if (strrchr($msg->entity_id'.'!= '.0'{
  300.                 $msg->entities[$i]->setEntIds($msg->entities[$i],$msg->entity_id,$i);
  301.             else {
  302.                 $msg->entities[$i]->setEntIds($msg->entities[$i],$msg->parent->entity_id,$i);
  303.             }
  304.         }
  305.     }
  306.  
  307.     /**
  308.      * @param string $read 
  309.      * @param integer $i 
  310.      * @param mixed $sub_msg 
  311.      * @return object Message object
  312.      * @todo document me
  313.      * @since 1.4.0 (code was part of parseStructure() in 1.3.x)
  314.      */
  315.     function parseBodyStructure($read&$i$sub_msg ''{
  316.         $arg_no 0;
  317.         $arg_a  array();
  318.         if ($sub_msg{
  319.             $message $sub_msg;
  320.         else {
  321.             $message new Message();
  322.         }
  323.  
  324.         for ($cnt strlen($read)$i $cnt++$i{
  325.             $char strtoupper($read{$i});
  326.             switch ($char{
  327.                 case '(':
  328.                     switch($arg_no{
  329.                         case 0:
  330.                             if (!isset($msg)) {
  331.                                 $msg new Message();
  332.                                 $hdr new MessageHeader();
  333.                                 $hdr->type0 'text';
  334.                                 $hdr->type1 'plain';
  335.                                 $hdr->encoding 'us-ascii';
  336.                             else {
  337.                                 $msg->header->type0 'multipart';
  338.                                 $msg->type0 'multipart';
  339.                                 while ($read{$i== '('{
  340.                                     $msg->addEntity($msg->parseBodyStructure($read$i$msg));
  341.                                 }
  342.                             }
  343.                             break;
  344.                         case 1:
  345.                             /* multipart properties */
  346.                             ++$i;
  347.                             $arg_a[$msg->parseProperties($read$i);
  348.                             ++$arg_no;
  349.                             break;
  350.                         case 2:
  351.                             if (isset($msg->type0&& ($msg->type0 == 'multipart')) {
  352.                                 ++$i;
  353.                                 $arg_a[$msg->parseDisposition($read$i);
  354.                             else /* properties */
  355.                                 $arg_a[$msg->parseProperties($read$i);
  356.                             }
  357.                             ++$arg_no;
  358.                             break;
  359.                         case 3:
  360.                             if (isset($msg->type0&& ($msg->type0 == 'multipart')) {
  361.                                 ++$i;
  362.                                 $arg_a[]$msg->parseLanguage($read$i);
  363.                             }
  364.                         case 7:
  365.                             if (($arg_a[0== 'message'&& ($arg_a[1== 'rfc822')) {
  366.                                 $msg->header->type0 $arg_a[0];
  367.                                 $msg->header->type1 $arg_a[1];
  368.                                 $msg->type0 $arg_a[0];
  369.                                 $msg->type1 $arg_a[1];
  370.                                 $rfc822_hdr new Rfc822Header();
  371.                                 $msg->rfc822_header $msg->parseEnvelope($read$i$rfc822_hdr);
  372.                                 while (($i $cnt&& ($read{$i!= '(')) {
  373.                                     ++$i;
  374.                                 }
  375.                                 $msg->addEntity($msg->parseBodyStructure($read$i,$msg));
  376.                             }
  377.                             break;
  378.                         case 8:
  379.                             ++$i;
  380.                             $arg_a[$msg->parseDisposition($read$i);
  381.                             ++$arg_no;
  382.                             break;
  383.                         case 9:
  384.                             ++$i;
  385.                             if (($arg_a[0== 'text'|| (($arg_a[0== 'message'&& ($arg_a[1== 'rfc822'))) {
  386.                                 $arg_a[$msg->parseDisposition($read$i);
  387.                             else {
  388.                                 $arg_a[$msg->parseLanguage($read$i);
  389.                             }
  390.                             ++$arg_no;
  391.                             break;
  392.                        case 10:
  393.                            if (($arg_a[0== 'text'|| (($arg_a[0== 'message'&& ($arg_a[1== 'rfc822'))) {
  394.                                ++$i;
  395.                                $arg_a[$msg->parseLanguage($read$i);
  396.                            else {
  397.                                $i $msg->parseParenthesis($read$i);
  398.                                $arg_a[''/* not yet described in rfc2060 */
  399.                            }
  400.                            ++$arg_no;
  401.                            break;
  402.                        default:
  403.                            /* unknown argument, skip this part */
  404.                            $i $msg->parseParenthesis($read$i);
  405.                            $arg_a['';
  406.                            ++$arg_no;
  407.                            break;
  408.                    /* switch */
  409.                    break;
  410.                 case '"':
  411.                     /* inside an entity -> start processing */
  412.                     $arg_s $msg->parseQuote($read$i);
  413.                     ++$arg_no;
  414.                     if ($arg_no 3{
  415.                         $arg_s strtolower($arg_s)/* type0 and type1 */
  416.                     }
  417.                     $arg_a[$arg_s;
  418.                     break;
  419.                 case 'n':
  420.                 case 'N':
  421.                     /* probably NIL argument */
  422.                     $tmpnil strtoupper(substr($read$i4));
  423.                     if ($tmpnil == 'NIL ' || $tmpnil == 'NIL)'{
  424.                         $arg_a['';
  425.                         ++$arg_no;
  426.                         $i += 2;
  427.                     }
  428.                     break;
  429.                 case '{':
  430.                     /* process the literal value */
  431.                     $arg_a[$msg->parseLiteral($read$i);
  432.                     ++$arg_no;
  433.                     break;
  434.         case '0':
  435.                 case is_numeric($read{$i}):
  436.                     /* process integers */
  437.                     if ($read{$i== ' 'break}
  438.             ++$arg_no;
  439.             if (preg_match('/^([0-9]+).*/',substr($read,$i)$regs)) {
  440.                 $i += strlen($regs[1])-1;
  441.                 $arg_a[$regs[1];
  442.             else {
  443.                 $arg_a[0;
  444.             }
  445.                     break;
  446.                 case ')':
  447.                     $multipart (isset($msg->type0&& ($msg->type0 == 'multipart'));
  448.                     if (!$multipart{
  449.                         $shifted_args (($arg_a[0== 'text'|| (($arg_a[0== 'message'&& ($arg_a[1== 'rfc822')));
  450.                         $hdr->type0 $arg_a[0];
  451.                         $hdr->type1 $arg_a[1];
  452.  
  453.                         $msg->type0 $arg_a[0];
  454.                         $msg->type1 $arg_a[1];
  455.                         $arr $arg_a[2];
  456.                         if (is_array($arr)) {
  457.                             $hdr->parameters $arg_a[2];
  458.                         }
  459.                         $hdr->id str_replace('<'''str_replace('>'''$arg_a[3]));
  460.                         $hdr->description $arg_a[4];
  461.                         $hdr->encoding strtolower($arg_a[5]);
  462.                         $hdr->entity_id $msg->entity_id;
  463.                         $hdr->size $arg_a[6];
  464.                         if ($shifted_args{
  465.                             $hdr->lines $arg_a[7];
  466.                             $s 1;
  467.                         else {
  468.                             $s 0;
  469.                         }
  470.                         $hdr->md5 (isset($arg_a[7+$s]$arg_a[7+$s$hdr->md5);
  471.                         $hdr->disposition (isset($arg_a[8+$s]$arg_a[8+$s$hdr->disposition);
  472.                         $hdr->language (isset($arg_a[9+$s]$arg_a[9+$s$hdr->language);
  473.                         $msg->header $hdr;
  474.                     else {
  475.                         $hdr->type0 'multipart';
  476.                         $hdr->type1 $arg_a[0];
  477.                         $msg->type0 'multipart';
  478.                         $msg->type1 $arg_a[0];
  479.                         $hdr->parameters (isset($arg_a[1]$arg_a[1$hdr->parameters);
  480.                         $hdr->disposition (isset($arg_a[2]$arg_a[2$hdr->disposition);
  481.                         $hdr->language (isset($arg_a[3]$arg_a[3$hdr->language);
  482.                         $msg->header $hdr;
  483.                     }
  484.                     return $msg;
  485.                 defaultbreak;
  486.             /* switch */
  487.         /* for */
  488.     /* parsestructure */
  489.  
  490.     /**
  491.      * @param string $read 
  492.      * @param integer $i 
  493.      * @return array 
  494.      */
  495.     function parseProperties($read&$i{
  496.         $properties array();
  497.         $prop_name '';
  498.  
  499.         for ($read{$i!= ')'++$i{
  500.             $arg_s '';
  501.             if ($read{$i== '"'{
  502.                 $arg_s $this->parseQuote($read$i);
  503.             else if ($read{$i== '{'{
  504.                 $arg_s $this->parseLiteral($read$i);
  505.             }
  506.  
  507.             if ($arg_s != ''{
  508.                 if ($prop_name == ''{
  509.                     $prop_name strtolower($arg_s);
  510.                     $properties[$prop_name'';
  511.                 else if ($prop_name != ''{
  512.                     $properties[$prop_name$arg_s;
  513.                     $prop_name '';
  514.                 }
  515.             }
  516.         }
  517.         return $properties;
  518.     }
  519.  
  520.     /**
  521.      * @param string $read 
  522.      * @param integer $i 
  523.      * @param object $hdr MessageHeader object
  524.      * @return object MessageHeader object
  525.      */
  526.     function parseEnvelope($read&$i$hdr{
  527.         $arg_no 0;
  528.         $arg_a array();
  529.         ++$i;
  530.         for ($cnt strlen($read)($i $cnt&& ($read{$i!= ')')++$i{
  531.             $char strtoupper($read{$i});
  532.             switch ($char{
  533.                 case '"':
  534.                     $arg_a[$this->parseQuote($read$i);
  535.                     ++$arg_no;
  536.                     break;
  537.                 case '{':
  538.                     $arg_a[$this->parseLiteral($read$i);
  539.             /* temp bugfix (SM 1.5 will have a working clean version)
  540.                too much work to implement that version right now */
  541. //            --$i;
  542.                     ++$arg_no;
  543.                     break;
  544.                 case 'N':
  545.                     /* probably NIL argument */
  546.                     if (strtoupper(substr($read$i3)) == 'NIL'{
  547.                         $arg_a['';
  548.                         ++$arg_no;
  549.                         $i += 2;
  550.                     }
  551.                     break;
  552.                 case '(':
  553.                     /* Address structure (with group support)
  554.                      * Note: Group support is useless on SMTP connections
  555.                      *       because the protocol doesn't support it
  556.                      */
  557.                     $addr_a array();
  558.                     $group '';
  559.                     $a=0;
  560.                     for ($i $cnt && $read{$i!= ')'++$i{
  561.                         if ($read{$i== '('{
  562.                             $addr $this->parseAddress($read$i);
  563.                             if (($addr->host == ''&& ($addr->mailbox != '')) {
  564.                                 /* start of group */
  565.                                 $group $addr->mailbox;
  566.                                 $group_addr $addr;
  567.                                 $j $a;
  568.                             else if ($group && ($addr->host == ''&& ($addr->mailbox == '')) {
  569.                                /* end group */
  570.                                 if ($a == ($j+1)) /* no group members */
  571.                                     $group_addr->group $group;
  572.                                     $group_addr->mailbox '';
  573.                                     $group_addr->personal "$groupUndisclosed recipients;";
  574.                                     $addr_a[$group_addr;
  575.                                     $group ='';
  576.                                 }
  577.                             else {
  578.                                 $addr->group $group;
  579.                                 $addr_a[$addr;
  580.                             }
  581.                             ++$a;
  582.                         }
  583.                     }
  584.                     $arg_a[$addr_a;
  585.                     break;
  586.                 defaultbreak;
  587.             }
  588.         }
  589.  
  590.         if (count($arg_a9{
  591.             $d strtr($arg_a[0]array('  ' => ' '));
  592.             $d explode(' '$d);
  593.         if (!$arg_a[1]$arg_a[1_("(no subject)");
  594.  
  595.             $hdr->date getTimeStamp($d)/* argument 1: date */
  596.             $hdr->subject $arg_a[1];     /* argument 2: subject */
  597.             $hdr->from is_array($arg_a[2]$arg_a[2][0'';     /* argument 3: from        */
  598.             $hdr->sender is_array($arg_a[3]$arg_a[3][0'';   /* argument 4: sender      */
  599.             $hdr->replyto is_array($arg_a[4]$arg_a[4][0'';  /* argument 5: reply-to    */
  600.             $hdr->to $arg_a[5];          /* argument 6: to          */
  601.             $hdr->cc $arg_a[6];          /* argument 7: cc          */
  602.             $hdr->bcc $arg_a[7];         /* argument 8: bcc         */
  603.             $hdr->inreplyto $arg_a[8];   /* argument 9: in-reply-to */
  604.             $hdr->message_id $arg_a[9];  /* argument 10: message-id */
  605.         }
  606.         return $hdr;
  607.     }
  608.  
  609.     /**
  610.      * @param string $read 
  611.      * @param integer $i 
  612.      * @return string 
  613.      * @todo document me
  614.      */
  615.     function parseLiteral($read&$i{
  616.         $lit_cnt '';
  617.         ++$i;
  618.         $iPos strpos($read,'}',$i);
  619.         if ($iPos{
  620.             $lit_cnt substr($read$i$iPos $i);
  621.             $i += strlen($lit_cnt3/* skip } + \r + \n */
  622.             /* Now read the literal */
  623.             $s ($lit_cnt substr($read,$i,$lit_cnt)'');
  624.             $i += $lit_cnt;
  625.             /* temp bugfix (SM 1.5 will have a working clean version)
  626.                too much work to implement that version right now */
  627.             --$i;
  628.         else /* should never happen */
  629.             $i += 3/* } + \r + \n */
  630.             $s '';
  631.         }
  632.         return $s;
  633.     }
  634.  
  635.     /**
  636.      * @param string $read 
  637.      * @param integer $i 
  638.      * @return string 
  639.      * @todo document me
  640.      */
  641.     function parseQuote($read&$i{
  642.         $s '';
  643.         $iPos = ++$i;
  644.         while (true{
  645.             $iPos strpos($read,'"',$iPos);
  646.             if (!$iPosbreak;
  647.             if ($iPos && $read{$iPos -1!= '\\'{
  648.                 $s substr($read,$i,($iPos-$i));
  649.                 $i $iPos;
  650.                 break;
  651.             }
  652.             ++$iPos;
  653.             if ($iPos strlen($read)) {
  654.                 break;
  655.             }
  656.         }
  657.         return $s;
  658.     }
  659.  
  660.     /**
  661.      * @param string $read 
  662.      * @param integer $i 
  663.      * @return object AddressStructure object
  664.      */
  665.     function parseAddress($read&$i{
  666.         $arg_a array();
  667.         for ($read{$i!= ')'++$i{
  668.             $char strtoupper($read{$i});
  669.             switch ($char{
  670.                 case '"'$arg_a[$this->parseQuote($read$i)break;
  671.                 case '{'$arg_a[$this->parseLiteral($read$i)break;
  672.                 case 'n':
  673.                 case 'N':
  674.                     if (strtoupper(substr($read$i3)) == 'NIL'{
  675.                         $arg_a['';
  676.                         $i += 2;
  677.                     }
  678.                     break;
  679.                 defaultbreak;
  680.             }
  681.         }
  682.  
  683.         if (count($arg_a== 4{
  684.             $adr new AddressStructure();
  685.             $adr->personal $arg_a[0];
  686.             $adr->adl $arg_a[1];
  687.             $adr->mailbox $arg_a[2];
  688.             $adr->host $arg_a[3];
  689.         else {
  690.             $adr '';
  691.         }
  692.         return $adr;
  693.     }
  694.  
  695.     /**
  696.      * @param string $read 
  697.      * @param integer $i 
  698.      * @param object Disposition object or empty string
  699.      */
  700.     function parseDisposition($read&$i{
  701.         $arg_a array();
  702.         for ($read{$i!= ')'++$i{
  703.             switch ($read{$i}{
  704.                 case '"'$arg_a[$this->parseQuote($read$i)break;
  705.                 case '{'$arg_a[$this->parseLiteral($read$i)break;
  706.                 case '('$arg_a[$this->parseProperties($read$i)break;
  707.                 defaultbreak;
  708.             }
  709.         }
  710.  
  711.         if (isset($arg_a[0])) {
  712.             $disp new Disposition($arg_a[0]);
  713.             if (isset($arg_a[1])) {
  714.                 $disp->properties $arg_a[1];
  715.             }
  716.         }
  717.         return (is_object($disp$disp '');
  718.     }
  719.  
  720.     /**
  721.      * @param string $read 
  722.      * @param integer $i 
  723.      * @return object Language object or empty string
  724.      */
  725.     function parseLanguage($read&$i{
  726.         /* no idea how to process this one without examples */
  727.         $arg_a array();
  728.  
  729.         for ($read{$i!= ')'++$i{
  730.             switch ($read{$i}{
  731.                 case '"'$arg_a[$this->parseQuote($read$i)break;
  732.                 case '{'$arg_a[$this->parseLiteral($read$i)break;
  733.                 case '('$arg_a[$this->parseProperties($read$i)break;
  734.                 defaultbreak;
  735.             }
  736.         }
  737.  
  738.         if (isset($arg_a[0])) {
  739.             $lang new Language($arg_a[0]);
  740.             if (isset($arg_a[1])) {
  741.                 $lang->properties $arg_a[1];
  742.             }
  743.         }
  744.         return (is_object($lang$lang '');
  745.     }
  746.  
  747.     /**
  748.      * Parse message text enclosed in parenthesis
  749.      * @param string $read 
  750.      * @param integer $i 
  751.      * @return integer 
  752.      */
  753.     function parseParenthesis($read$i{
  754.         for ($read{$i!= ')'++$i{
  755.             switch ($read{$i}{
  756.                 case '"'$this->parseQuote($read$i)break;
  757.                 case '{'$this->parseLiteral($read$i)break;
  758.                 case '('$this->parseProperties($read$i)break;
  759.                 defaultbreak;
  760.             }
  761.         }
  762.         return $i;
  763.     }
  764.  
  765.     /**
  766.      * Function to fill the message structure in case the
  767.      * bodystructure is not available
  768.      * NOT FINISHED YET
  769.      * @param string $read 
  770.      * @param string $type0 message part type
  771.      * @param string $type1 message part subtype
  772.      * @return string (only when type0 is not message or multipart)
  773.      */
  774.     function parseMessage($read$type0$type1{
  775.         switch ($type0{
  776.             case 'message':
  777.                 $rfc822_header true;
  778.                 $mime_header false;
  779.                 break;
  780.             case 'multipart':
  781.                 $rfc822_header false;
  782.                 $mime_header true;
  783.                 break;
  784.             defaultreturn $read;
  785.         }
  786.  
  787.         for ($i 1$i $count++$i{
  788.             $line trim($body[$i]);
  789.             if (($mime_header || $rfc822_header&&
  790.                 (preg_match("/^.*boundary=\"?(.+(?=\")|.+).*/i"$line$reg))) {
  791.                 $bnd $reg[1];
  792.                 $bndreg $bnd;
  793.                 $bndreg str_replace("\\""\\\\"$bndreg);
  794.                 $bndreg str_replace("?""\\?"$bndreg);
  795.                 $bndreg str_replace("+""\\+"$bndreg);
  796.                 $bndreg str_replace(".""\\."$bndreg);
  797.                 $bndreg str_replace("/""\\/"$bndreg);
  798.                 $bndreg str_replace("-""\\-"$bndreg);
  799.                 $bndreg str_replace("(""\\("$bndreg);
  800.                 $bndreg str_replace(")""\\)"$bndreg);
  801.             else if ($rfc822_header && $line == ''{
  802.                 $rfc822_header false;
  803.                 if ($msg->type0 == 'multipart'{
  804.                     $mime_header true;
  805.                 }
  806.             }
  807.  
  808.             if ((($line{0== '-'|| $rfc822_header)  && isset($boundaries[0])) {
  809.                 $cnt count($boundaries)-1;
  810.                 $bnd $boundaries[$cnt]['bnd'];
  811.                 $bndreg $boundaries[$cnt]['bndreg'];
  812.  
  813.                 $regstr '/^--'."($bndreg)".".*".'/';
  814.                 if (preg_match($regstr$line$reg)) {
  815.                     $bndlen strlen($reg[1]);
  816.                     $bndend false;
  817.                     if (strlen($line($bndlen 3)) {
  818.                         if (($line{$bndlen+2== '-'&& ($line{$bndlen+3== '-')) {
  819.                             $bndend true;
  820.                         }
  821.                     }
  822.                     if ($bndend{
  823.                         /* calc offset and return $msg */
  824.                         //$entStr = CalcEntity("$entStr", -1);
  825.                         array_pop($boundaries);
  826.                         $mime_header true;
  827.                         $bnd_end true;
  828.                     else {
  829.                         $mime_header true;
  830.                          $bnd_end false;
  831.                         //$entStr = CalcEntity("$entStr", 0);
  832.                         ++$content_indx;
  833.                     }
  834.                 else {
  835.                     if ($header}
  836.                 }
  837.             }
  838.         }
  839.     }
  840.  
  841.     /**
  842.      * @param array $entity 
  843.      * @param array $alt_order 
  844.      * @param boolean $strict 
  845.      * @return array 
  846.      */
  847.     function findDisplayEntity($entity array()$alt_order array('text/plain''text/html')$strict=false{
  848.         $found false;
  849.         if ($this->type0 == 'multipart'{
  850.             if($this->type1 == 'alternative'{
  851.                 $msg $this->findAlternativeEntity($alt_order);
  852.                 if (count($msg->entities== 0{
  853.                     $entity[$msg->entity_id;
  854.                 else {
  855.                     $entity $msg->findDisplayEntity($entity$alt_order$strict);
  856.                 }
  857.                 $found true;
  858.             else if ($this->type1 == 'related'/* RFC 2387 */
  859.                 $msgs $this->findRelatedEntity();
  860.                 foreach ($msgs as $msg{
  861.                     if (count($msg->entities== 0{
  862.                         $entity[$msg->entity_id;
  863.                     else {
  864.                         $entity $msg->findDisplayEntity($entity$alt_order$strict);
  865.                     }
  866.                 }
  867.                 if (count($msgs0{
  868.                     $found true;
  869.                 }
  870.             else /* Treat as multipart/mixed */
  871.                 foreach ($this->entities as $ent{
  872.                     if(!(is_object($ent->header->disposition&& strtolower($ent->header->disposition->name== 'attachment'&&
  873.                             (!isset($ent->header->parameters['filename'])) &&
  874.                             (!isset($ent->header->parameters['name'])) &&
  875.                             (($ent->type0 != 'message'&& ($ent->type1 != 'rfc822'))) {
  876.                         $entity $ent->findDisplayEntity($entity$alt_order$strict);
  877.                         $found true;
  878.                     }
  879.                 }
  880.             }
  881.         else /* If not multipart, then just compare with each entry from $alt_order */
  882.             $type $this->type0.'/'.$this->type1;
  883. //        $alt_order[] = "message/rfc822";
  884.             foreach ($alt_order as $alt{
  885.                 if( ($alt == $type&& isset($this->entity_id) ) {
  886.                     if ((count($this->entities== 0&&
  887.                             (!isset($this->header->parameters['filename'])) &&
  888.                             (!isset($this->header->parameters['name'])) &&
  889.                             (isset($this->header->disposition&& is_object($this->header->disposition&&
  890.                              strtolower($this->header->disposition->name!= 'attachment')) {
  891.                         $entity[$this->entity_id;
  892.                         $found true;
  893.                     }
  894.                 }
  895.             }
  896.         }
  897.         if(!$found{
  898.             foreach ($this->entities as $ent{
  899.                 if(!(is_object($ent->header->disposition&& strtolower($ent->header->disposition->name== 'attachment'&&
  900.                    (($ent->type0 != 'message'&& ($ent->type1 != 'rfc822'))) {
  901.                     $entity $ent->findDisplayEntity($entity$alt_order$strict);
  902.                     $found true;
  903.                 }
  904.             }
  905.         }
  906.         if(!$strict && !$found{
  907.             if (($this->type0 == 'text'&&
  908.                 in_array($this->type1array('plain''html''message')) &&
  909.                 isset($this->entity_id)) {
  910.                 if (count($this->entities== 0{
  911.                     if (!is_object($this->header->disposition|| strtolower($this->header->disposition->name!= 'attachment'{
  912.                         $entity[$this->entity_id;
  913.                     }
  914.                 }
  915.             }
  916.         }
  917.         return $entity;
  918.     }
  919.  
  920.     /**
  921.      * @param array $alt_order 
  922.      * @return array 
  923.      */
  924.     function findAlternativeEntity($alt_order{
  925.         /* If we are dealing with alternative parts then we  */
  926.         /* choose the best viewable message supported by SM. */
  927.         $best_view 0;
  928.         $entity array();
  929.         foreach($this->entities as $ent{
  930.             $type $ent->header->type0 '/' $ent->header->type1;
  931.             if ($type == 'multipart/related'{
  932.                 $type $ent->header->getParameter('type');
  933.             // Mozilla bug. Mozilla does not provide the parameter type.
  934.             if (!$type$type 'text/html';
  935.             }
  936.             $altCount count($alt_order);
  937.             for ($j $best_view$j $altCount++$j{
  938.                 if (($alt_order[$j== $type&& ($j >= $best_view)) {
  939.                     $best_view $j;
  940.                     $entity $ent;
  941.                 }
  942.             }
  943.         }
  944.         return $entity;
  945.     }
  946.  
  947.     /**
  948.      * @return array 
  949.      */
  950.     function findRelatedEntity({
  951.         $msgs array();
  952.         $related_type $this->header->getParameter('type');
  953.         // Mozilla bug. Mozilla does not provide the parameter type.
  954.         if (!$related_type$related_type 'text/html';
  955.         $entCount count($this->entities);
  956.         for ($i 0$i $entCount++$i{
  957.             $type $this->entities[$i]->header->type0.'/'.$this->entities[$i]->header->type1;
  958.             if ($related_type == $type{
  959.                 $msgs[$this->entities[$i];
  960.             }
  961.         }
  962.         return $msgs;
  963.     }
  964.  
  965.     /**
  966.      * @param array $exclude_id 
  967.      * @param array $result 
  968.      * @return array 
  969.      */
  970.     function getAttachments($exclude_id=array()$result array()) {
  971. /*
  972.         if (($this->type0 == 'message') &&
  973.         ($this->type1 == 'rfc822') &&
  974.         ($this->entity_id) ) {
  975.             $this = $this->entities[0];
  976.         }
  977. */
  978.         if (count($this->entities)) {
  979.             foreach ($this->entities as $entity{
  980.                 $exclude false;
  981.                 foreach ($exclude_id as $excl{
  982.                     if ($entity->entity_id === $excl{
  983.                         $exclude true;
  984.                     }
  985.                 }
  986.  
  987.                 if (!$exclude{
  988.                     if (($entity->type0 == 'multipart'&&
  989.                         ($entity->type1 != 'related')) {
  990.                         $result $entity->getAttachments($exclude_id$result);
  991.                     else if ($entity->type0 != 'multipart'{
  992.                         $result[$entity;
  993.                     }
  994.                 }
  995.             }
  996.         else {
  997.             $exclude false;
  998.             foreach ($exclude_id as $excl{
  999.                 $exclude $exclude || ($this->entity_id == $excl);
  1000.             }
  1001.  
  1002.             if (!$exclude{
  1003.                 $result[$this;
  1004.             }
  1005.         }
  1006.         return $result;
  1007.     }
  1008.  
  1009.     /**
  1010.      * Add attachment to message object
  1011.      * @param string $type attachment type
  1012.      * @param string $name attachment name
  1013.      * @param string $location path to attachment
  1014.      */
  1015.     function initAttachment($type$name$location{
  1016.         $attachment new Message();
  1017.         $mime_header new MessageHeader();
  1018.         $mime_header->setParameter('name'$name);
  1019.         $pos strpos($type'/');
  1020.         if ($pos 0{
  1021.             $mime_header->type0 substr($type0$pos);
  1022.             $mime_header->type1 substr($type$pos+1);
  1023.         else {
  1024.             $mime_header->type0 $type;
  1025.         }
  1026.         $attachment->att_local_name $location;
  1027.         $disposition new Disposition('attachment');
  1028.         $disposition->properties['filename'$name;
  1029.         $mime_header->disposition $disposition;
  1030.         $attachment->mime_header $mime_header;
  1031.         $this->entities[]=$attachment;
  1032.     }
  1033.     
  1034.     /**
  1035.      * Delete all attachments from this object from disk.
  1036.      * @since 1.4.6
  1037.      */
  1038.     function purgeAttachments({
  1039.         if ($this->att_local_name && file_exists($this->att_local_name)) {
  1040.             unlink($this->att_local_name);
  1041.         }
  1042.         // recursively delete attachments from entities contained in this object
  1043.         for ($i=0$entCount=count($this->entities);$i$entCount++$i{
  1044.             $this->entities[$i]->purgeAttachments();
  1045.         }
  1046.     }
  1047. }
  1048.  
  1049. ?>

Documentation generated on Sat, 07 Oct 2006 16:32:22 +0300 by phpDocumentor 1.3.0RC6