PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/system/vendor/swift/Swift/Message.php

http://github.com/ushahidi/Ushahidi_Web
PHP | 797 lines | 558 code | 11 blank | 228 comment | 121 complexity | 7a2277fd9dfaead9fb04ab993925e6d9 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * Swift Mailer Message Component
  4. * Composes MIME 1.0 messages meeting various RFC standards
  5. * Deals with attachments, embedded images, multipart bodies, forwarded messages...
  6. * Please read the LICENSE file
  7. * @copyright Chris Corbyn <chris@w3style.co.uk>
  8. * @author Chris Corbyn <chris@w3style.co.uk>
  9. * @package Swift_Message
  10. * @license GNU Lesser General Public License
  11. */
  12. require_once dirname(__FILE__) . "/ClassLoader.php";
  13. Swift_ClassLoader::load("Swift_Address");
  14. Swift_ClassLoader::load("Swift_Message_Mime");
  15. Swift_ClassLoader::load("Swift_Message_Image");
  16. Swift_ClassLoader::load("Swift_Message_Part");
  17. /**
  18. * Swift Message class
  19. * @package Swift_Message
  20. * @author Chris Corbyn <chris@w3style.co.uk>
  21. */
  22. class Swift_Message extends Swift_Message_Mime
  23. {
  24. /**
  25. * Constant from a high priority message (pretty meaningless)
  26. */
  27. const PRIORITY_HIGH = 1;
  28. /**
  29. * Constant for a low priority message
  30. */
  31. const PRIORITY_LOW = 5;
  32. /**
  33. * Constant for a normal priority message
  34. */
  35. const PRIORITY_NORMAL = 3;
  36. /**
  37. * The MIME warning for client not supporting multipart content
  38. * @var string
  39. */
  40. protected $mimeWarning = null;
  41. /**
  42. * The version of the library (Swift) if known.
  43. * @var string
  44. */
  45. protected $libVersion = "";
  46. /**
  47. * A container for references to other objects.
  48. * This is used in some very complex logic when sub-parts get shifted around.
  49. * @var array
  50. */
  51. protected $references = array(
  52. "parent" => array("alternative" => null, "mixed" => null, "related" => null),
  53. "alternative" => array(),
  54. "mixed" => array(),
  55. "related" => array()
  56. );
  57. /**
  58. * Ctor.
  59. * @param string Message subject
  60. * @param string Body
  61. * @param string Content-type
  62. * @param string Encoding
  63. * @param string Charset
  64. */
  65. public function __construct($subject="", $body=null, $type="text/plain", $encoding=null, $charset=null)
  66. {
  67. parent::__construct();
  68. if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get"))
  69. {
  70. date_default_timezone_set(@date_default_timezone_get());
  71. }
  72. $this->setReturnPath(null);
  73. $this->setTo("");
  74. $this->setFrom("");
  75. $this->setCc(null);
  76. $this->setBcc(null);
  77. $this->setReplyTo(null);
  78. $this->setSubject($subject);
  79. $this->setDate(time());
  80. if (defined("Swift::VERSION"))
  81. {
  82. $this->libVersion = Swift::VERSION;
  83. $this->headers->set("X-LibVersion", $this->libVersion);
  84. }
  85. $this->headers->set("MIME-Version", "1.0");
  86. $this->setContentType($type);
  87. $this->setCharset($charset);
  88. $this->setFlowed(true);
  89. $this->setEncoding($encoding);
  90. foreach (array_keys($this->references["parent"]) as $key)
  91. {
  92. $this->setReference("parent", $key, $this);
  93. }
  94. $this->setMimeWarning(
  95. "This is a message in multipart MIME format. Your mail client should not be displaying this. " .
  96. "Consider upgrading your mail client to view this message correctly."
  97. );
  98. if ($body !== null)
  99. {
  100. $this->setData($body);
  101. if ($charset === null)
  102. {
  103. Swift_ClassLoader::load("Swift_Message_Encoder");
  104. if (Swift_Message_Encoder::instance()->isUTF8($body)) $this->setCharset("utf-8");
  105. else $this->setCharset("iso-8859-1");
  106. }
  107. }
  108. }
  109. /**
  110. * Sets a reference so when nodes are nested, operations can be redirected.
  111. * This really should be refactored to use just one array rather than dynamic variables.
  112. * @param string Key 1
  113. * @param string Key 2
  114. * @param Object Reference
  115. */
  116. protected function setReference($where, $key, $ref)
  117. {
  118. if ($ref === $this) $this->references[$where][$key] = false;
  119. else $this->references[$where][$key] = $ref;
  120. }
  121. /**
  122. * Get a reference to an object (for complex reasons).
  123. * @param string Key 1
  124. * @param string Key 2
  125. * @return Object
  126. */
  127. protected function getReference($where, $key)
  128. {
  129. if (!$this->references[$where][$key]) return $this;
  130. else return $this->references[$where][$key];
  131. }
  132. /**
  133. * Get the level in the MIME hierarchy at which this section should appear.
  134. * @return string
  135. */
  136. public function getLevel()
  137. {
  138. return Swift_Message_Mime::LEVEL_TOP;
  139. }
  140. /**
  141. * Set the message id literally.
  142. * Unless you know what you are doing you should be using generateId() rather than this method,
  143. * otherwise you may break compliancy with RFC 2822.
  144. * @param string The message ID string.
  145. */
  146. public function setId($id)
  147. {
  148. $this->headers->set("Message-ID", $id);
  149. }
  150. /**
  151. * Create a RFC 2822 compliant message id, optionally based upon $idstring.
  152. * The message ID includes information about the current time, the server and some random characters.
  153. * @param string An optional string the base the ID on
  154. * @return string The generated message ID, including the <> quotes.
  155. * @author Cristian Rodriguez <judas.iscariote@flyspray.org>
  156. */
  157. public function generateId($idstring=null)
  158. {
  159. $midparams = array(
  160. "utctime" => gmstrftime("%Y%m%d%H%M%S"),
  161. "pid" => getmypid(),
  162. "randint" => mt_rand(),
  163. "customstr" => (preg_match("/^(?<!\\.)[a-z0-9\\.]+(?!\\.)\$/iD", $idstring) ? $idstring : "swift") ,
  164. "hostname" => (isset($_SERVER["SERVER_NAME"]) ? $_SERVER["SERVER_NAME"] : php_uname("n")),
  165. );
  166. $this->setId(vsprintf("<%s.%d.%d.%s@%s>", $midparams));
  167. return $this->getId();
  168. }
  169. /**
  170. * Get the generated message ID for this message, including the <> quotes.
  171. * If generated automatically, or using generateId() this method returns a RFC2822 compliant Message-ID.
  172. * @return string
  173. * @author Cristian Rodriguez <judas.iscariote@flyspray.org>
  174. */
  175. public function getId()
  176. {
  177. return $this->headers->has("Message-ID") ? $this->headers->get("Message-ID") : null;
  178. }
  179. /**
  180. * Set the address in the Return-Path: header
  181. * @param string The bounce-detect address
  182. */
  183. public function setReturnPath($address)
  184. {
  185. if ($address instanceof Swift_Address) $address = $address->build(true);
  186. $this->headers->set("Return-Path", $address);
  187. }
  188. /**
  189. * Return the address used in the Return-Path: header
  190. * @return string
  191. * @param boolean Return the address for SMTP command
  192. */
  193. public function getReturnPath($smtp=false)
  194. {
  195. if ($this->headers->has("Return-Path"))
  196. {
  197. if (!$smtp) return $this->headers->get("Return-Path");
  198. else
  199. {
  200. $path = $this->headers->get("Return-Path");
  201. if (strpos($path, ">") > strpos($path, "<")) return substr($path, ($start = strpos($path, "<")), ($start + strrpos($path, ">") + 1));
  202. else return "<" . $path . ">";
  203. }
  204. }
  205. }
  206. /**
  207. * Set the address in the From: header
  208. * @param string The address to set as From
  209. */
  210. public function setFrom($from)
  211. {
  212. if ($from instanceof Swift_Address) $from = $from->build();
  213. $this->headers->set("From", $from);
  214. }
  215. /**
  216. * Get the address used in the From: header
  217. * @return string
  218. */
  219. public function getFrom()
  220. {
  221. if ($this->headers->has("From")) return $this->headers->get("From");
  222. }
  223. /**
  224. * Set the list of recipients in the To: header
  225. * @param mixed An array or a string
  226. */
  227. public function setTo($to)
  228. {
  229. if ($to)
  230. {
  231. if (!is_array($to)) $to = array($to);
  232. foreach ($to as $key => $value)
  233. {
  234. if ($value instanceof Swift_Address) $to[$key] = $value->build();
  235. }
  236. }
  237. $this->headers->set("To", $to);
  238. }
  239. /**
  240. * Return the list of recipients in the To: header
  241. * @return array
  242. */
  243. public function getTo()
  244. {
  245. if ($this->headers->has("To"))
  246. {
  247. $to = $this->headers->get("To");
  248. if ($to == "") return array();
  249. else return (array) $to;
  250. }
  251. }
  252. /**
  253. * Set the list of recipients in the Reply-To: header
  254. * @param mixed An array or a string
  255. */
  256. public function setReplyTo($replyto)
  257. {
  258. if ($replyto)
  259. {
  260. if (!is_array($replyto)) $replyto = array($replyto);
  261. foreach ($replyto as $key => $value)
  262. {
  263. if ($value instanceof Swift_Address) $replyto[$key] = $value->build();
  264. }
  265. }
  266. $this->headers->set("Reply-To", $replyto);
  267. }
  268. /**
  269. * Return the list of recipients in the Reply-To: header
  270. * @return array
  271. */
  272. public function getReplyTo()
  273. {
  274. if ($this->headers->has("Reply-To"))
  275. {
  276. $reply_to = $this->headers->get("Reply-To");
  277. if ($reply_to == "") return array();
  278. else return (array) $reply_to;
  279. }
  280. }
  281. /**
  282. * Set the list of recipients in the Cc: header
  283. * @param mixed An array or a string
  284. */
  285. public function setCc($cc)
  286. {
  287. if ($cc)
  288. {
  289. if (!is_array($cc)) $cc = array($cc);
  290. foreach ($cc as $key => $value)
  291. {
  292. if ($value instanceof Swift_Address) $cc[$key] = $value->build();
  293. }
  294. }
  295. $this->headers->set("Cc", $cc);
  296. }
  297. /**
  298. * Return the list of recipients in the Cc: header
  299. * @return array
  300. */
  301. public function getCc()
  302. {
  303. if ($this->headers->has("Cc"))
  304. {
  305. $cc = $this->headers->get("Cc");
  306. if ($cc == "") return array();
  307. else return (array) $cc;
  308. }
  309. }
  310. /**
  311. * Set the list of recipients in the Bcc: header
  312. * @param mixed An array or a string
  313. */
  314. public function setBcc($bcc)
  315. {
  316. if ($bcc)
  317. {
  318. if (!is_array($bcc)) $bcc = array($bcc);
  319. foreach ($bcc as $key => $value)
  320. {
  321. if ($value instanceof Swift_Address) $bcc[$key] = $value->build();
  322. }
  323. }
  324. $this->headers->set("Bcc", $bcc);
  325. }
  326. /**
  327. * Return the list of recipients in the Bcc: header
  328. * @return array
  329. */
  330. public function getBcc()
  331. {
  332. if ($this->headers->has("Bcc"))
  333. {
  334. $bcc = $this->headers->get("Bcc");
  335. if ($bcc == "") return array();
  336. else return (array) $bcc;
  337. }
  338. }
  339. /**
  340. * Set the subject in the headers
  341. * @param string The subject of the email
  342. */
  343. public function setSubject($subject)
  344. {
  345. $this->headers->set("Subject", $subject);
  346. }
  347. /**
  348. * Get the current subject used in the headers
  349. * @return string
  350. */
  351. public function getSubject()
  352. {
  353. return $this->headers->get("Subject");
  354. }
  355. /**
  356. * Set the date in the headers in RFC 2822 format
  357. * @param int The time as a UNIX timestamp
  358. */
  359. public function setDate($date)
  360. {
  361. $this->headers->set("Date", date("r", $date));
  362. }
  363. /**
  364. * Get the date as it looks in the headers
  365. * @return string
  366. */
  367. public function getDate()
  368. {
  369. return strtotime($this->headers->get("Date"));
  370. }
  371. /**
  372. * Set the charset of the document
  373. * @param string The charset used
  374. */
  375. public function setCharset($charset)
  376. {
  377. $this->headers->setAttribute("Content-Type", "charset", $charset);
  378. if (($this->getEncoding() == "7bit") && (strtolower($charset) == "utf-8" || strtolower($charset) == "utf8")) $this->setEncoding("8bit");
  379. }
  380. /**
  381. * Get the charset used in the document
  382. * Returns null if none is set
  383. * @return string
  384. */
  385. public function getCharset()
  386. {
  387. if ($this->headers->hasAttribute("Content-Type", "charset"))
  388. {
  389. return $this->headers->getAttribute("Content-Type", "charset");
  390. }
  391. else
  392. {
  393. return null;
  394. }
  395. }
  396. /**
  397. * Set the "format" attribute to flowed
  398. * @param boolean On or Off
  399. */
  400. public function setFlowed($flowed=true)
  401. {
  402. $value = null;
  403. if ($flowed) $value = "flowed";
  404. $this->headers->setAttribute("Content-Type", "format", $value);
  405. }
  406. /**
  407. * Check if the message format is set as flowed
  408. * @return boolean
  409. */
  410. public function isFlowed()
  411. {
  412. if ($this->headers->hasAttribute("Content-Type", "format")
  413. && $this->headers->getAttribute("Content-Type", "format") == "flowed")
  414. {
  415. return true;
  416. }
  417. else return false;
  418. }
  419. /**
  420. * Set the message prioirty in the mail client (don't rely on this)
  421. * @param int The priority as a value between 1 (high) and 5 (low)
  422. */
  423. public function setPriority($priority)
  424. {
  425. $priority = (int) $priority;
  426. if ($priority > self::PRIORITY_LOW) $priority = self::PRIORITY_LOW;
  427. if ($priority < self::PRIORITY_HIGH) $priority = self::PRIORITY_HIGH;
  428. $label = array(1 => "High", 2 => "High", 3 => "Normal", 4 => "Low", 5 => "Low");
  429. $this->headers->set("X-Priority", $priority);
  430. $this->headers->set("X-MSMail-Priority", $label[$priority]);
  431. $this->headers->set("X-MimeOLE", "Produced by SwiftMailer " . $this->libVersion);
  432. }
  433. /**
  434. * Request that the client send back a read-receipt (don't rely on this!)
  435. * @param string Request address
  436. */
  437. public function requestReadReceipt($request)
  438. {
  439. if ($request instanceof Swift_Address) $request = $request->build();
  440. if (!$request)
  441. {
  442. $this->headers->set("Disposition-Notification-To", null);
  443. $this->headers->set("X-Confirm-Reading-To", null);
  444. $this->headers->set("Return-Receipt-To", null);
  445. }
  446. else
  447. {
  448. $this->headers->set("Disposition-Notification-To", $request);
  449. $this->headers->set("X-Confirm-Reading-To", $request);
  450. $this->headers->set("Return-Receipt-To", $request);
  451. }
  452. }
  453. /**
  454. * Check if a read receipt has been requested for this message
  455. * @return boolean
  456. */
  457. public function wantsReadReceipt()
  458. {
  459. return $this->headers->has("Disposition-Notification-To");
  460. }
  461. /**
  462. * Get the current message priority
  463. * Returns NULL if none set
  464. * @return int
  465. */
  466. public function getPriority()
  467. {
  468. if ($this->headers->has("X-Priority")) return $this->headers->get("X-Priority");
  469. else return null;
  470. }
  471. /**
  472. * Alias for setData()
  473. * @param mixed Body
  474. */
  475. public function setBody($body)
  476. {
  477. $this->setData($body);
  478. }
  479. /**
  480. * Alias for getData()
  481. * @return mixed The document body
  482. */
  483. public function getBody()
  484. {
  485. return $this->getData();
  486. }
  487. /**
  488. * Set the MIME warning message which is displayed to old clients
  489. * @var string The full warning message (in 7bit ascii)
  490. */
  491. public function setMimeWarning($text)
  492. {
  493. $this->mimeWarning = (string) $text;
  494. }
  495. /**
  496. * Get the MIME warning which is displayed to old clients
  497. * @return string
  498. */
  499. public function getMimeWarning()
  500. {
  501. return $this->mimeWarning;
  502. }
  503. /**
  504. * Attach a mime part or an attachment of some sort
  505. * Any descendant of Swift_Message_Mime can be added safely (including other Swift_Message objects for mail forwarding!!)
  506. * @param Swift_Message_Mime The document to attach
  507. * @param string An identifier to use (one is returned otherwise)
  508. * @return string The identifier for the part
  509. */
  510. public function attach(Swift_Message_Mime $child, $id=null)
  511. {
  512. try {
  513. switch ($child->getLevel())
  514. {
  515. case Swift_Message_Mime::LEVEL_ALTERNATIVE:
  516. $sign = (strtolower($child->getContentType()) == "text/plain") ? -1 : 1;
  517. $id = $this->getReference("parent", "alternative")->addChild($child, $id, $sign);
  518. $this->setReference("alternative", $id, $child);
  519. break;
  520. case Swift_Message_Mime::LEVEL_RELATED:
  521. $id = "cid:" . $child->getContentId();
  522. $id = $this->getReference("parent", "related")->addChild($child, $id, 1);
  523. $this->setReference("related", $id, $child);
  524. break;
  525. case Swift_Message_Mime::LEVEL_MIXED: default:
  526. $id = $this->getReference("parent", "mixed")->addChild($child, $id, 1);
  527. $this->setReference("mixed", $id, $child);
  528. break;
  529. }
  530. $this->postAttachFixStructure();
  531. $this->fixContentType();
  532. return $id;
  533. } catch (Swift_Message_MimeException $e) {
  534. throw new Swift_Message_MimeException("Something went wrong whilst trying to move some MIME parts during an attach(). " .
  535. "The MIME component threw an exception:<br />" . $e->getMessage());
  536. }
  537. }
  538. /**
  539. * Remove a nested MIME part
  540. * @param string The ID of the attached part
  541. * @throws Swift_Message_MimeException If no such part exists
  542. */
  543. public function detach($id)
  544. {
  545. try {
  546. switch (true)
  547. {
  548. case array_key_exists($id, $this->references["alternative"]):
  549. $this->getReference("parent", "alternative")->removeChild($id);
  550. unset($this->references["alternative"][$id]);
  551. break;
  552. case array_key_exists($id, $this->references["related"]):
  553. $this->getReference("parent", "related")->removeChild($id);
  554. unset($this->references["related"][$id]);
  555. break;
  556. case array_key_exists($id, $this->references["mixed"]):
  557. $this->getReference("parent", "mixed")->removeChild($id);
  558. unset($this->references["mixed"][$id]);
  559. break;
  560. default:
  561. throw new Swift_Message_MimeException("Unable to detach part identified by ID '" . $id . "' since it's not registered.");
  562. break;
  563. }
  564. $this->postDetachFixStructure();
  565. $this->fixContentType();
  566. } catch (Swift_Message_MimeException $e) {
  567. throw new Swift_Message_MimeException("Something went wrong whilst trying to move some MIME parts during a detach(). " .
  568. "The MIME component threw an exception:<br />" . $e->getMessage());
  569. }
  570. }
  571. /**
  572. * Sets the correct content type header by looking at what types of data we have set
  573. */
  574. protected function fixContentType()
  575. {
  576. if (!empty($this->references["mixed"])) $this->setContentType("multipart/mixed");
  577. elseif (!empty($this->references["related"])) $this->setContentType("multipart/related");
  578. elseif (!empty($this->references["alternative"])) $this->setContentType("multipart/alternative");
  579. }
  580. /**
  581. * Move a branch of the tree, containing all it's MIME parts onto another branch
  582. * @param string The content type on the branch itself
  583. * @param string The content type which may exist in the branch's parent
  584. * @param array The array containing all the nodes presently
  585. * @param string The location of the branch now
  586. * @param string The location of the branch after moving
  587. * @param string The key to identify the branch by in it's new location
  588. */
  589. protected function moveBranchIn($type, $nested_type, $from, $old_branch, $new_branch, $tag)
  590. {
  591. $new = new Swift_Message_Part();
  592. $new->setContentType($type);
  593. $this->getReference("parent", $new_branch)->addChild($new, $tag, -1);
  594. switch ($new_branch)
  595. {
  596. case "related": $this->setReference("related", $tag, $new);//relatedRefs[$tag] = $new;
  597. break;
  598. case "mixed": $this->setReference("mixed", $tag, $new);//mixedRefs[$tag] = $new;
  599. break;
  600. }
  601. foreach ($from as $id => $ref)
  602. {
  603. if (!$ref) $ref = $this;
  604. $sign = (strtolower($ref->getContentType()) == "text/plain"
  605. || strtolower($ref->getContentType()) == $nested_type) ? -1 : 1;
  606. switch ($new_branch)
  607. {
  608. case "related": $this->getReference("related", $tag)->addChild($ref, $id, $sign);
  609. break;
  610. case "mixed": $this->getReference("mixed", $tag)->addChild($ref, $id, $sign);
  611. break;
  612. }
  613. $this->getReference("parent", $old_branch)->removeChild($id);
  614. }
  615. $this->setReference("parent", $old_branch, $new); //parentRefs[$old_branch] = $new;
  616. }
  617. /**
  618. * Analyzes the mixing of MIME types in a mulitpart message an re-arranges if needed
  619. * It looks complicated and long winded but the concept is pretty simple, even if putting it
  620. * in code does me make want to cry!
  621. */
  622. protected function postAttachFixStructure()
  623. {
  624. switch (true)
  625. {
  626. case (!empty($this->references["mixed"]) && !empty($this->references["related"]) && !empty($this->references["alternative"])):
  627. if (!isset($this->references["related"]["_alternative"]))
  628. {
  629. $this->moveBranchIn(
  630. "multipart/alternative", "multipart/alternative", $this->references["alternative"], "alternative", "related", "_alternative");
  631. }
  632. if (!isset($this->references["mixed"]["_related"]))
  633. {
  634. $this->moveBranchIn(
  635. "multipart/related", "multipart/alternative", $this->references["related"], "related", "mixed", "_related");
  636. }
  637. break;
  638. case (!empty($this->references["mixed"]) && !empty($this->references["related"])):
  639. if (!isset($this->references["mixed"]["_related"]))
  640. {
  641. $this->moveBranchIn(
  642. "multipart/related", "multipart/related", $this->references["related"], "related", "mixed", "_related");
  643. }
  644. break;
  645. case (!empty($this->references["mixed"]) && !empty($this->references["alternative"])):
  646. if (!isset($this->references["mixed"]["_alternative"]))
  647. {
  648. $this->moveBranchIn(
  649. "multipart/alternative", null, $this->references["alternative"], "alternative", "mixed", "_alternative");
  650. }
  651. break;
  652. case (!empty($this->references["related"]) && !empty($this->references["alternative"])):
  653. if (!isset($this->references["related"]["_alternative"]))
  654. {
  655. $this->moveBranchIn(
  656. "multipart/alternative", "multipart/alternative", $this->references["alternative"], "alternative", "related", "_alternative");
  657. }
  658. break;
  659. }
  660. }
  661. /**
  662. * Move a branch further toward the top of the tree
  663. * @param array The array containing MIME parts from the old branch
  664. * @param string The name of the old branch
  665. * @param string The name of the new branch
  666. * @param string The key of the branch being moved
  667. */
  668. protected function moveBranchOut($from, $old_branch, $new_branch, $tag)
  669. {
  670. foreach ($from as $id => $ref)
  671. {
  672. if (!$ref) $ref = $this;
  673. $sign = (strtolower($ref->getContentType()) == "text/html"
  674. || strtolower($ref->getContentType()) == "multipart/alternative") ? -1 : 1;
  675. $this->getReference("parent", $new_branch)->addChild($ref, $id, $sign);
  676. switch ($new_branch)
  677. {
  678. case "related": $this->getReference("related", $tag)->removeChild($id);
  679. break;
  680. case "mixed": $this->getReference("parent", $old_branch)->removeChild($id);
  681. break;
  682. }
  683. }
  684. $this->getReference("parent", $new_branch)->removeChild($tag);
  685. $mixed = $this->getReference("parent", $new_branch);//parentRefs[$new_branch];
  686. $this->setReference("parent", $old_branch, $mixed);//parentRefs[$old_branch] = $mixed;
  687. switch ($new_branch)
  688. {
  689. case "related": unset($this->references["related"][$tag]);
  690. break;
  691. case "mixed": unset($this->references["mixed"][$tag]);
  692. break;
  693. }
  694. }
  695. /**
  696. * Analyzes the mixing of MIME types in a mulitpart message an re-arranges if needed
  697. * It looks complicated and long winded but the concept is pretty simple, even if putting it
  698. * in code does me make want to cry!
  699. */
  700. protected function postDetachFixStructure()
  701. {
  702. switch (true)
  703. {
  704. case (!empty($this->references["mixed"]) && !empty($this->references["related"]) && !empty($this->references["alternative"])):
  705. if (array_keys($this->references["related"]) == array("_alternative"))
  706. {
  707. $alt = $this->getReference("parent", "related")->getChild("_alternative");
  708. $this->getReference("parent", "mixed")->addChild($alt, "_alternative", -1);
  709. $this->setReference("mixed", "_alternative", $alt);//mixedRefs["_alternative"] = $alt;
  710. $this->getReference("parent", "related")->removeChild("_alternative");
  711. unset($this->references["related"]["_alternative"]);
  712. $this->getReference("parent", "mixed")->removeChild("_related");
  713. unset($this->references["mixed"]["_related"]);
  714. }
  715. if (array_keys($this->references["mixed"]) == array("_related"))
  716. {
  717. $this->moveBranchOut($this->references["related"], "related", "mixed", "_related");
  718. }
  719. break;
  720. case (!empty($this->references["mixed"]) && !empty($this->references["related"])):
  721. if (array_keys($this->references["mixed"]) == array("_related"))
  722. {
  723. $this->moveBranchOut($this->references["related"], "related", "mixed", "_related");
  724. }
  725. if (isset($this->references["related"]["_alternative"]))
  726. {
  727. $this->detach("_alternative");
  728. }
  729. break;
  730. case (!empty($this->references["mixed"]) && !empty($this->references["alternative"])):
  731. if (array_keys($this->references["mixed"]) == array("_alternative"))
  732. {
  733. $this->moveBranchOut($this->references["alternative"], "alternative", "mixed", "_alternative");
  734. }
  735. break;
  736. case (!empty($this->references["related"]) && !empty($this->references["alternative"])):
  737. if (array_keys($this->references["related"]) == array("_alternative"))
  738. {
  739. $this->moveBranchOut($this->references["alternative"], "alternative", "related", "_alternative");
  740. }
  741. break;
  742. case (!empty($this->references["mixed"])):
  743. if (isset($this->references["mixed"]["_related"])) $this->detach("_related");
  744. case (!empty($this->references["related"])):
  745. if (isset($this->references["related"]["_alternative"]) || isset($this->references["mixed"]["_alternative"]))
  746. $this->detach("_alternative");
  747. break;
  748. }
  749. }
  750. /**
  751. * Execute needed logic prior to compilation
  752. */
  753. public function preBuild()
  754. {
  755. $data = $this->getData();
  756. if (!($enc = $this->getEncoding()))
  757. {
  758. $this->setEncoding("8bit");
  759. }
  760. if ($this->getCharset() === null && !$this->numChildren())
  761. {
  762. Swift_ClassLoader::load("Swift_Message_Encoder");
  763. if (is_string($data) && Swift_Message_Encoder::instance()->isUTF8($data))
  764. {
  765. $this->setCharset("utf-8");
  766. }
  767. elseif(is_string($data) && Swift_Message_Encoder::instance()->is7BitAscii($data))
  768. {
  769. $this->setCharset("us-ascii");
  770. if (!$enc) $this->setEncoding("7bit");
  771. }
  772. else $this->setCharset("iso-8859-1");
  773. }
  774. elseif ($this->numChildren())
  775. {
  776. if (!$this->getData())
  777. {
  778. $this->setData($this->getMimeWarning());
  779. $this->setLineWrap(76);
  780. }
  781. if ($this->getCharset() !== null) $this->setCharset(null);
  782. if ($this->isFlowed()) $this->setFlowed(false);
  783. $this->setEncoding("7bit");
  784. }
  785. }
  786. }