Structure.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. <?php
  2. /*
  3. * File: Structure.php
  4. * Category: -
  5. * Author: M.Goldenbaum
  6. * Created: 17.09.20 20:38
  7. * Updated: -
  8. *
  9. * Description:
  10. * -
  11. */
  12. namespace Webklex\PHPIMAP;
  13. use Webklex\PHPIMAP\Exceptions\InvalidMessageDateException;
  14. use Webklex\PHPIMAP\Exceptions\MessageContentFetchingException;
  15. /**
  16. * Class Structure
  17. *
  18. * @package Webklex\PHPIMAP
  19. */
  20. class Structure {
  21. /**
  22. * Raw structure
  23. *
  24. * @var string $raw
  25. */
  26. public $raw = "";
  27. /**
  28. * @var Header $header
  29. */
  30. private $header = null;
  31. /**
  32. * Message type (if multipart or not)
  33. *
  34. * @var int $type
  35. */
  36. public $type = IMAP::MESSAGE_TYPE_TEXT;
  37. /**
  38. * All available parts
  39. *
  40. * @var Part[] $parts
  41. */
  42. public $parts = [];
  43. /**
  44. * Config holder
  45. *
  46. * @var array $config
  47. */
  48. protected $config = [];
  49. /**
  50. * Structure constructor.
  51. * @param $raw_structure
  52. * @param Header $header
  53. *
  54. * @throws MessageContentFetchingException
  55. * @throws InvalidMessageDateException
  56. */
  57. public function __construct($raw_structure, Header $header) {
  58. $this->raw = $raw_structure;
  59. $this->header = $header;
  60. $this->config = ClientManager::get('options');
  61. $this->parse();
  62. }
  63. /**
  64. * Parse the given raw structure
  65. *
  66. * @throws MessageContentFetchingException
  67. * @throws InvalidMessageDateException
  68. */
  69. protected function parse(){
  70. $this->findContentType();
  71. $this->parts = $this->find_parts();
  72. }
  73. /**
  74. * Determine the message content type
  75. */
  76. public function findContentType(){
  77. $content_type = $this->header->get("content_type");
  78. $content_type = (is_array($content_type)) ? implode(' ', $content_type) : $content_type;
  79. if(stripos($content_type, 'multipart') === 0) {
  80. $this->type = IMAP::MESSAGE_TYPE_MULTIPART;
  81. }else{
  82. $this->type = IMAP::MESSAGE_TYPE_TEXT;
  83. }
  84. }
  85. /**
  86. * Find all available headers and return the left over body segment
  87. * @var string $context
  88. * @var integer $part_number
  89. *
  90. * @return Part[]
  91. * @throws InvalidMessageDateException
  92. */
  93. private function parsePart($context, $part_number = 0){
  94. $body = $context;
  95. while (($pos = strpos($body, "\r\n")) > 0) {
  96. $body = substr($body, $pos + 2);
  97. }
  98. $headers = substr($context, 0, strlen($body) * -1);
  99. $body = substr($body, 0, -2);
  100. $headers = new Header($headers);
  101. if (($boundary = $headers->getBoundary()) !== null) {
  102. return $this->detectParts($boundary, $body, $part_number);
  103. }
  104. return [new Part($body, $headers, $part_number)];
  105. }
  106. /**
  107. * @param string $boundary
  108. * @param string $context
  109. * @param int $part_number
  110. *
  111. * @return array
  112. * @throws InvalidMessageDateException
  113. */
  114. private function detectParts($boundary, $context, $part_number = 0){
  115. $base_parts = explode( $boundary, $context);
  116. $final_parts = [];
  117. foreach($base_parts as $ctx) {
  118. $ctx = substr($ctx, 2);
  119. if ($ctx !== "--" && $ctx != "") {
  120. $parts = $this->parsePart($ctx, $part_number);
  121. foreach ($parts as $part) {
  122. $final_parts[] = $part;
  123. $part_number = $part->part_number;
  124. }
  125. $part_number++;
  126. }
  127. }
  128. return $final_parts;
  129. }
  130. /**
  131. * Find all available parts
  132. *
  133. * @return array
  134. * @throws MessageContentFetchingException
  135. * @throws InvalidMessageDateException
  136. */
  137. public function find_parts(){
  138. if($this->type === IMAP::MESSAGE_TYPE_MULTIPART) {
  139. if (($boundary = $this->header->getBoundary()) === null) {
  140. throw new MessageContentFetchingException("no content found", 0);
  141. }
  142. return $this->detectParts($boundary, $this->raw);
  143. }
  144. return [new Part($this->raw, $this->header)];
  145. }
  146. /**
  147. * Try to find a boundary if possible
  148. *
  149. * @return string|null
  150. * @Depricated since version 2.4.4
  151. */
  152. public function getBoundary(){
  153. return $this->header->getBoundary();
  154. }
  155. }