finally managed to solve the bad Junk after literal output from the
[squirrelmail.git] / class / mime.class.php
index dd2eec539f39dbf9fbe0c83aa786dc14ec49ccff..f6ae0d74c328a68d674ef0c5b5e1f344064837e7 100644 (file)
@@ -67,24 +67,35 @@ class rfc822_header {
         $result = '';
 
         $cnt = strlen($value);
-        for ($i = 0; $i < $cnt; ++$i) {
+        for ($i = 0; $i < $cnt; $i++) {
             switch ($value{$i}) {
                 case '"':
                     $result .= '"';
-                    ++$i;
-                    while ($value{$i} != '"') {
+                    while ((++$i < $cnt) && ($value{$i} != '"')) {
                         if ($value{$i} == '\\') {
                             $result .= '\\';
-                            ++$i;
+                            $i++;
                         }
                         $result .= $value{$i};
-                        if (++$i > $cnt) { break; }
                     }
                     $result .= $value{$i};
                     break;
                 case '(':
-                    while ($value{$i} != ')') {
-                        $i += ($value{$i} == '\\' ? 2 : 1);
+                    $depth = 1;
+                    while (($depth > 0) && (++$i < $cnt)) {
+                        switch($value{$i}) {
+                            case '\\':
+                                $i++;
+                                break;
+                            case '(':
+                                $depth++;
+                                break;
+                            case ')':
+                                $depth--;
+                                break;
+                            default:
+                                break;
+                        }
                     }
                     break;
                 default:
@@ -397,7 +408,6 @@ class rfc822_header {
                 }
             }
         }
-
         return $s;
     }
 
@@ -491,7 +501,7 @@ class address_structure {
         $result = '';
 
         if (is_object($this)) {
-            if (isset($this->host) &&$this->host != '')) {
+            if (isset($this->host) && ($this->host != '')) {
                 $email = $this->mailbox.'@'.$this->host;
             } else {
                 $email = $this->mailbox;
@@ -509,7 +519,6 @@ class address_structure {
             }
             $result = ($full ? $addr : $best_dpl);
         }
-
         return $result;
     }
 }
@@ -545,18 +554,14 @@ class message {
 
     function getFilename() {
         $filename = '';
-
-        if (is_object($this->header->disposition)) {
-            $filename = $this->header->disposition->getproperty('filename');
-            if (!$filename) {
-                $filename = $this->header->disposition->getproperty('name');
-            }
+        $filename = $this->header->getParameter('filename');   
+        if (!$filename) {
+            $filename = $this->header->getParameter('name');
         }
 
         if (!$filename) {
             $filename = 'untitled-'.$this->entity_id;
         }
-
         return $filename;
     }
 
@@ -569,7 +574,7 @@ class message {
     function getEntity($ent) {
         $cur_ent = $this->entity_id;
         $msg = $this;
-        if (($cur_ent == '') ||$cur_ent == '0')) {
+        if (($cur_ent == '') || ($cur_ent == '0')) {
             $cur_ent_a = array();
         } else {
             $cur_ent_a = explode('.', $this->entity_id);
@@ -618,8 +623,8 @@ class message {
         $msg = $this;
         $msg->body_part = '';
 
-        for ($i = 0; isset($msg->entities[$i]); ++$i) {
-            $msg->entities[$i]->clean_up();
+        foreach ($msg->entities as $m) {
+            $m->clean_up();
         }
     }
 
@@ -643,7 +648,7 @@ class message {
             if ($par_ent == '0') {
                 $ent_no = count($this->entities) + 1;
                 if ($ent_no > 0) {
-                    $ent = substr($this->entity_id, 0,strrpos($this->entity_id, '.'));
+                    $ent = substr($this->entity_id, 0, strrpos($this->entity_id, '.'));
                     $ent = ($ent ? $ent . ".$ent_no" : $ent_no);
                     $msg->entity_id = $ent;
                 } else {
@@ -670,142 +675,139 @@ class message {
      *
      * Question/Bugs:
      *
-     * Ask for me (Marc Groot Koerkamp, stekkel@users.sourceforge.net.
+     * Ask for me (Marc Groot Koerkamp, stekkel@users.sourceforge.net)
      *
      */
     function parseStructure($read, $i = 0) {
-       $arg_no = 0;
-       $arg_a = array();
-       $cnt = strlen($read);
+        $arg_no = 0;
+        $arg_a  = array();
+        $cnt    = strlen($read);
 
-       for (; $i < $cnt; ++$i) {
-           $char = strtoupper($read{$i});
+        for (; $i < $cnt; ++$i) {
+            $char = strtoupper($read{$i});
             switch ($char) {
                 case '(':
-                    if ($arg_no == 0) {
-                        if (!isset($msg)) {
-                            $msg = new message();
-                            $hdr = new msg_header();
-                            $hdr->type0 = 'text';
-                            $hdr->type1 = 'plain';
-                            $hdr->encoding = 'us-ascii';
-                            $msg->entity_id = $this->calcEntity($msg);
-                        } else {
-                            $msg->header->type0 = 'multipart';
-                            $msg->type0 = 'multipart';
-                            while ($read{$i} == '(') {
-                                $res = $msg->parseStructure($read, $i);
-                                $i = $res[1];
-                                $msg->addEntity($res[0]);
-                            }
-                        }
-                    } else {
-                        switch ($arg_no) {
-                            case 1:
-                                /* multipart properties */
-                                ++$i;
-                                $res = $this->parseProperties($read, $i);
-                                $arg_a[] = $res[0];
-                                $i = $res[1];
-                                ++$arg_no;
-                                break;
-                            case 2:
-                                if (isset($msg->type0) && ($msg->type0 == 'multipart')) {
-                                    ++$i;
-                                   $res = $msg->parseDisposition($read, $i);
-                                    $arg_a[] = $res[0];
-                                    $i = $res[1];
-                                } else { /* properties */
-                                    $res = $msg->parseProperties($read, $i);
-                                    $arg_a[] = $res[0];
-                                   $i = $res[1];
-                                }
-                                ++$arg_no;
-                                break;
-                            case 3:
-                                if (isset($msg->type0) && ($msg->type0 == 'multipart')) {
-                                    ++$i;
-                                    $res= $msg->parseLanguage($read, $i);
-                                    $arg_a[] = $res[0];
-                                    $i = $res[1];
-                                }
-                            case 7:
-                                if (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822')) {
-                                    $msg->header->type0 = $arg_a[0];
-                                    $msg->type0 = $arg_a[0];
-                                    $msg->header->type1 = $arg_a[1];
-                                    $msg->type1 = $arg_a[1];
-                                    $rfc822_hdr = new rfc822_header();
-                                    $res = $msg->parseEnvelope($read, $i, $rfc822_hdr);
-                                    $i = $res[1] + 1;
-                                    $msg->rfc822_header =  $res[0];
-                                    while (($i < $cnt) && ($read{$i} != '(')) {
-                                        ++$i;
-                                    }
+                    switch($arg_no) {
+                        case 0:
+                            if (!isset($msg)) {
+                                $msg = new message();
+                                $hdr = new msg_header();
+                                $hdr->type0 = 'text';
+                                $hdr->type1 = 'plain';
+                                $hdr->encoding = 'us-ascii';
+                                $msg->entity_id = $this->calcEntity($msg);
+                            } else {
+                                $msg->header->type0 = 'multipart';
+                                $msg->type0 = 'multipart';
+                                while ($read{$i} == '(') {
                                     $res = $msg->parseStructure($read, $i);
                                     $i = $res[1];
                                     $msg->addEntity($res[0]);
                                 }
-                                break;
-                            case 8:
+                            }
+                            break;
+                        case 1:
+                            /* multipart properties */
+                            ++$i;
+                            $res = $this->parseProperties($read, $i);
+                            $arg_a[] = $res[0];
+                            $i = $res[1];
+                            ++$arg_no;
+                            break;
+                        case 2:
+                            if (isset($msg->type0) && ($msg->type0 == 'multipart')) {
                                 ++$i;
                                 $res = $msg->parseDisposition($read, $i);
+                            } else { /* properties */
+                                $res = $msg->parseProperties($read, $i);
+                            }
+                            $arg_a[] = $res[0];
+                            $i = $res[1];
+                            ++$arg_no;
+                            break;
+                        case 3:
+                            if (isset($msg->type0) && ($msg->type0 == 'multipart')) {
+                                ++$i;
+                                $res= $msg->parseLanguage($read, $i);
                                 $arg_a[] = $res[0];
                                 $i = $res[1];
-                                ++$arg_no;
-                                break;
-                            case 9:
-                                ++$i;
-                                if (($arg_a[0] == 'text') || (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822'))) {
-                                    $res = $msg->parseDisposition($read, $i);
-                                } else {
-                                    $res = $msg->parseLanguage($read, $i);
+                            }
+                        case 7:
+                            if (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822')) {
+                                $msg->header->type0 = $arg_a[0];
+                                $msg->header->type1 = $arg_a[1];
+                                $msg->type0 = $arg_a[0];
+                                $msg->type1 = $arg_a[1];
+                                $rfc822_hdr = new rfc822_header();
+                                $res = $msg->parseEnvelope($read, $i, $rfc822_hdr);
+                                $msg->rfc822_header = $res[0];
+                                $i = $res[1] + 1;
+                                while (($i < $cnt) && ($read{$i} != '(')) {
+                                    ++$i;
                                 }
-                                $arg_a[] = $res[0];
+                                $res = $msg->parseStructure($read, $i);
                                 $i = $res[1];
-                                ++$arg_no;
-                                break;
-                           case 10:
-                               if (($arg_a[0] == 'text') || (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822'))) {
-                                   ++$i;
-                                   $res = $msg->parseLanguage($read, $i);
-                                   $arg_a[] = $res[0];
-                                   $i = $res[1];
-                               } else {
-                                   $i = $msg->parseParenthesis($read, $i);
-                                   $arg_a[] = ''; /* not yet desribed in rfc2060 */
-                               }
-                               ++$arg_no;
-                               break;
-                           default:
-                               /* unknown argument, skip this part */
+                                $msg->addEntity($res[0]);
+                            }
+                            break;
+                        case 8:
+                            ++$i;
+                            $res = $msg->parseDisposition($read, $i);
+                            $arg_a[] = $res[0];
+                            $i = $res[1];
+                            ++$arg_no;
+                            break;
+                        case 9:
+                            ++$i;
+                            if (($arg_a[0] == 'text') || (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822'))) {
+                                $res = $msg->parseDisposition($read, $i);
+                            } else {
+                                $res = $msg->parseLanguage($read, $i);
+                            }
+                            $arg_a[] = $res[0];
+                            $i = $res[1];
+                            ++$arg_no;
+                            break;
+                       case 10:
+                           if (($arg_a[0] == 'text') || (($arg_a[0] == 'message') && ($arg_a[1] == 'rfc822'))) {
+                               ++$i;
+                               $res = $msg->parseLanguage($read, $i);
+                               $arg_a[] = $res[0];
+                               $i = $res[1];
+                           } else {
                                $i = $msg->parseParenthesis($read, $i);
-                               $arg_a[] = '';
-                               ++$arg_no;
-                               break;
-                       } /* switch */
-                   }
-                   break;
-               case '"':
-                   /* inside an entity -> start processing */
-                   $debug = substr($read, $i, 20);
-                   $res = $msg->parseQuote($read, $i);
-                   $arg_s = $res[0];
-                   $i = $res[1];
-                   ++$arg_no;
-                   if ($arg_no < 3) {
-                       $arg_s = strtolower($arg_s); /* type0 and type1 */
-                   }
-                   $arg_a[] = $arg_s;
+                               $arg_a[] = ''; /* not yet described in rfc2060 */
+                           }
+                           ++$arg_no;
+                           break;
+                       default:
+                           /* unknown argument, skip this part */
+                           $i = $msg->parseParenthesis($read, $i);
+                           $arg_a[] = '';
+                           ++$arg_no;
+                           break;
+                   } /* switch */
                    break;
-               case 'n':
-               case 'N':
-                   /* probably NIL argument */
-                   if (strtoupper(substr($read, $i, 4)) == 'NIL ') {
-                       $arg_a[] = '';
-                       ++$arg_no;
-                       $i += 2;
-                   }
+                case '"':
+                    /* inside an entity -> start processing */
+                    $debug = substr($read, $i, 20);
+                    $res = $msg->parseQuote($read, $i);
+                    $arg_s = $res[0];
+                    $i = $res[1];
+                    ++$arg_no;
+                    if ($arg_no < 3) {
+                        $arg_s = strtolower($arg_s); /* type0 and type1 */
+                    }
+                    $arg_a[] = $arg_s;
+                    break;
+                case 'n':
+                case 'N':
+                    /* probably NIL argument */
+                    if (strtoupper(substr($read, $i, 4)) == 'NIL ') {
+                        $arg_a[] = '';
+                        ++$arg_no;
+                        $i += 2;
+                    }
                     break;
                 case '{':
                     /* process the literal value */
@@ -833,7 +835,6 @@ class message {
 
                         $msg->type0 = $arg_a[0];
                         $msg->type1 = $arg_a[1];
-
                         $arr = $arg_a[2];
                         if (is_array($arr)) {
                             $hdr->parameters = $arg_a[2];
@@ -853,10 +854,8 @@ class message {
                         $hdr->disposition = (isset($arg_a[8+$s]) ? $arg_a[8+$s] : $hdr->disposition);
                         $hdr->language = (isset($arg_a[9+$s]) ? $arg_a[9+$s] : $hdr->language);
                         $msg->header = $hdr;
-//                        $arg_no = 0;
-                        ++$i;
-                        if ((substr($msg->entity_id, -2) == '.0') && ($msg->type0 !='multipart')) {
-                           $msg->entity_id++;
+                        if ((strrchr($msg->entity_id, '.') == '.0') && ($msg->type0 !='multipart')) {
+                           $msg->entity_id = $this->entity_id . '.1';
                         }
                     } else {
                         $hdr->type0 = 'multipart';
@@ -868,6 +867,7 @@ class message {
                         $hdr->language = (isset($arg_a[3]) ? $arg_a[3] : $hdr->language);
                         $msg->header = $hdr;
                     }
+                    ++$i;
                     return (array($msg, $i));
                 default: break;
             } /* switch */
@@ -878,9 +878,9 @@ class message {
     function parseProperties($read, $i) {
         $properties = array();
         $prop_name = '';
-        $arg_s = '';
 
         for (; $read{$i} != ')'; ++$i) {
+            $arg_s = '';
             if ($read{$i} == '"') {
                 $res = $this->parseQuote($read, $i);
                 $arg_s = $res[0];
@@ -891,18 +891,17 @@ class message {
                 $i = $res[1];
             }
 
-            if (($prop_name == '') && $arg_s) {
-                $prop_name = strtolower($arg_s);
-                $properties[$prop_name] = '';
-                $arg_s = '';
-            } else if (($prop_name != '') && ($arg_s != '')) {
-                $properties[$prop_name] = $arg_s;
-                $prop_name = '';
-                $arg_s = '';
+            if ($arg_s != '') {
+                if ($prop_name == '') {
+                    $prop_name = strtolower($arg_s);
+                    $properties[$prop_name] = '';
+                } else if ($prop_name != '') {
+                    $properties[$prop_name] = $arg_s;
+                    $prop_name = '';
+                }
             }
         }
-
-        return (array($properties, $i));
+        return array($properties, $i);
     }
 
     function parseEnvelope($read, $i, $hdr) {
@@ -1205,62 +1204,77 @@ class message {
         }
     }
 
-    function findDisplayEntity($entity = array(), $alt_order = array('text/plain', 'text/html')) {
+    function findDisplayEntity($entity = array(), $alt_order = array('text/plain', 'text/html'), $strict=false) {
         $found = false;
-        $type = $this->type0.'/'.$this->type1;
-        if ($type == 'multipart/alternative') {
-            $msg = $this->findAlternativeEntity($alt_order);
-            if (count($msg->entities) == 0) {
-                $entity[] = $msg->entity_id;
-            } else {
-                $entity = $msg->findDisplayEntity($entity, $alt_order);
-            }
-            $found = true;
-        } else if ($type == 'multipart/related') {
-            $msgs = $this->findRelatedEntity();
-            foreach ($msgs as $msg) {
+        if ($this->type0 == 'multipart') {
+            if($this->type1 == 'alternative') {
+                $msg = $this->findAlternativeEntity($alt_order);
                 if (count($msg->entities) == 0) {
                     $entity[] = $msg->entity_id;
                 } else {
-                    $entity = $msg->findDisplayEntity($entity, $alt_order);
+                    $entity = $msg->findDisplayEntity($entity, $alt_order, $strict);
                 }
-            }
-            if (count($msgs) > 0) {
                 $found = true;
+            } else if ($this->type1 == 'related') { /* RFC 2387 */
+                $msgs = $this->findRelatedEntity();
+                foreach ($msgs as $msg) {
+                    if (count($msg->entities) == 0) {
+                        $entity[] = $msg->entity_id;
+                    } else {
+                        $entity = $msg->findDisplayEntity($entity, $alt_order, $strict);
+                    }
+                }
+                if (count($msgs) > 0) {
+                    $found = true;
+                }
+            } else { /* Treat as multipart/mixed */
+                foreach ($this->entities as $ent) {
+                    if(strtolower($ent->header->disposition->name) != 'attachment' &&
+                       ($ent->type0 != 'message' && $ent->type1 != 'rfc822'))
+                    {
+                        $entity = $ent->findDisplayEntity($entity, $alt_order, $strict);
+                        $found = true;
+                    }
+                }
             }
-        } else if (($this->type0 == 'text') &&
-                   (($this->type1 == 'plain') ||
-                    ($this->type1 == 'html')  ||
-                    ($this->type1 == 'message')) &&
-                   isset($this->entity_id)) {
-            if (count($this->entities) == 0) {
-                if (strtolower($this->header->disposition->name) != 'attachment') {
-                    $entity[] = $this->entity_id;
+        } else { /* If not multipart, then just compare with each entry from $alt_order */
+            $type = $this->type0.'/'.$this->type1;
+            foreach ($alt_order as $alt) {
+                if( ($alt == $type) && isset($this->entity_id) ) {
+                    if ( (count($this->entities) == 0) && 
+                         (strtolower($this->header->disposition->name) != 'attachment') )
+                    {
+                            $entity[] = $this->entity_id;
+                            $found = true;
+                    }
                 }
             }
         }
-        $i = 0;
-        if (!$found) {
+        if(!$found) {
             foreach ($this->entities as $ent) {
                 if((strtolower($ent->header->disposition->name) != 'attachment') &&
                    (($ent->type0 != 'message') && ($ent->type1 != 'rfc822'))) {
-                    $entity = $ent->findDisplayEntity($entity, $alt_order);
+                    $entity = $ent->findDisplayEntity($entity, $alt_order, $strict);
+                    $found = true;
+                }
+            }
+        }
+        if(!$strict && !$found) {
+            if ($this->type0 == 'text' &&
+                ($this->type1 == 'plain' ||
+                 $this->type1 == 'html'  ||
+                 $this->type1 == 'message') &&
+                isset($this->entity_id) )
+            {
+                if (count($this->entities) == 0) {
+                    if (strtolower($this->header->disposition->name) != 'attachment') {
+                        $entity[] = $this->entity_id;
+                    }
                 }
             }
         }
 
-        /* CAN THIS BE REMOVED? IF SO, DO IT!!! */
-        //while (isset($this->entities[$i]) && !$found &&
-        //        (strtolower($this->entities[$i]->header->disposition->name)
-        //         != 'attachment') &&
-        //        ($this->entities[$i]->type0 != 'message' &&
-        //         $this->entities[$i]->type1 != 'rfc822')
-        //     ) {
-        //    $entity = $this->entities[$i]->findDisplayEntity($entity, $alt_order);
-        //    ++$i;
-        //}
-
-        return ($entity);
+        return $entity;
     }
 
     function findAlternativeEntity($alt_order) {