/packages/ezc/Mail/src/parser/interfaces/part_parser.php

https://github.com/ksecor/civicrm · PHP · 206 lines · 99 code · 15 blank · 92 comment · 9 complexity · 9a3b85b4557c366ee2dc653b05a490b5 MD5 · raw file

  1. <?php
  2. /**
  3. * File containing the ezcMailPartParser class
  4. *
  5. * @package Mail
  6. * @version 1.6.3
  7. * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
  8. * @license http://ez.no/licenses/new_bsd New BSD License
  9. */
  10. /**
  11. * Base class for all parser parts.
  12. *
  13. * Parse process
  14. * 1. Figure out the headers of the next part.
  15. * 2. Based on the headers, create the parser for the bodyPart corresponding to
  16. * the headers.
  17. * 3. Parse the body line by line. In the case of a multipart or a digest recursively
  18. * start this process. Note that in the case of RFC822 messages the body contains
  19. * headers.
  20. * 4. call finish() on the partParser and retrieve the ezcMailPart
  21. *
  22. * Each parser part gets the header for that part through the constructor
  23. * and is responsible for parsing the body of that part.
  24. * Parsing of the body is done on a push basis trough the parseBody() method
  25. * which is called repeatedly by the parent part for each line in the message.
  26. *
  27. * When there are no more lines the parent part will call finish() and the mail
  28. * part corresponding to the part you are parsing should be returned.
  29. *
  30. * @todo case on headers
  31. * @package Mail
  32. * @version 1.6.3
  33. * @access private
  34. */
  35. abstract class ezcMailPartParser
  36. {
  37. /**
  38. * The name of the last header parsed.
  39. *
  40. * This variable is used when glueing together multi-line headers.
  41. *
  42. * @var string
  43. */
  44. private $lastParsedHeader = null;
  45. /**
  46. * Parse the body of a message line by line.
  47. *
  48. * This method is called by the parent part on a push basis. When there
  49. * are no more lines the parent part will call finish() to retrieve the
  50. * mailPart.
  51. *
  52. * @param string $line
  53. */
  54. abstract public function parseBody( $line );
  55. /**
  56. * Return the result of the parsed part.
  57. *
  58. * This method is called when all the lines of this part have been parsed.
  59. *
  60. * @return ezcMailPart
  61. */
  62. abstract public function finish();
  63. /**
  64. * Returns a part parser corresponding to the given $headers.
  65. *
  66. * @throws ezcBaseFileNotFoundException
  67. * if a neccessary temporary file could not be openened.
  68. * @param ezcMailHeadersHolder $headers
  69. * @return ezcMailPartParser
  70. */
  71. static public function createPartParserForHeaders( ezcMailHeadersHolder $headers )
  72. {
  73. // default as specified by RFC2045 - #5.2
  74. $mainType = 'text';
  75. $subType = 'plain';
  76. // parse the Content-Type header
  77. if ( isset( $headers['Content-Type'] ) )
  78. {
  79. $matches = array();
  80. // matches "type/subtype; blahblahblah"
  81. preg_match_all( '/^(\S+)\/([^;]+)/',
  82. $headers['Content-Type'], $matches, PREG_SET_ORDER );
  83. if ( count( $matches ) > 0 )
  84. {
  85. $mainType = strtolower( $matches[0][1] );
  86. $subType = strtolower( $matches[0][2] );
  87. }
  88. }
  89. $bodyParser = null;
  90. // create the correct type parser for this the detected type of part
  91. switch ( $mainType )
  92. {
  93. /* RFC 2045 defined types */
  94. case 'image':
  95. case 'audio':
  96. case 'video':
  97. case 'application':
  98. $bodyParser = new ezcMailFileParser( $mainType, $subType, $headers );
  99. break;
  100. case 'message':
  101. switch ( $subType )
  102. {
  103. case "rfc822":
  104. $bodyParser = new ezcMailRfc822DigestParser( $headers );
  105. break;
  106. case "delivery-status":
  107. $bodyParser = new ezcMailDeliveryStatusParser( $headers );
  108. break;
  109. default:
  110. $bodyParser = new ezcMailFileParser( $mainType, $subType, $headers );
  111. break;
  112. }
  113. break;
  114. case 'text':
  115. $bodyParser = new ezcMailTextParser( $subType, $headers );
  116. break;
  117. case 'multipart':
  118. switch ( $subType )
  119. {
  120. case 'mixed':
  121. $bodyParser = new ezcMailMultipartMixedParser( $headers );
  122. break;
  123. case 'alternative':
  124. $bodyParser = new ezcMailMultipartAlternativeParser( $headers );
  125. break;
  126. case 'related':
  127. $bodyParser = new ezcMailMultipartRelatedParser( $headers );
  128. break;
  129. case 'digest':
  130. $bodyParser = new ezcMailMultipartDigestParser( $headers );
  131. break;
  132. case 'report':
  133. $bodyParser = new ezcMailMultipartReportParser( $headers );
  134. break;
  135. default:
  136. $bodyParser = new ezcMailMultipartMixedParser( $headers );
  137. break;
  138. }
  139. break;
  140. /* extensions */
  141. default:
  142. // we treat the body as binary if no main content type is set
  143. // or if it is unknown
  144. $bodyParser = new ezcMailFileParser( $mainType, $subType, $headers );
  145. break;
  146. }
  147. return $bodyParser;
  148. }
  149. /**
  150. * Parses the header given by $line and adds to $headers.
  151. *
  152. * This method is usually used to parse the headers for a subpart. The
  153. * only exception is RFC822 parts since you know the type in advance.
  154. *
  155. * @todo deal with headers that are listed several times
  156. * @param string $line
  157. * @param ezcMailHeadersHolder $headers
  158. */
  159. protected function parseHeader( $line, ezcMailHeadersHolder $headers )
  160. {
  161. $matches = array();
  162. preg_match_all( "/^([\w-_]*):\s?(.*)/", $line, $matches, PREG_SET_ORDER );
  163. if ( count( $matches ) > 0 )
  164. {
  165. $headers[$matches[0][1]] = str_replace( "\t", " ", trim( $matches[0][2] ) );
  166. $this->lastParsedHeader = $matches[0][1];
  167. }
  168. else if ( $this->lastParsedHeader !== null ) // take care of folding
  169. {
  170. $headers[$this->lastParsedHeader] .= str_replace( "\t", " ", $line );
  171. }
  172. // else -invalid syntax, this should never happen.
  173. }
  174. /**
  175. * Scans through $headers and sets any specific header properties on $part.
  176. *
  177. * Currently we only have Content-Disposition on the ezcMailPart level.
  178. * All parser parts must call this method once.
  179. *
  180. * @param ezcMailHeadersHolder $headers
  181. * @param ezcMailPart $part
  182. */
  183. static public function parsePartHeaders( ezcMailHeadersHolder $headers, ezcMailPart $part )
  184. {
  185. if ( isset( $headers['Content-Disposition'] ) )
  186. {
  187. $part->contentDisposition = ezcMailRfc2231Implementation::parseContentDisposition( $headers['Content-Disposition'] );
  188. }
  189. }
  190. }
  191. ?>