/**
  * Begins the decoding process. If called statically
  * it will create an object and call the decode() method
  * of it.
  *
  * @param array $ An array of various parameters that determine
  *               various things:
  *               include_bodies - Whether to include the body in the returned
  *                                object.
  *               decode_bodies  - Whether to decode the bodies
  *                                of the parts. (Transfer encoding)
  *               decode_headers - Whether to decode headers
  *               input          - If called statically, this will be treated
  *                                as the input
  * @return object Decoded results
  * @access public
  */
 function decode($params = null)
 {
     // Have we been called statically? If so, create an object and pass details to that.
     if (!isset($this->mailMimeDecode) and isset($params['input'])) {
         $obj = new MIMEDECODE($params['input']);
         $structure = $obj->decode($params);
         // Called statically but no input
     } elseif (!isset($this->mailMimeDecode)) {
         return $this->_error = 'Called statically and no input given';
         // Called via an object
     } else {
         // $this->_include_bodies = isset($params['include_bodies'])  ? $params['include_bodies']  : false;
         // $this->_decode_bodies  = isset($params['decode_bodies'])   ? $params['decode_bodies']   : false;
         // $this->_decode_headers = isset($params['decode_headers'])  ? $params['decode_headers']  : false;
         //Trace
         $this->_decode_headers = true;
         $structure = $this->_decode($this->_header, $this->_body);
         if ($structure === false) {
             $structure = $this->_error;
         }
     }
     return $structure;
 }
 /**
  * Performs the decoding. Decodes the body string passed to it
  * If it finds certain content-types it will call itself in a
  * recursive fashion
  *
  * @param string $ Header section
  * @param string $ Body section
  * @return object Results of decoding process
  * @access private
  */
 function _decode($headers, $body, $default_ctype = 'text/plain')
 {
     $return = new stdClass();
     $headers = $this->_parseHeaders($headers);
     foreach ($headers as $value) {
         if (isset($return->headers[strtolower($value['name'])]) and !is_array($return->headers[strtolower($value['name'])])) {
             $return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]);
             $return->headers[strtolower($value['name'])][] = $value['value'];
         } elseif (isset($return->headers[strtolower($value['name'])])) {
             $return->headers[strtolower($value['name'])][] = $value['value'];
         } else {
             $return->headers[strtolower($value['name'])] = $value['value'];
         }
     }
     reset($headers);
     while (list($key, $value) = each($headers)) {
         $headers[$key]['name'] = strtolower($headers[$key]['name']);
         switch ($headers[$key]['name']) {
             case 'content-type':
                 $content_type = $this->_parseHeaderValue($headers[$key]['value']);
                 if (preg_match('/([0-9a-z+.-]+)\\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) {
                     $return->ctype_primary = $regs[1];
                     $return->ctype_secondary = $regs[2];
                 }
                 if (isset($content_type['other'])) {
                     while (list($p_name, $p_value) = each($content_type['other'])) {
                         $return->ctype_parameters[$p_name] = $p_value;
                     }
                 }
                 break;
             case 'content-disposition':
                 $content_disposition = $this->_parseHeaderValue($headers[$key]['value']);
                 $return->disposition = $content_disposition['value'];
                 if (isset($content_disposition['other'])) {
                     while (list($p_name, $p_value) = each($content_disposition['other'])) {
                         $return->d_parameters[$p_name] = $p_value;
                     }
                 }
                 break;
             case 'content-transfer-encoding':
                 $content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']);
                 break;
         }
     }
     if (isset($content_type)) {
         switch (trim(strtolower($content_type['value']))) {
             case 'text/plain':
                 $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
                 $this->_include_bodies ? $return->body = $this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body : null;
                 break;
             case 'text/html':
                 $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
                 $this->_include_bodies ? $return->body = $this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body : null;
                 break;
             case 'multipart/parallel':
             case 'multipart/report':
                 // RFC1892
             // RFC1892
             case 'multipart/signed':
                 // PGP
             // PGP
             case 'multipart/digest':
             case 'multipart/alternative':
             case 'multipart/related':
             case 'multipart/mixed':
                 if (!isset($content_type['other']['boundary'])) {
                     $this->_error = 'No boundary found for ' . $content_type['value'] . ' part';
                     return false;
                 }
                 $default_ctype = strtolower($content_type['value']) === 'multipart/digest' ? 'message/rfc822' : 'text/plain';
                 $parts = $this->_boundarySplit($body, $content_type['other']['boundary']);
                 for ($i = 0; $i < count($parts); $i++) {
                     list($part_header, $part_body) = $this->_split_body_header($parts[$i]);
                     $part = $this->_decode($part_header, $part_body, $default_ctype);
                     if ($part === false) {
                         $part = $this->raiseError($this->_error);
                     }
                     $return->parts[] = $part;
                 }
                 break;
             case 'message/rfc822':
                 //  $obj = &new MIMEDECODE($body);// See below by Anoop
                 $obj = new MIMEDECODE($body);
                 // Php 5.4 fix by Anoop
                 $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies));
                 unset($obj);
                 break;
             default:
                 if (!isset($content_transfer_encoding['value'])) {
                     $content_transfer_encoding['value'] = '7bit';
                 }
                 $this->_include_bodies ? $return->body = $this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body : null;
                 break;
         }
     } else {
         $ctype = explode('/', $default_ctype);
         $return->ctype_primary = $ctype[0];
         $return->ctype_secondary = $ctype[1];
         $this->_include_bodies ? $return->body = $this->_decode_bodies ? $this->_decodeBody($body) : $body : null;
     }
     return $return;
 }