blob: 1ee11e80786db568350e54554b17757a300ead18 [file] [log] [blame]
<?php
/**
* File containing the ezcMailRfc2231Implementation class
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* @package Mail
* @version //autogen//
* @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved.
* @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @access private
*/
/**
* This class parses header fields that conform to RFC2231.
*
* Headers conforming to this specification are Content-Type and Content-Disposition.
*
* @package Mail
* @version //autogen//
* @access private
*/
class ezcMailRfc2231Implementation
{
/**
* Returns the parsed header $header according to RFC 2231.
*
* This method returns the parsed header as a structured array and is
* intended for internal usage. Use parseContentDisposition and
* parseContentType to retrieve the correct header structs directly.
*
* @param string $header
* @return array( 'argument', array( 'paramName' => array( value => string, charset => string,
* language => string ) ) );
*/
public static function parseHeader( $header )
{
$result = array();
// argument
if ( preg_match( '/^\s*([^;]*);?/i', $header, $matches ) )
{
$result[0] = $matches[1];
}
// We must go through all parameters and store this data because
// parameters can be unordered. We will store them in this buffer
// array( paramName => array( array( value => string, encoding ) ) )
$parameterBuffer = array();
// parameters
if ( preg_match_all( '/\s*(\S*?)="?([^;"]*);?/i', $header, $matches, PREG_SET_ORDER ) )
{
foreach ( $matches as $parameter )
{
// if normal parameter, simply add it
if ( !preg_match( '/([^\*]+)\*(\d+)?(\*)?/', $parameter[1], $metaData ) )
{
$result[1][$parameter[1]] = array( 'value' => $parameter[2] );
}
else // coded and/or folded
{
// metaData [1] holds the param name
// metaData [2] holds the count or is not set in case of charset only
// metaData [3] holds '*' if there is charset in addition to folding
if ( isset( $metaData[2] ) ) // we have folding
{
$parameterBuffer[$metaData[1]][$metaData[2]]['value'] = $parameter[2];
$parameterBuffer[$metaData[1]][$metaData[2]]['encoding'] =
isset( $metaData[3] ) ? true : false;;
}
else
{
$parameterBuffer[$metaData[1]][0]['value'] = $parameter[2];
$parameterBuffer[$metaData[1]][0]['encoding'] = true;
}
}
}
// whohooo... we have all the parameters nicely sorted.
// Now we must go through them all and convert them into the end result
foreach ( $parameterBuffer as $paramName => $parts )
{
// fetch language and encoding if we have it
// syntax: '[charset]'[language]'encoded_string
$language = null;
$charset = null;
if ( $parts[0]['encoding'] == true )
{
preg_match( "/(\S*)'(\S*)'(.*)/", $parts[0]['value'], $matches );
$charset = $matches[1];
$language = $matches[2];
$parts[0]['value'] = urldecode( $matches[3] ); // rewrite value: todo: decoding
$result[1][$paramName] = array( 'value' => $parts[0]['value'] );
}
$result[1][$paramName] = array( 'value' => $parts[0]['value'] );
if ( strlen( $charset ) > 0 )
{
$result[1][$paramName]['charset'] = $charset;
}
if ( strlen( $language ) > 0 )
{
$result[1][$paramName]['language'] = $language;
}
if ( count( $parts > 1 ) )
{
for ( $i = 1; $i < count( $parts ); $i++ )
{
$result[1][$paramName]['value'] .= $parts[$i]['encoding'] ?
urldecode( $parts[$i]['value'] ) : $parts[$i]['value'];
}
}
}
}
return $result;
}
/**
* Returns the a ezcMailContentDispositionHeader for the parsed $header.
*
* If $cd is provided this object will be used to fill in the blanks. This function
* will not clear out any old values in the object.
*
* @param string $header
* @param ezcMailContentDispositionHeader $cd
* @return ezcMailContentDispositionHeader
*/
public static function parseContentDisposition( $header, ezcMailContentDispositionHeader $cd = null )
{
if ( $cd === null )
{
$cd = new ezcMailContentDispositionHeader();
}
$parsedHeader = self::parseHeader( $header );
$cd->disposition = $parsedHeader[0];
if ( isset( $parsedHeader[1] ) )
{
foreach ( $parsedHeader[1] as $paramName => $data )
{
switch ( $paramName )
{
case 'filename':
$cd->fileName = $data['value'];
$cd->displayFileName = trim( $data['value'], '"' );
if ( isset( $data['charset'] ) )
{
$cd->fileNameCharSet = $data['charset'];
$cd->displayFileName = ezcMailCharsetConverter::convertToUTF8Iconv( $cd->displayFileName, $cd->fileNameCharSet );
}
// Work around for bogus email clients that think
// it's allowed to use mime-encoding for filenames.
// It isn't, see RFC 2184, and issue #13038.
else if ( preg_match( '@^=\?[^?]+\?[QqBb]\?@', $cd->displayFileName ) )
{
$cd->displayFileName = ezcMailTools::mimeDecode( $cd->displayFileName );
}
if ( isset( $data['language'] ) )
{
$cd->fileNameLanguage = $data['language'];
}
break;
case 'creation-date':
$cd->creationDate = $data['value'];
break;
case 'modification-date':
$cd->modificationDate = $data['value'];
break;
case 'read-date':
$cd->readDate = $data['value'];
break;
case 'size':
$cd->size = $data['value'];
break;
default:
$cd->additionalParameters[$paramName] = $data['value'];
if ( isset( $data['charset'] ) )
{
$cd->additionalParametersMetaData[$paramName]['charSet'] = $data['charset'];
}
if ( isset( $data['language'] ) )
{
$cd->additionalParametersMetaData[$paramName]['language'] = $data['language'];
}
break;
}
}
}
return $cd;
}
}
?>