PlainContentEncoder.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. /*
  3. * This file is part of SwiftMailer.
  4. * (c) 2004-2009 Chris Corbyn
  5. *
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. /**
  10. * Handles binary/7/8-bit Transfer Encoding in Swift Mailer.
  11. *
  12. * When sending 8-bit content over SMTP, you should use
  13. * Swift_Transport_Esmtp_EightBitMimeHandler to enable the 8BITMIME SMTP
  14. * extension.
  15. *
  16. * @author Chris Corbyn
  17. */
  18. class Swift_Mime_ContentEncoder_PlainContentEncoder implements Swift_Mime_ContentEncoder
  19. {
  20. /**
  21. * The name of this encoding scheme (probably 7bit or 8bit).
  22. *
  23. * @var string
  24. */
  25. private $name;
  26. /**
  27. * True if canonical transformations should be done.
  28. *
  29. * @var bool
  30. */
  31. private $canonical;
  32. /**
  33. * Creates a new PlainContentEncoder with $name (probably 7bit or 8bit).
  34. *
  35. * @param string $name
  36. * @param bool $canonical if canonicalization transformation should be done
  37. */
  38. public function __construct($name, $canonical = false)
  39. {
  40. $this->name = $name;
  41. $this->canonical = $canonical;
  42. }
  43. /**
  44. * Encode a given string to produce an encoded string.
  45. *
  46. * @param string $string
  47. * @param int $firstLineOffset ignored
  48. * @param int $maxLineLength - 0 means no wrapping will occur
  49. *
  50. * @return string
  51. */
  52. public function encodeString($string, $firstLineOffset = 0, $maxLineLength = 0)
  53. {
  54. if ($this->canonical) {
  55. $string = $this->canonicalize($string);
  56. }
  57. return $this->safeWordwrap($string, $maxLineLength, "\r\n");
  58. }
  59. /**
  60. * Encode stream $in to stream $out.
  61. *
  62. * @param int $firstLineOffset ignored
  63. * @param int $maxLineLength optional, 0 means no wrapping will occur
  64. */
  65. public function encodeByteStream(Swift_OutputByteStream $os, Swift_InputByteStream $is, $firstLineOffset = 0, $maxLineLength = 0)
  66. {
  67. $leftOver = '';
  68. while (false !== $bytes = $os->read(8192)) {
  69. $toencode = $leftOver.$bytes;
  70. if ($this->canonical) {
  71. $toencode = $this->canonicalize($toencode);
  72. }
  73. $wrapped = $this->safeWordwrap($toencode, $maxLineLength, "\r\n");
  74. $lastLinePos = strrpos($wrapped, "\r\n");
  75. $leftOver = substr($wrapped, $lastLinePos);
  76. $wrapped = substr($wrapped, 0, $lastLinePos);
  77. $is->write($wrapped);
  78. }
  79. if (\strlen($leftOver)) {
  80. $is->write($leftOver);
  81. }
  82. }
  83. /**
  84. * Get the name of this encoding scheme.
  85. *
  86. * @return string
  87. */
  88. public function getName()
  89. {
  90. return $this->name;
  91. }
  92. /**
  93. * Not used.
  94. */
  95. public function charsetChanged($charset)
  96. {
  97. }
  98. /**
  99. * A safer (but weaker) wordwrap for unicode.
  100. *
  101. * @param string $string
  102. * @param int $length
  103. * @param string $le
  104. *
  105. * @return string
  106. */
  107. private function safeWordwrap($string, $length = 75, $le = "\r\n")
  108. {
  109. if (0 >= $length) {
  110. return $string;
  111. }
  112. $originalLines = explode($le, $string);
  113. $lines = [];
  114. $lineCount = 0;
  115. foreach ($originalLines as $originalLine) {
  116. $lines[] = '';
  117. $currentLine = &$lines[$lineCount++];
  118. //$chunks = preg_split('/(?<=[\ \t,\.!\?\-&\+\/])/', $originalLine);
  119. $chunks = preg_split('/(?<=\s)/', $originalLine);
  120. foreach ($chunks as $chunk) {
  121. if (0 != \strlen($currentLine)
  122. && \strlen($currentLine.$chunk) > $length) {
  123. $lines[] = '';
  124. $currentLine = &$lines[$lineCount++];
  125. }
  126. $currentLine .= $chunk;
  127. }
  128. }
  129. return implode("\r\n", $lines);
  130. }
  131. /**
  132. * Canonicalize string input (fix CRLF).
  133. *
  134. * @param string $string
  135. *
  136. * @return string
  137. */
  138. private function canonicalize($string)
  139. {
  140. return str_replace(
  141. ["\r\n", "\r", "\n"],
  142. ["\n", "\n", "\r\n"],
  143. $string
  144. );
  145. }
  146. }