39     'multipart/mixed' => array(self::LEVEL_TOP, self::LEVEL_MIXED),
 
   40     'multipart/alternative' => array(self::LEVEL_MIXED, self::LEVEL_ALTERNATIVE),
 
   41     'multipart/related' => array(self::LEVEL_ALTERNATIVE, self::LEVEL_RELATED)
 
   66     'multipart/related' => 3
 
   86     $this->_cacheKey = uniqid();
 
   87     $this->_cache = $cache;
 
   88     $this->_headers = $headers;
 
   90     $this->_headers->defineOrdering(
 
   91       array(
'Content-Type', 
'Content-Transfer-Encoding')
 
  107     $this->_compoundLevelFilters = array(
 
  108       (self::LEVEL_ALTERNATIVE + self::LEVEL_RELATED) => array(
 
  109         self::LEVEL_ALTERNATIVE => array(
 
  110           'text/plain' => self::LEVEL_ALTERNATIVE,
 
  111           'text/html' => self::LEVEL_RELATED
 
  166     $this->_userContentType = 
$type;
 
  215       $this->_headers->addTextHeader(
'Content-Description', $description);
 
  236     $this->_maxLineLength = $length;
 
  254   public function setChildren(array $children, $compoundLevel = null)
 
  258     $compoundLevel = isset($compoundLevel)
 
  263     $immediateChildren = array();
 
  264     $grandchildren = array();
 
  267     foreach ($children as $child)
 
  270       if (empty($immediateChildren)) 
 
  272         $immediateChildren = array($child);
 
  277         if ($nextLevel == $level)
 
  279           $immediateChildren[] = $child;
 
  281         elseif ($level < $nextLevel)
 
  284           $grandchildren = array_merge($grandchildren, $immediateChildren);
 
  286           $immediateChildren = array($child);
 
  290           $grandchildren[] = $child;
 
  295     if (!empty($immediateChildren))
 
  301       foreach ($this->_compositeRanges as $mediaType => $range)
 
  303         if ($lowestLevel > $range[0]
 
  304           && $lowestLevel <= $range[1])
 
  306           $newContentType = $mediaType;
 
  312       if (!empty($grandchildren))
 
  315         $subentity->_setNestingLevel($lowestLevel);
 
  316         $subentity->setChildren($grandchildren, $compoundLevel);
 
  317         array_unshift($immediateChildren, $subentity);
 
  321     $this->_immediateChildren = $immediateChildren;
 
  322     $this->_children = $children;
 
  347   public function setBody($body, $contentType = null)
 
  349     if ($body !== $this->_body)
 
  354     $this->_body = $body;
 
  355     if (isset($contentType))
 
  377     if ($encoder !== $this->_encoder)
 
  382     $this->_encoder = $encoder;
 
  394     if (!isset($this->_boundary))
 
  396       $this->_boundary = 
'_=_swift_v4_' . time() . uniqid() . 
'_=_';
 
  409     $this->_boundary = $boundary;
 
  439     $string = $this->_headers->toString();
 
  440     if (isset($this->_body) && empty($this->_immediateChildren))
 
  442       if ($this->_cache->hasKey($this->_cacheKey, 
'body'))
 
  444         $body = $this->_cache->getString($this->_cacheKey, 
'body');
 
  448         $body = 
"\r\n" . $this->_encoder->encodeString($this->
getBody(), 0,
 
  451         $this->_cache->setString($this->_cacheKey, 
'body', $body,
 
  458     if (!empty($this->_immediateChildren))
 
  460       foreach ($this->_immediateChildren as $child)
 
  462         $string .= 
"\r\n\r\n--" . $this->
getBoundary() . 
"\r\n";
 
  463         $string .= $child->toString();
 
  465       $string .= 
"\r\n\r\n--" . $this->
getBoundary() . 
"--\r\n";
 
  489     $is->
write($this->_headers->toString());
 
  492     if (empty($this->_immediateChildren))
 
  494       if (isset($this->_body))
 
  496         if ($this->_cache->hasKey($this->_cacheKey, 
'body'))
 
  498           $this->_cache->exportToByteStream($this->_cacheKey, 
'body', $is);
 
  502           $cacheIs = $this->_cache->getInputByteStream($this->_cacheKey, 
'body');
 
  512             $this->_body->setReadPointer(0);
 
  514             $this->_encoder->encodeByteStream($this->_body, $is, 0,
 
  520             $is->
write($this->_encoder->encodeString(
 
  533     if (!empty($this->_immediateChildren))
 
  535       foreach ($this->_immediateChildren as $child)
 
  538         $child->toByteStream($is);
 
  558     if ($this->_headers->has(
$field))
 
  560       return $this->_headers->get(
$field)->getFieldBodyModel();
 
  569     if ($this->_headers->has(
$field))
 
  571       $this->_headers->get(
$field)->setFieldBodyModel($model);
 
  585     if ($this->_headers->has(
$field))
 
  587       return $this->_headers->get(
$field)->getParameter($parameter);
 
  596     if ($this->_headers->has(
$field))
 
  598       $this->_headers->get(
$field)->setParameter($parameter, $value);
 
  612     if (count($this->_immediateChildren))
 
  617       $this->_headers->remove(
'Content-Transfer-Encoding');
 
  639     $this->_cache->clearKey($this->_cacheKey, 
'body');
 
  648     $idLeft = time() . 
'.' . uniqid();
 
  649     $idRight = !empty($_SERVER[
'SERVER_NAME'])
 
  650       ? $_SERVER[
'SERVER_NAME']
 
  652     return $idLeft . 
'@' . $idRight;
 
  660     while (
false !== $bytes = $os->
read(8192))
 
  671       $this->_headers->addTextHeader(
'Content-Transfer-Encoding', $encoding);
 
  678       '/^[a-z0-9\'\(\)\+_\-,\.\/:=\?\ ]{0,69}[a-z0-9\'\(\)\+_\-,\.\/:=\?]$/Di',
 
  689       $this->_headers->addParameterizedHeader(
'Content-Type', 
$type);
 
  695     $this->_nestingLevel = $level;
 
  701     foreach ($children as $child)
 
  703       $level |= $child->getNestingLevel();
 
  711     foreach ($this->_compoundLevelFilters as $bitmask => $rules)
 
  713       if (($compoundLevel & $bitmask) === $bitmask)
 
  715         $filter = $rules + $filter;
 
  719     $realLevel = $child->getNestingLevel();
 
  720     $lowercaseType = strtolower($child->getContentType());
 
  722     if (isset($filter[$realLevel])
 
  723       && isset($filter[$realLevel][$lowercaseType]))
 
  725       return $filter[$realLevel][$lowercaseType];
 
  735     return new self($this->_headers->newInstance(),
 
  741     foreach ($this->_immediateChildren as $child)
 
  743       $child->encoderChanged($encoder);
 
  749     $this->_encoder->charsetChanged($charset);
 
  750     $this->_headers->charsetChanged($charset);
 
  751     foreach ($this->_immediateChildren as $child)
 
  753       $child->charsetChanged($charset);
 
  760     foreach ($this->_immediateChildren as $child)
 
  763       if ($child->getNestingLevel() == self::LEVEL_ALTERNATIVE)
 
  773       usort($this->_immediateChildren, array($this, 
'_childSortAlgorithm'));
 
  779     $typePrefs = array();
 
  781       strtolower($a->getContentType()),
 
  782       strtolower($b->getContentType())
 
  784     foreach ($types as 
$type)
 
  786       $typePrefs[] = (array_key_exists($type, $this->_alternativePartOrder))
 
  787         ? $this->_alternativePartOrder[$type]
 
  788         : (max($this->_alternativePartOrder) + 1);
 
  790     return ($typePrefs[0] >= $typePrefs[1]) ? 1 : -1;
 
  800     $this->_cache->clearAll($this->_cacheKey);