/protected/components/ezcomponents/Mail/src/parser/rfc2231_implementation.php

https://github.com/kamarulismail/kamarul-playground · PHP · 192 lines · 128 code · 9 blank · 55 comment · 20 complexity · ba643f71276c1f3d50fab20122e5a127 MD5 · raw file

  1. <?php
  2. /**
  3. * File containing the ezcMailRfc2231Implementation class
  4. *
  5. * @package Mail
  6. * @version 1.7.1
  7. * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
  8. * @license http://ez.no/licenses/new_bsd New BSD License
  9. * @access private
  10. */
  11. /**
  12. * This class parses header fields that conform to RFC2231.
  13. *
  14. * Headers conforming to this specification are Content-Type and Content-Disposition.
  15. *
  16. * @package Mail
  17. * @version 1.7.1
  18. * @access private
  19. */
  20. class ezcMailRfc2231Implementation
  21. {
  22. /**
  23. * Returns the parsed header $header according to RFC 2231.
  24. *
  25. * This method returns the parsed header as a structured array and is
  26. * intended for internal usage. Use parseContentDisposition and
  27. * parseContentType to retrieve the correct header structs directly.
  28. *
  29. * @param string $header
  30. * @return array( 'argument', array( 'paramName' => array( value => string, charset => string,
  31. * language => string ) ) );
  32. */
  33. public static function parseHeader( $header )
  34. {
  35. $result = array();
  36. // argument
  37. if ( preg_match( '/^\s*([^;]*);?/i', $header, $matches ) )
  38. {
  39. $result[0] = $matches[1];
  40. }
  41. // We must go through all parameters and store this data because
  42. // parameters can be unordered. We will store them in this buffer
  43. // array( paramName => array( array( value => string, encoding ) ) )
  44. $parameterBuffer = array();
  45. // parameters
  46. if ( preg_match_all( '/\s*(\S*?)="?([^;"]*);?/i', $header, $matches, PREG_SET_ORDER ) )
  47. {
  48. foreach ( $matches as $parameter )
  49. {
  50. // if normal parameter, simply add it
  51. if ( !preg_match( '/([^\*]+)\*(\d+)?(\*)?/', $parameter[1], $metaData ) )
  52. {
  53. $result[1][$parameter[1]] = array( 'value' => $parameter[2] );
  54. }
  55. else // coded and/or folded
  56. {
  57. // metaData [1] holds the param name
  58. // metaData [2] holds the count or is not set in case of charset only
  59. // metaData [3] holds '*' if there is charset in addition to folding
  60. if ( isset( $metaData[2] ) ) // we have folding
  61. {
  62. $parameterBuffer[$metaData[1]][$metaData[2]]['value'] = $parameter[2];
  63. $parameterBuffer[$metaData[1]][$metaData[2]]['encoding'] =
  64. isset( $metaData[3] ) ? true : false;;
  65. }
  66. else
  67. {
  68. $parameterBuffer[$metaData[1]][0]['value'] = $parameter[2];
  69. $parameterBuffer[$metaData[1]][0]['encoding'] = true;
  70. }
  71. }
  72. }
  73. // whohooo... we have all the parameters nicely sorted.
  74. // Now we must go through them all and convert them into the end result
  75. foreach ( $parameterBuffer as $paramName => $parts )
  76. {
  77. // fetch language and encoding if we have it
  78. // syntax: '[charset]'[language]'encoded_string
  79. $language = null;
  80. $charset = null;
  81. if ( $parts[0]['encoding'] == true )
  82. {
  83. preg_match( "/(\S*)'(\S*)'(.*)/", $parts[0]['value'], $matches );
  84. $charset = $matches[1];
  85. $language = $matches[2];
  86. $parts[0]['value'] = urldecode( $matches[3] ); // rewrite value: todo: decoding
  87. $result[1][$paramName] = array( 'value' => $parts[0]['value'] );
  88. }
  89. $result[1][$paramName] = array( 'value' => $parts[0]['value'] );
  90. if ( strlen( $charset ) > 0 )
  91. {
  92. $result[1][$paramName]['charset'] = $charset;
  93. }
  94. if ( strlen( $language ) > 0 )
  95. {
  96. $result[1][$paramName]['language'] = $language;
  97. }
  98. if ( count( $parts > 1 ) )
  99. {
  100. for ( $i = 1; $i < count( $parts ); $i++ )
  101. {
  102. $result[1][$paramName]['value'] .= $parts[$i]['encoding'] ?
  103. urldecode( $parts[$i]['value'] ) : $parts[$i]['value'];
  104. }
  105. }
  106. }
  107. }
  108. return $result;
  109. }
  110. /**
  111. * Returns the a ezcMailContentDispositionHeader for the parsed $header.
  112. *
  113. * If $cd is provided this object will be used to fill in the blanks. This function
  114. * will not clear out any old values in the object.
  115. *
  116. * @param string $header
  117. * @param ezcMailContentDispositionHeader $cd
  118. * @return ezcMailContentDispositionHeader
  119. */
  120. public static function parseContentDisposition( $header, ezcMailContentDispositionHeader $cd = null )
  121. {
  122. if ( $cd === null )
  123. {
  124. $cd = new ezcMailContentDispositionHeader();
  125. }
  126. $parsedHeader = self::parseHeader( $header );
  127. $cd->disposition = $parsedHeader[0];
  128. if ( isset( $parsedHeader[1] ) )
  129. {
  130. foreach ( $parsedHeader[1] as $paramName => $data )
  131. {
  132. switch ( $paramName )
  133. {
  134. case 'filename':
  135. $cd->fileName = $data['value'];
  136. $cd->displayFileName = trim( $data['value'], '"' );
  137. if ( isset( $data['charset'] ) )
  138. {
  139. $cd->fileNameCharSet = $data['charset'];
  140. $cd->displayFileName = ezcMailCharsetConverter::convertToUTF8Iconv( $cd->displayFileName, $cd->fileNameCharSet );
  141. }
  142. // Work around for bogus email clients that think
  143. // it's allowed to use mime-encoding for filenames.
  144. // It isn't, see RFC 2184, and issue #13038.
  145. else if ( preg_match( '@^=\?[^?]+\?[QqBb]\?@', $cd->displayFileName ) )
  146. {
  147. $cd->displayFileName = ezcMailTools::mimeDecode( $cd->displayFileName );
  148. }
  149. if ( isset( $data['language'] ) )
  150. {
  151. $cd->fileNameLanguage = $data['language'];
  152. }
  153. break;
  154. case 'creation-date':
  155. $cd->creationDate = $data['value'];
  156. break;
  157. case 'modification-date':
  158. $cd->modificationDate = $data['value'];
  159. break;
  160. case 'read-date':
  161. $cd->readDate = $data['value'];
  162. break;
  163. case 'size':
  164. $cd->size = $data['value'];
  165. break;
  166. default:
  167. $cd->additionalParameters[$paramName] = $data['value'];
  168. if ( isset( $data['charset'] ) )
  169. {
  170. $cd->additionalParametersMetaData[$paramName]['charSet'] = $data['charset'];
  171. }
  172. if ( isset( $data['language'] ) )
  173. {
  174. $cd->additionalParametersMetaData[$paramName]['language'] = $data['language'];
  175. }
  176. break;
  177. }
  178. }
  179. }
  180. return $cd;
  181. }
  182. }
  183. ?>