Updated to Symfony 2.1 BETA3

This commit is contained in:
Polonkai Gergely
2012-07-16 21:40:19 +02:00
parent 7a06301624
commit 9d0d2ce524
1551 changed files with 157774 additions and 5177 deletions

View File

@@ -429,11 +429,11 @@ class SymfonyRequirements extends RequirementCollection
);
if (version_compare($installedPhpVersion, self::REQUIRED_PHP_VERSION, '>=')) {
$this->addRequirement(
(in_array(date_default_timezone_get(), DateTimeZone::listIdentifiers())),
sprintf('Default timezone is deprecated (%s)', date_default_timezone_get()),
'Fix your <strong>php.ini</strong> file (list of deprecated timezones http://us.php.net/manual/en/timezones.others.php).'
);
$this->addRequirement(
(in_array(date_default_timezone_get(), DateTimeZone::listIdentifiers())),
sprintf('Default timezone "%s" is not supported by your installation of PHP', date_default_timezone_get()),
'Fix your <strong>php.ini</strong> file (check for typos and have a look at the list of deprecated timezones http://php.net/manual/en/timezones.others.php).'
);
}
$this->addRequirement(
@@ -492,6 +492,12 @@ class SymfonyRequirements extends RequirementCollection
/* optional recommendations follow */
$this->addRecommendation(
version_compare($installedPhpVersion, '5.3.4', '>='),
sprintf('Your project might not work properly ("Notice: Trying to get property of non-object") due to the PHP bug #52083 before PHP 5.3.4 (%s installed)', $installedPhpVersion),
'Install PHP 5.3.4 or newer'
);
$this->addRecommendation(
version_compare($installedPhpVersion, '5.3.8', '>='),
sprintf('Annotations might not work properly due to the PHP bug #55156 before PHP 5.3.8 (%s installed)', $installedPhpVersion),

View File

@@ -13,7 +13,7 @@ namespace Symfony\Component\DependencyInjection
interface ContainerAwareInterface
{
function setContainer(ContainerInterface $container = null);
public function setContainer(ContainerInterface $container = null);
}
}
@@ -35,37 +35,37 @@ interface ContainerInterface
const SCOPE_PROTOTYPE = 'prototype';
function set($id, $service, $scope = self::SCOPE_CONTAINER);
public function set($id, $service, $scope = self::SCOPE_CONTAINER);
function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE);
public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE);
function has($id);
public function has($id);
function getParameter($name);
public function getParameter($name);
function hasParameter($name);
public function hasParameter($name);
function setParameter($name, $value);
public function setParameter($name, $value);
function enterScope($name);
public function enterScope($name);
function leaveScope($name);
public function leaveScope($name);
function addScope(ScopeInterface $scope);
public function addScope(ScopeInterface $scope);
function hasScope($name);
public function hasScope($name);
function isScopeActive($name);
public function isScopeActive($name);
}
}
@@ -79,7 +79,7 @@ namespace Symfony\Component\DependencyInjection
interface IntrospectableContainerInterface extends ContainerInterface
{
function initialized($id);
public function initialized($id);
}
}
@@ -340,13 +340,13 @@ class Container implements IntrospectableContainerInterface
}
static public function camelize($id)
public static function camelize($id)
{
return preg_replace_callback('/(^|_|\.)+(.)/', function ($match) { return ('.' === $match[1] ? '_' : '').strtoupper($match[2]); }, $id);
}
static public function underscore($id)
public static function underscore($id)
{
return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), strtr($id, '_', '.')));
}
@@ -356,23 +356,6 @@ class Container implements IntrospectableContainerInterface
namespace Symfony\Component\HttpKernel
{
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
interface TerminableInterface
{
function terminate(Request $request, Response $response);
}
}
namespace Symfony\Component\HttpKernel
{
@@ -386,7 +369,7 @@ interface HttpKernelInterface
const SUB_REQUEST = 2;
function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
}
}
@@ -405,55 +388,72 @@ use Symfony\Component\Config\Loader\LoaderInterface;
interface KernelInterface extends HttpKernelInterface, \Serializable
{
function registerBundles();
public function registerBundles();
function registerContainerConfiguration(LoaderInterface $loader);
public function registerContainerConfiguration(LoaderInterface $loader);
function boot();
public function boot();
function shutdown();
public function shutdown();
function getBundles();
public function getBundles();
function isClassInActiveBundle($class);
public function isClassInActiveBundle($class);
function getBundle($name, $first = true);
public function getBundle($name, $first = true);
function locateResource($name, $dir = null, $first = true);
public function locateResource($name, $dir = null, $first = true);
function getName();
public function getName();
function getEnvironment();
public function getEnvironment();
function isDebug();
public function isDebug();
function getRootDir();
public function getRootDir();
function getContainer();
public function getContainer();
function getStartTime();
public function getStartTime();
function getCacheDir();
public function getCacheDir();
function getLogDir();
public function getLogDir();
function getCharset();
public function getCharset();
}
}
namespace Symfony\Component\HttpKernel
{
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
interface TerminableInterface
{
public function terminate(Request $request, Response $response);
}
}
@@ -502,12 +502,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface
protected $classes;
protected $errorReportingLevel;
const VERSION = '2.1.0-BETA2';
const VERSION = '2.1.0-DEV';
const VERSION_ID = '20100';
const MAJOR_VERSION = '2';
const MINOR_VERSION = '1';
const RELEASE_VERSION = '0';
const EXTRA_VERSION = 'BETA';
const EXTRA_VERSION = 'DEV';
public function __construct($environment, $debug)
@@ -516,7 +516,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
$this->debug = (Boolean) $debug;
$this->booted = false;
$this->rootDir = $this->getRootDir();
$this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
$this->name = $this->getName();
$this->classes = array();
if ($this->debug) {
@@ -706,6 +706,10 @@ abstract class Kernel implements KernelInterface, TerminableInterface
public function getName()
{
if (null === $this->name) {
$this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
}
return $this->name;
}
@@ -975,7 +979,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface
}
static public function stripComments($source)
public static function stripComments($source)
{
if (!function_exists('token_get_all')) {
return $source;
@@ -1084,28 +1088,28 @@ use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
interface BundleInterface extends ContainerAwareInterface
{
function boot();
public function boot();
function shutdown();
public function shutdown();
function build(ContainerBuilder $container);
public function build(ContainerBuilder $container);
function getContainerExtension();
public function getContainerExtension();
function getParent();
public function getParent();
function getName();
public function getName();
function getNamespace();
public function getNamespace();
function getPath();
public function getPath();
}
}
@@ -1348,6 +1352,7 @@ namespace Symfony\Component\HttpKernel
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
@@ -1450,14 +1455,27 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface
$event = new GetResponseForExceptionEvent($this, $request, $type, $e);
$this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event);
$e = $event->getException();
if (!$event->hasResponse()) {
throw $e;
}
$response = $event->getResponse();
if (!$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) {
if ($e instanceof HttpExceptionInterface) {
$response->setStatusCode($e->getStatusCode());
$response->headers->add($e->getHeaders());
} else {
$response->setStatusCode(500);
}
}
try {
return $this->filterResponse($event->getResponse(), $request, $type);
return $this->filterResponse($response, $request, $type);
} catch (\Exception $e) {
return $event->getResponse();
return $response;
}
}

View File

@@ -17,7 +17,8 @@
"sensio/framework-extra-bundle": "dev-master",
"sensio/generator-bundle": "dev-master",
"jms/security-extra-bundle": "1.1.*",
"jms/di-extra-bundle": "1.0.*"
"jms/di-extra-bundle": "1.0.*",
"egeloen/ckeditor-bundle": "2.0.*"
},
"scripts": {
"post-install-cmd": [

59
composer.lock generated
View File

@@ -1,5 +1,5 @@
{
"hash": "ab7ccf177098603cace942212179431f",
"hash": "0890891a613a13d9980307e458190353",
"packages": [
{
"package": "doctrine/common",
@@ -8,20 +8,23 @@
{
"package": "doctrine/dbal",
"version": "2.2.x-dev",
"source-reference": "b961a3fce6bf220f1dca47d7d747b9074bea4730",
"commit-date": "1341779435"
"source-reference": "b961a3fce6bf220f1dca47d7d747b9074bea4730"
},
{
"package": "doctrine/doctrine-bundle",
"version": "dev-master",
"source-reference": "c9ea46d1f0c48bb88bb87b44214fe44e03c0c692",
"commit-date": "1341405737"
"source-reference": "c9ea46d1f0c48bb88bb87b44214fe44e03c0c692"
},
{
"package": "doctrine/orm",
"version": "2.2.x-dev",
"source-reference": "5d2a3bcb3b467f41ee58575764f3ba84937f76e4",
"commit-date": "1341676080"
"source-reference": "5d2a3bcb3b467f41ee58575764f3ba84937f76e4"
},
{
"package": "egeloen/ckeditor-bundle",
"version": "2.0.x-dev",
"source-reference": "ca9d4a631577d7195c6517dd89ae8a3cc02b85ba",
"commit-date": "1337272707"
},
{
"package": "jms/aop-bundle",
@@ -52,8 +55,7 @@
{
"package": "kriswallsmith/assetic",
"version": "dev-master",
"source-reference": "d6f89a3170c5280ad554347dc113eb25fdf00ad7",
"commit-date": "1339515714"
"source-reference": "d6f89a3170c5280ad554347dc113eb25fdf00ad7"
},
{
"package": "monolog/monolog",
@@ -62,20 +64,20 @@
{
"package": "sensio/distribution-bundle",
"version": "dev-master",
"source-reference": "9a7dbd867fd5061e4bfd660a175aa66122f53d25",
"commit-date": "1341741741"
"source-reference": "5886adae1613c0a72fbb95259a83ae798e86c0d3",
"commit-date": "1342347850"
},
{
"package": "sensio/framework-extra-bundle",
"version": "dev-master",
"source-reference": "4f54e5d5fb3b54fb107892684018f3704934c48d",
"commit-date": "1341126219"
"source-reference": "e9ac8f1a911ed29e30296c7f1549f53d4c94eddf",
"commit-date": "1342084432"
},
{
"package": "sensio/generator-bundle",
"version": "dev-master",
"source-reference": "43ed45c48db18e4a0e48aec0c098f42e56e22d36",
"commit-date": "1340138445"
"source-reference": "c17dbddefe517e3adfcbeaa1ab7cef3e572d29c6",
"commit-date": "1342195488"
},
{
"package": "swiftmailer/swiftmailer",
@@ -86,25 +88,25 @@
{
"package": "swiftmailer/swiftmailer",
"version": "dev-master",
"source-reference": "f51b5f33c83b48faea75f1285f99a2e8f1c66f75",
"commit-date": "1341746460"
"source-reference": "8b2aa953f87da228ba413e8fb1372e49c1374050",
"commit-date": "1342198037"
},
{
"package": "symfony/assetic-bundle",
"version": "dev-master",
"source-reference": "8fe7b898b08103c1d6fce64c3e279a7afd61adfc",
"commit-date": "1340234971"
"source-reference": "ed933dcfa45f00b6bc6d7727007403f3ff429e5a",
"commit-date": "1342126277"
},
{
"package": "symfony/monolog-bundle",
"version": "dev-master",
"source-reference": "7fe7f711bb04b86ad7f45a9e11a7f8cbaf9bc1a5",
"source-reference": "v2.1.0-BETA3",
"commit-date": "1341078487"
},
{
"package": "symfony/swiftmailer-bundle",
"version": "dev-master",
"source-reference": "e1d413ce27fd1696bdc82ad9525f1b874664530e",
"source-reference": "v2.1.0-BETA3",
"commit-date": "1341509614"
},
{
@@ -116,14 +118,13 @@
{
"package": "symfony/symfony",
"version": "dev-master",
"source-reference": "v2.1.0-BETA2",
"commit-date": "1341820358"
"source-reference": "151b79a6ce3f459e2fa8815cd9f2786eef750993",
"commit-date": "1342376835"
},
{
"package": "twig/extensions",
"version": "dev-master",
"source-reference": "feb6d3f10c411e2631997c0a905aa581c80305c1",
"commit-date": "1337599699"
"source-reference": "feb6d3f10c411e2631997c0a905aa581c80305c1"
},
{
"package": "twig/twig",
@@ -134,13 +135,11 @@
{
"package": "twig/twig",
"version": "dev-master",
"source-reference": "26eb0a2653eade50dffdd31b11ca454232dea8cf",
"commit-date": "1341423205"
"source-reference": "d45664045194ef62573c153c424508527105041e",
"commit-date": "1342424564"
}
],
"packages-dev": [
],
"packages-dev": null,
"aliases": [
],

BIN
composer.phar Executable file

Binary file not shown.

View File

@@ -21,6 +21,7 @@ return array(
'JMS\\SecurityExtraBundle' => $vendorDir . '/jms/security-extra-bundle/',
'JMS\\DiExtraBundle' => $vendorDir . '/jms/di-extra-bundle/',
'JMS\\AopBundle' => $vendorDir . '/jms/aop-bundle/',
'Ivory\\CKEditorBundle' => $vendorDir . '/egeloen/ckeditor-bundle/',
'Doctrine\\ORM' => $vendorDir . '/doctrine/orm/lib/',
'Doctrine\\DBAL' => $vendorDir . '/doctrine/dbal/lib/',
'Doctrine\\Common' => $vendorDir . '/doctrine/common/lib/',

View File

@@ -3,7 +3,7 @@
"name": "jms/metadata",
"version": "1.1.1",
"version_normalized": "1.1.1.0",
"time": "2011-12-30 10:32:49",
"time": "2011-12-29 22:32:49",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/metadata",
@@ -47,7 +47,7 @@
"name": "jms/cg",
"version": "1.0.0",
"version_normalized": "1.0.0.0",
"time": "2011-12-30 09:40:52",
"time": "2011-12-29 21:40:52",
"source": {
"type": "git",
"url": "git://github.com/schmittjoh/cg-library.git",
@@ -89,7 +89,7 @@
"version": "1.0.0",
"version_normalized": "1.0.0.0",
"target-dir": "JMS/AopBundle",
"time": "2011-12-30 09:50:26",
"time": "2011-12-29 21:50:26",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/JMSAopBundle",
@@ -133,7 +133,7 @@
"version": "1.1.0",
"version_normalized": "1.1.0.0",
"target-dir": "JMS/SecurityExtraBundle",
"time": "2011-12-30 13:38:12",
"time": "2011-12-30 01:38:12",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/JMSSecurityExtraBundle",
@@ -178,7 +178,7 @@
"version": "1.0.1",
"version_normalized": "1.0.1.0",
"target-dir": "JMS/DiExtraBundle",
"time": "2012-02-25 05:01:54",
"time": "2012-02-24 17:01:54",
"source": {
"type": "git",
"url": "https://github.com/schmittjoh/JMSDiExtraBundle",
@@ -221,7 +221,7 @@
"name": "doctrine/common",
"version": "2.2.2",
"version_normalized": "2.2.2.0",
"time": "2012-04-08 03:46:44",
"time": "2012-04-07 03:46:44",
"source": {
"type": "git",
"url": "https://github.com/doctrine/common",
@@ -287,7 +287,7 @@
"name": "monolog/monolog",
"version": "1.1.0",
"version_normalized": "1.1.0.0",
"time": "2012-04-18 14:27:40",
"time": "2012-04-17 14:27:40",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
@@ -337,7 +337,7 @@
"name": "twig/extensions",
"version": "dev-master",
"version_normalized": "9999999-dev",
"time": "2012-05-16 21:28:19",
"time": "2012-05-15 21:28:19",
"source": {
"type": "git",
"url": "https://github.com/fabpot/Twig-extensions",
@@ -382,7 +382,7 @@
"name": "kriswallsmith/assetic",
"version": "dev-master",
"version_normalized": "9999999-dev",
"time": "2012-06-08 01:41:54",
"time": "2012-06-07 01:41:54",
"source": {
"type": "git",
"url": "http://github.com/kriswallsmith/assetic.git",
@@ -437,285 +437,12 @@
}
}
},
{
"name": "sensio/generator-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Sensio/Bundle/GeneratorBundle",
"time": "2012-06-15 18:40:45",
"source": {
"type": "git",
"url": "https://github.com/sensio/SensioGeneratorBundle",
"reference": "43ed45c48db18e4a0e48aec0c098f42e56e22d36"
},
"dist": {
"type": "zip",
"url": "https://github.com/sensio/SensioGeneratorBundle/zipball/43ed45c48db18e4a0e48aec0c098f42e56e22d36",
"reference": "43ed45c48db18e4a0e48aec0c098f42e56e22d36",
"shasum": ""
},
"require": {
"symfony/framework-bundle": "2.1.*"
},
"require-dev": {
"symfony/doctrine-bridge": "2.1.*",
"doctrine/orm": ">=2.1,<2.4-dev",
"twig/twig": ">=1.8,<2.0-dev"
},
"suggest": {
"doctrine/doctrine-bundle": "to generate entities and their crud controller"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev"
}
},
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
}
],
"description": "This bundle generates code for you",
"autoload": {
"psr-0": {
"Sensio\\Bundle\\GeneratorBundle": ""
}
}
},
{
"name": "symfony/assetic-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Symfony/Bundle/AsseticBundle",
"time": "2012-06-16 23:29:31",
"source": {
"type": "git",
"url": "https://github.com/symfony/AsseticBundle",
"reference": "8fe7b898b08103c1d6fce64c3e279a7afd61adfc"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/AsseticBundle/zipball/8fe7b898b08103c1d6fce64c3e279a7afd61adfc",
"reference": "8fe7b898b08103c1d6fce64c3e279a7afd61adfc",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"symfony/framework-bundle": "2.1.*",
"kriswallsmith/assetic": "1.1.*"
},
"suggest": {
"symfony/twig-bundle": "2.1.*"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev"
}
},
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Kris Wallsmith",
"email": "kris.wallsmith@gmail.com",
"homepage": "http://kriswallsmith.net/",
"role": null
}
],
"description": "Integrates Assetic into Symfony2",
"homepage": "https://github.com/symfony/AsseticBundle",
"keywords": [
"assets",
"compression",
"minification"
],
"autoload": {
"psr-0": {
"Symfony\\Bundle\\AsseticBundle": ""
}
}
},
{
"name": "symfony/monolog-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Symfony/Bundle/MonologBundle",
"time": "2012-06-28 15:48:07",
"source": {
"type": "git",
"url": "https://github.com/symfony/MonologBundle",
"reference": "7fe7f711bb04b86ad7f45a9e11a7f8cbaf9bc1a5"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/MonologBundle/zipball/7fe7f711bb04b86ad7f45a9e11a7f8cbaf9bc1a5",
"reference": "7fe7f711bb04b86ad7f45a9e11a7f8cbaf9bc1a5",
"shasum": ""
},
"require": {
"php": ">=5.3.2",
"monolog/monolog": "1.*",
"symfony/monolog-bridge": "2.1.*",
"symfony/dependency-injection": "2.1.*",
"symfony/config": "2.1.*"
},
"require-dev": {
"symfony/yaml": "2.1.*",
"symfony/config": "2.1.*"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev"
}
},
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
},
{
"name": "Symfony Community",
"email": null,
"homepage": "http://symfony.com/contributors",
"role": null
}
],
"description": "Symfony MonologBundle",
"homepage": "http://symfony.com",
"autoload": {
"psr-0": {
"Symfony\\Bundle\\MonologBundle": ""
}
}
},
{
"name": "sensio/framework-extra-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Sensio/Bundle/FrameworkExtraBundle",
"time": "2012-06-29 05:03:39",
"source": {
"type": "git",
"url": "https://github.com/sensio/SensioFrameworkExtraBundle",
"reference": "4f54e5d5fb3b54fb107892684018f3704934c48d"
},
"dist": {
"type": "zip",
"url": "https://github.com/sensio/SensioFrameworkExtraBundle/zipball/4f54e5d5fb3b54fb107892684018f3704934c48d",
"reference": "4f54e5d5fb3b54fb107892684018f3704934c48d",
"shasum": ""
},
"require": {
"doctrine/common": ">=2.1,<2.4-dev",
"symfony/framework-bundle": "2.1.*"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev"
}
},
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
}
],
"description": "This bundle provides a way to configure your controllers with annotations",
"keywords": [
"annotations",
"controllers"
],
"autoload": {
"psr-0": {
"Sensio\\Bundle\\FrameworkExtraBundle": ""
}
}
},
{
"name": "twig/twig",
"version": "dev-master",
"version_normalized": "9999999-dev",
"time": "2012-07-03 15:33:25",
"source": {
"type": "git",
"url": "git://github.com/fabpot/Twig.git",
"reference": "26eb0a2653eade50dffdd31b11ca454232dea8cf"
},
"dist": {
"type": "zip",
"url": "https://github.com/fabpot/Twig/zipball/26eb0a2653eade50dffdd31b11ca454232dea8cf",
"reference": "26eb0a2653eade50dffdd31b11ca454232dea8cf",
"shasum": ""
},
"require": {
"php": ">=5.2.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
}
},
"installation-source": "source",
"license": [
"BSD-3"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"homepage": null,
"role": null
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
],
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
}
},
{
"name": "doctrine/doctrine-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Doctrine/Bundle/DoctrineBundle",
"time": "2012-07-03 10:42:17",
"time": "2012-07-02 10:42:17",
"source": {
"type": "git",
"url": "git://github.com/doctrine/DoctrineBundle.git",
@@ -785,70 +512,11 @@
}
}
},
{
"name": "symfony/swiftmailer-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Symfony/Bundle/SwiftmailerBundle",
"time": "2012-07-04 15:33:34",
"source": {
"type": "git",
"url": "https://github.com/symfony/SwiftmailerBundle",
"reference": "e1d413ce27fd1696bdc82ad9525f1b874664530e"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/SwiftmailerBundle/zipball/e1d413ce27fd1696bdc82ad9525f1b874664530e",
"reference": "e1d413ce27fd1696bdc82ad9525f1b874664530e",
"shasum": ""
},
"require": {
"php": ">=5.3.2",
"symfony/swiftmailer-bridge": "2.1.*",
"swiftmailer/swiftmailer": ">=4.2.0,<4.3-dev"
},
"require-dev": {
"symfony/dependency-injection": "2.1.*",
"symfony/http-kernel": "2.1.*",
"symfony/config": "2.1.*"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
},
{
"name": "Symfony Community",
"email": null,
"homepage": "http://symfony.com/contributors",
"role": null
}
],
"description": "Symfony SwiftmailerBundle",
"homepage": "http://symfony.com",
"autoload": {
"psr-0": {
"Symfony\\Bundle\\SwiftmailerBundle": ""
}
}
},
{
"name": "doctrine/orm",
"version": "2.2.x-dev",
"version_normalized": "2.2.9999999.9999999-dev",
"time": "2012-07-07 07:48:00",
"time": "2012-07-06 07:48:00",
"source": {
"type": "git",
"url": "git://github.com/doctrine/doctrine2.git",
@@ -909,66 +577,11 @@
}
}
},
{
"name": "swiftmailer/swiftmailer",
"version": "dev-master",
"version_normalized": "9999999-dev",
"time": "2012-07-08 09:21:00",
"source": {
"type": "git",
"url": "git://github.com/swiftmailer/swiftmailer.git",
"reference": "f51b5f33c83b48faea75f1285f99a2e8f1c66f75"
},
"dist": {
"type": "zip",
"url": "https://github.com/swiftmailer/swiftmailer/zipball/f51b5f33c83b48faea75f1285f99a2e8f1c66f75",
"reference": "f51b5f33c83b48faea75f1285f99a2e8f1c66f75",
"shasum": ""
},
"require": {
"php": ">=5.2.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.2-dev"
}
},
"installation-source": "source",
"license": [
"LGPL"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
},
{
"name": "Chris Corbyn",
"email": "",
"homepage": null,
"role": null
}
],
"description": "Swiftmailer, free feature-rich PHP mailer",
"homepage": "http://swiftmailer.org",
"keywords": [
"mail",
"mailer"
],
"autoload": {
"files": [
"lib/swift_required.php"
]
}
},
{
"name": "doctrine/dbal",
"version": "2.2.x-dev",
"version_normalized": "2.2.9999999.9999999-dev",
"time": "2012-07-08 18:30:35",
"time": "2012-07-07 18:30:35",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal",
@@ -1030,25 +643,456 @@
}
},
{
"name": "symfony/symfony",
"version": "dev-master",
"version_normalized": "9999999-dev",
"time": "2012-07-09 05:52:38",
"name": "egeloen/ckeditor-bundle",
"version": "2.0.x-dev",
"version_normalized": "2.0.9999999.9999999-dev",
"target-dir": "Ivory/CKEditorBundle",
"time": "2012-05-16 18:38:27",
"source": {
"type": "git",
"url": "git://github.com/symfony/symfony.git",
"reference": "v2.1.0-BETA2"
"url": "https://github.com/egeloen/IvoryCKEditorBundle",
"reference": "ca9d4a631577d7195c6517dd89ae8a3cc02b85ba"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/symfony/zipball/v2.1.0-BETA2",
"reference": "v2.1.0-BETA2",
"url": "https://github.com/egeloen/IvoryCKEditorBundle/zipball/ca9d4a631577d7195c6517dd89ae8a3cc02b85ba",
"reference": "ca9d4a631577d7195c6517dd89ae8a3cc02b85ba",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"symfony/framework-bundle": "2.*"
},
"type": "symfony-bundle",
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Eric GELOEN",
"email": "geloen.eric@gmail.com",
"homepage": null,
"role": null
}
],
"description": "Provides a CKEditor integration for your Symfony2 Project.",
"keywords": [
"CKEditor"
],
"autoload": {
"psr-0": {
"Ivory\\CKEditorBundle": ""
}
}
},
{
"name": "sensio/generator-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Sensio/Bundle/GeneratorBundle",
"time": "2012-07-13 00:04:48",
"source": {
"type": "git",
"url": "https://github.com/sensio/SensioGeneratorBundle",
"reference": "c17dbddefe517e3adfcbeaa1ab7cef3e572d29c6"
},
"dist": {
"type": "zip",
"url": "https://github.com/sensio/SensioGeneratorBundle/zipball/c17dbddefe517e3adfcbeaa1ab7cef3e572d29c6",
"reference": "c17dbddefe517e3adfcbeaa1ab7cef3e572d29c6",
"shasum": ""
},
"require": {
"symfony/framework-bundle": "2.1.*"
},
"require-dev": {
"symfony/doctrine-bridge": "2.1.*",
"doctrine/orm": ">=2.1,<2.4-dev",
"twig/twig": ">=1.8,<2.0-dev"
},
"suggest": {
"doctrine/doctrine-bundle": "to generate entities and their crud controller"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev"
}
},
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
}
],
"description": "This bundle generates code for you",
"autoload": {
"psr-0": {
"Sensio\\Bundle\\GeneratorBundle": ""
}
}
},
{
"name": "symfony/assetic-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Symfony/Bundle/AsseticBundle",
"time": "2012-07-12 06:51:17",
"source": {
"type": "git",
"url": "https://github.com/symfony/AsseticBundle",
"reference": "ed933dcfa45f00b6bc6d7727007403f3ff429e5a"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/AsseticBundle/zipball/ed933dcfa45f00b6bc6d7727007403f3ff429e5a",
"reference": "ed933dcfa45f00b6bc6d7727007403f3ff429e5a",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"symfony/framework-bundle": "2.1.*",
"kriswallsmith/assetic": "1.1.*"
},
"suggest": {
"symfony/twig-bundle": "2.1.*"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev"
}
},
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Kris Wallsmith",
"email": "kris.wallsmith@gmail.com",
"homepage": "http://kriswallsmith.net/",
"role": null
}
],
"description": "Integrates Assetic into Symfony2",
"homepage": "https://github.com/symfony/AsseticBundle",
"keywords": [
"assets",
"compression",
"minification"
],
"autoload": {
"psr-0": {
"Symfony\\Bundle\\AsseticBundle": ""
}
}
},
{
"name": "symfony/monolog-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Symfony/Bundle/MonologBundle",
"time": "2012-06-30 05:48:07",
"source": {
"type": "git",
"url": "https://github.com/symfony/MonologBundle",
"reference": "v2.1.0-BETA3"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/MonologBundle/zipball/v2.1.0-BETA3",
"reference": "v2.1.0-BETA3",
"shasum": ""
},
"require": {
"php": ">=5.3.2",
"monolog/monolog": "1.*",
"symfony/monolog-bridge": "2.1.*",
"symfony/dependency-injection": "2.1.*",
"symfony/config": "2.1.*"
},
"require-dev": {
"symfony/yaml": "2.1.*",
"symfony/config": "2.1.*"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev"
}
},
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
},
{
"name": "Symfony Community",
"email": null,
"homepage": "http://symfony.com/contributors",
"role": null
}
],
"description": "Symfony MonologBundle",
"homepage": "http://symfony.com",
"autoload": {
"psr-0": {
"Symfony\\Bundle\\MonologBundle": ""
}
}
},
{
"name": "sensio/framework-extra-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Sensio/Bundle/FrameworkExtraBundle",
"time": "2012-07-11 23:13:52",
"source": {
"type": "git",
"url": "https://github.com/sensio/SensioFrameworkExtraBundle",
"reference": "e9ac8f1a911ed29e30296c7f1549f53d4c94eddf"
},
"dist": {
"type": "zip",
"url": "https://github.com/sensio/SensioFrameworkExtraBundle/zipball/e9ac8f1a911ed29e30296c7f1549f53d4c94eddf",
"reference": "e9ac8f1a911ed29e30296c7f1549f53d4c94eddf",
"shasum": ""
},
"require": {
"doctrine/common": ">=2.1,<2.4-dev",
"symfony/framework-bundle": "2.1.*"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev"
}
},
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
}
],
"description": "This bundle provides a way to configure your controllers with annotations",
"keywords": [
"annotations",
"controllers"
],
"autoload": {
"psr-0": {
"Sensio\\Bundle\\FrameworkExtraBundle": ""
}
}
},
{
"name": "twig/twig",
"version": "dev-master",
"version_normalized": "9999999-dev",
"time": "2012-07-15 23:42:44",
"source": {
"type": "git",
"url": "git://github.com/fabpot/Twig.git",
"reference": "d45664045194ef62573c153c424508527105041e"
},
"dist": {
"type": "zip",
"url": "https://github.com/fabpot/Twig/zipball/d45664045194ef62573c153c424508527105041e",
"reference": "d45664045194ef62573c153c424508527105041e",
"shasum": ""
},
"require": {
"php": ">=5.2.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.9-dev"
}
},
"installation-source": "source",
"license": [
"BSD-3"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"homepage": null,
"role": null
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
],
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
}
},
{
"name": "symfony/swiftmailer-bundle",
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Symfony/Bundle/SwiftmailerBundle",
"time": "2012-07-05 11:33:34",
"source": {
"type": "git",
"url": "https://github.com/symfony/SwiftmailerBundle",
"reference": "v2.1.0-BETA3"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/SwiftmailerBundle/zipball/v2.1.0-BETA3",
"reference": "v2.1.0-BETA3",
"shasum": ""
},
"require": {
"php": ">=5.3.2",
"symfony/swiftmailer-bridge": "2.1.*",
"swiftmailer/swiftmailer": ">=4.2.0,<4.3-dev"
},
"require-dev": {
"symfony/dependency-injection": "2.1.*",
"symfony/http-kernel": "2.1.*",
"symfony/config": "2.1.*"
},
"type": "symfony-bundle",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"installation-source": "source",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
},
{
"name": "Symfony Community",
"email": null,
"homepage": "http://symfony.com/contributors",
"role": null
}
],
"description": "Symfony SwiftmailerBundle",
"homepage": "http://symfony.com",
"autoload": {
"psr-0": {
"Symfony\\Bundle\\SwiftmailerBundle": ""
}
}
},
{
"name": "swiftmailer/swiftmailer",
"version": "dev-master",
"version_normalized": "9999999-dev",
"time": "2012-07-13 12:47:17",
"source": {
"type": "git",
"url": "git://github.com/swiftmailer/swiftmailer.git",
"reference": "8b2aa953f87da228ba413e8fb1372e49c1374050"
},
"dist": {
"type": "zip",
"url": "https://github.com/swiftmailer/swiftmailer/zipball/8b2aa953f87da228ba413e8fb1372e49c1374050",
"reference": "8b2aa953f87da228ba413e8fb1372e49c1374050",
"shasum": ""
},
"require": {
"php": ">=5.2.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.2-dev"
}
},
"installation-source": "source",
"license": [
"LGPL"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": null,
"role": null
},
{
"name": "Chris Corbyn",
"email": "",
"homepage": null,
"role": null
}
],
"description": "Swiftmailer, free feature-rich PHP mailer",
"homepage": "http://swiftmailer.org",
"keywords": [
"mail",
"mailer"
],
"autoload": {
"files": [
"lib/swift_required.php"
]
}
},
{
"name": "symfony/symfony",
"version": "dev-master",
"version_normalized": "9999999-dev",
"time": "2012-07-15 16:27:15",
"source": {
"type": "git",
"url": "git://github.com/symfony/symfony.git",
"reference": "151b79a6ce3f459e2fa8815cd9f2786eef750993"
},
"dist": {
"type": "zip",
"url": "https://github.com/symfony/symfony/zipball/151b79a6ce3f459e2fa8815cd9f2786eef750993",
"reference": "151b79a6ce3f459e2fa8815cd9f2786eef750993",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"twig/twig": ">=1.8,<2.0-dev",
"doctrine/common": ">2.2,<2.4-dev"
"doctrine/common": ">2.2,<2.4-dev",
"php": ">=5.3.3"
},
"replace": {
"symfony/doctrine-bridge": "self.version",
@@ -1135,16 +1179,16 @@
"version": "dev-master",
"version_normalized": "9999999-dev",
"target-dir": "Sensio/Bundle/DistributionBundle",
"time": "2012-07-08 08:02:21",
"time": "2012-07-15 10:24:10",
"source": {
"type": "git",
"url": "https://github.com/sensio/SensioDistributionBundle",
"reference": "9a7dbd867fd5061e4bfd660a175aa66122f53d25"
"reference": "5886adae1613c0a72fbb95259a83ae798e86c0d3"
},
"dist": {
"type": "zip",
"url": "https://github.com/sensio/SensioDistributionBundle/zipball/9a7dbd867fd5061e4bfd660a175aa66122f53d25",
"reference": "9a7dbd867fd5061e4bfd660a175aa66122f53d25",
"url": "https://github.com/sensio/SensioDistributionBundle/zipball/5886adae1613c0a72fbb95259a83ae798e86c0d3",
"reference": "5886adae1613c0a72fbb95259a83ae798e86c0d3",
"shasum": ""
},
"require": {

Submodule vendor/egeloen/ckeditor-bundle/Ivory/CKEditorBundle added at ca9d4a6315

View File

@@ -31,7 +31,7 @@ class ScriptHandler
return;
}
static::executeBuildBootstrap($appDir);
static::executeBuildBootstrap($appDir, $options['process-timeout']);
}
public static function clearCache($event)
@@ -45,7 +45,7 @@ class ScriptHandler
return;
}
static::executeCommand($event, $appDir, 'cache:clear --no-warmup');
static::executeCommand($event, $appDir, 'cache:clear --no-warmup', $options['process-timeout']);
}
public static function installAssets($event)
@@ -123,7 +123,7 @@ namespace { return \$loader; }
", substr(file_get_contents($file), 5)));
}
protected static function executeCommand($event, $appDir, $cmd)
protected static function executeCommand($event, $appDir, $cmd, $timeout = 300)
{
$php = escapeshellarg(self::getPhp());
$console = escapeshellarg($appDir.'/console');
@@ -131,17 +131,17 @@ namespace { return \$loader; }
$console.= ' --ansi';
}
$process = new Process($php.' '.$console.' '.$cmd, null, null, null, 300);
$process = new Process($php.' '.$console.' '.$cmd, null, null, null, $timeout);
$process->run(function ($type, $buffer) { echo $buffer; });
}
protected static function executeBuildBootstrap($appDir)
protected static function executeBuildBootstrap($appDir, $timeout = 300)
{
$php = escapeshellarg(self::getPhp());
$cmd = escapeshellarg(__DIR__.'/../Resources/bin/build_bootstrap.php');
$appDir = escapeshellarg($appDir);
$process = new Process($php.' '.$cmd.' '.$appDir, null, null, null, 300);
$process = new Process($php.' '.$cmd.' '.$appDir, null, null, null, $timeout);
$process->run(function ($type, $buffer) { echo $buffer; });
}
@@ -155,6 +155,8 @@ namespace { return \$loader; }
$options['symfony-assets-install'] = getenv('SYMFONY_ASSETS_INSTALL') ?: $options['symfony-assets-install'];
$options['process-timeout'] = $event->getComposer()->getConfig()->get('process-timeout');
return $options;
}

View File

@@ -1,91 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\DistributionBundle\Diff;
/**
* Computes a Diff between files (line by line).
*
* Implements the Longest common subsequence problem algorithm.
*
* @see http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Diff
{
private $diff;
public function __construct($str1, $str2)
{
$lines1 = explode("\n", $str1);
$lines2 = explode("\n", $str2);
$this->diff = $this->computeDiff($this->computeLcs($lines1, $lines2), $lines1, $lines2, count($lines1) - 1, count($lines2) - 1);
}
public function getDiff()
{
$diff = array();
for ($i = 0, $max = count($this->diff); $i < $max; $i++) {
if ('' != $this->diff[$i][0]) {
$diff[] = array('@', sprintf(' Line %s', $this->diff[$i][2]));
do {
$diff[] = $this->diff[$i++];
} while ('' != $this->diff[$i][0]);
}
}
return $diff;
}
public function computeDiff(array $c, array $lines1, array $lines2, $i, $j)
{
$diff = array();
if ($i > -1 && $j > -1 && $lines1[$i] == $lines2[$j]) {
$diff = array_merge($diff, $this->computeDiff($c, $lines1, $lines2, $i - 1, $j - 1));
$diff[] = array('', $lines1[$i], $i, $j);
} else {
if ($j > -1 && ($i == -1 || $c[$i][$j - 1] >= $c[$i - 1][$j])) {
$diff = array_merge($diff, $this->computeDiff($c, $lines1, $lines2, $i, $j - 1));
$diff[] = array('+', $lines2[$j], $i, $j);
} elseif ($i > -1 && ($j == -1 || $c[$i][$j - 1] < $c[$i - 1][$j])) {
$diff = array_merge($diff, $this->computeDiff($c, $lines1, $lines2, $i - 1, $j));
$diff[] = array('-', $lines1[$i], $i, $j);
}
}
return $diff;
}
private function computeLcs(array $lines1, array $lines2)
{
for ($i = -1, $len1 = count($lines1); $i < $len1; $i++) {
for ($j = -1, $len2 = count($lines2); $j < $len2; $j++) {
$c[$i][$j] = 0;
}
}
for ($i = 0; $i < $len1; $i++) {
for ($j = 0; $j < $len2; $j++) {
if ($lines1[$i] == $lines2[$j]) {
$c[$i][$j] = $c[$i - 1][$j - 1] + 1;
} else {
$c[$i][$j] = max($c[$i][$j - 1], $c[$i - 1][$j]);
}
}
}
return $c;
}
}

View File

@@ -429,11 +429,11 @@ class SymfonyRequirements extends RequirementCollection
);
if (version_compare($installedPhpVersion, self::REQUIRED_PHP_VERSION, '>=')) {
$this->addRequirement(
(in_array(date_default_timezone_get(), DateTimeZone::listIdentifiers())),
sprintf('Default timezone is deprecated (%s)', date_default_timezone_get()),
'Fix your <strong>php.ini</strong> file (list of deprecated timezones http://us.php.net/manual/en/timezones.others.php).'
);
$this->addRequirement(
(in_array(date_default_timezone_get(), DateTimeZone::listIdentifiers())),
sprintf('Default timezone "%s" is not supported by your installation of PHP', date_default_timezone_get()),
'Fix your <strong>php.ini</strong> file (check for typos and have a look at the list of deprecated timezones http://php.net/manual/en/timezones.others.php).'
);
}
$this->addRequirement(
@@ -492,6 +492,12 @@ class SymfonyRequirements extends RequirementCollection
/* optional recommendations follow */
$this->addRecommendation(
version_compare($installedPhpVersion, '5.3.4', '>='),
sprintf('Your project might not work properly ("Notice: Trying to get property of non-object") due to the PHP bug #52083 before PHP 5.3.4 (%s installed)', $installedPhpVersion),
'Install PHP 5.3.4 or newer'
);
$this->addRecommendation(
version_compare($installedPhpVersion, '5.3.8', '>='),
sprintf('Annotations might not work properly due to the PHP bug #55156 before PHP 5.3.8 (%s installed)', $installedPhpVersion),

View File

@@ -1,59 +0,0 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\DistributionBundle\Upgrade;
use Sensio\Bundle\DistributionBundle\Diff\Diff;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Upgrade class.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class Upgrade
{
public function outputConsoleDiff(OutputInterface $output, $file1, $file2)
{
if (is_file($file1)) {
$file1 = realpath($file1);
$str1 = file_get_contents($file1);
} else {
$str1 = '';
}
if (!is_file($file2)) {
throw new \RuntimeException(sprintf('The skeleton file "%s" does not exist.', $file2));
}
$file2 = realpath($file2);
$str2 = file_get_contents($file2);
$diff = new Diff($str1, $str2);
$output->writeln(sprintf('--- %s', $file1));
$output->writeln(sprintf('+++ %s', $file2));
foreach ($diff->getDiff() as $line) {
if ('+' == $line[0]) {
$format = '<fg=green>+%s</>';
} elseif ('-' == $line[0]) {
$format = '<fg=red>-%s</>';
} elseif ('@' == $line[0]) {
$format = '<fg=cyan>@%s</>';
} else {
$format = ' %s';
}
$output->writeln(sprintf($format, $line[1]));
}
$output->writeln('');
}
}

View File

@@ -0,0 +1,4 @@
coverage
phpunit.xml
vendor
composer.lock

View File

@@ -0,0 +1,6 @@
CHANGELOG for 2.1.x
===================
* added the possibility to configure the id name for the Doctrine converter via the id option
* [BC break] The ParamConverterInterface::apply() method now must return a
Boolean value indicating if a conversion was done.

View File

@@ -74,6 +74,19 @@ option::
{
}
This also allows you to have multiple converters in one action::
/**
* @Route("/blog/{id}/comments/{comment_id}")
* @ParamConverter("comment", class="SensioBlogBundle:Comment", options={"id" = "comment_id"})
*/
public function showAction(Post $post, Comment $comment)
{
}
In the example above, the post parameter is handled automatically, but the comment is
configured with the annotation since they can not both follow the default convention.
Creating a Converter
--------------------

View File

@@ -0,0 +1,18 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\Configuration;
class ConfigurationAnnotationTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException RuntimeException
*/
public function testUndefinedSetterThrowsException()
{
$this->getMockForAbstractClass('Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationAnnotation', array(
array(
'doesNotExists' => true,
),
));
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Sensio\Bundle\FrameworkExtraBundle\EventListener\CacheListener;
class CacheListenerTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->listener = new CacheListener();
$this->response = new Response();
$this->cache = new Cache(array());
$this->request = $this->createRequest($this->cache);
$this->event = $this->createEventMock($this->request, $this->response);
}
public function testWontReassignResponseWhenResponseIsUnsuccessful()
{
$this->event
->expects($this->never())
->method('setResponse')
;
$this->response->setStatusCode(404);
$this->assertInternalType('null', $this->listener->onKernelResponse($this->event));
}
public function testWontReassignResponseWhenNoConfigurationIsPresent()
{
$this->event
->expects($this->never())
->method('setResponse')
;
$this->request->attributes->remove('_cache');
$this->assertInternalType('null', $this->listener->onKernelResponse($this->event));
}
public function testResponseIsPublicIfConfigurationIsPublic()
{
$request = $this->createRequest(new Cache(array(
'public' => true,
)));
$this->listener->onKernelResponse($this->createEventMock($request, $this->response));
$this->assertTrue($this->response->headers->hasCacheControlDirective('public'));
$this->assertFalse($this->response->headers->hasCacheControlDirective('private'));
}
public function testConfigurationAttributesAreSetOnResponse()
{
$this->assertInternalType('null', $this->response->getMaxAge());
$this->assertInternalType('null', $this->response->getExpires());
$this->assertFalse($this->response->headers->hasCacheControlDirective('s-maxage'));
$this->request->attributes->set('_cache', new Cache(array(
'expires' => 'tomorrow',
'smaxage' => '15',
'maxage' => '15',
)));
$this->listener->onKernelResponse($this->event);
$this->assertEquals('15', $this->response->getMaxAge());
$this->assertEquals('15', $this->response->headers->getCacheControlDirective('s-maxage'));
$this->assertInstanceOf('DateTime', $this->response->getExpires());
}
protected function createRequest(Cache $cache = null)
{
return new Request(array(), array(), array(
'_cache' => $cache,
));
}
protected function createEventMock(Request $request, Response $response)
{
$event = $this->getMock('Symfony\Component\HttpKernel\Event\FilterResponseEvent', array(), array(), '', null);
$event
->expects($this->any())
->method('getRequest')
->will($this->returnValue($request))
;
$event
->expects($this->any())
->method('getResponse')
->will($this->returnValue($response))
;
return $event;
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Sensio\Bundle\FrameworkExtraBundle\EventListener\ControllerListener;
use Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener\Fixture\FooControllerCacheAtClass;
use Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener\Fixture\FooControllerCacheAtClassAndMethod;
use Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener\Fixture\FooControllerCacheAtMethod;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class ControllerListenerTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->listener = new ControllerListener(new AnnotationReader());
$this->request = $this->createRequest();
}
public function tearDown()
{
$this->listener = null;
$this->request = null;
}
public function testCacheAnnotationAtMethod()
{
$controller = new FooControllerCacheAtMethod();
$this->event = $this->getFilterControllerEvent(array($controller, 'barAction'), $this->request);
$this->listener->onKernelController($this->event);
$this->assertNotNull($this->getReadedCache());
$this->assertEquals(FooControllerCacheAtMethod::METHOD_SMAXAGE, $this->getReadedCache()->getSMaxAge());
}
public function testCacheAnnotationAtClass()
{
$controller = new FooControllerCacheAtClass();
$this->event = $this->getFilterControllerEvent(array($controller, 'barAction'), $this->request);
$this->listener->onKernelController($this->event);
$this->assertNotNull($this->getReadedCache());
$this->assertEquals(FooControllerCacheAtClass::CLASS_SMAXAGE, $this->getReadedCache()->getSMaxAge());
}
public function testCacheAnnotationAtClassAndMethod()
{
$controller = new FooControllerCacheAtClassAndMethod();
$this->event = $this->getFilterControllerEvent(array($controller, 'barAction'), $this->request);
$this->listener->onKernelController($this->event);
$this->assertNotNull($this->getReadedCache());
$this->assertEquals(FooControllerCacheAtClassAndMethod::METHOD_SMAXAGE, $this->getReadedCache()->getSMaxAge());
$this->event = $this->getFilterControllerEvent(array($controller, 'bar2Action'), $this->request);
$this->listener->onKernelController($this->event);
$this->assertNotNull($this->getReadedCache());
$this->assertEquals(FooControllerCacheAtClassAndMethod::CLASS_SMAXAGE, $this->getReadedCache()->getSMaxAge());
}
protected function createRequest(Cache $cache = null)
{
return new Request(array(), array(), array(
'_cache' => $cache,
));
}
protected function getFilterControllerEvent($controller, Request $request)
{
$mockKernel = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\Kernel', array('', ''));
return new FilterControllerEvent($mockKernel, $controller, $request, HttpKernelInterface::MASTER_REQUEST);
}
protected function getReadedCache()
{
return $this->request->attributes->get('_cache');
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener\Fixture;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
/**
* @Cache(smaxage="20")
*/
class FooControllerCacheAtClass
{
const CLASS_SMAXAGE = 20;
public function barAction()
{
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener\Fixture;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
/**
* @Cache(smaxage="20")
*/
class FooControllerCacheAtClassAndMethod
{
const CLASS_SMAXAGE = 20;
const METHOD_SMAXAGE = 15;
/**
* @Cache(smaxage="15")
*/
public function barAction()
{
}
public function bar2Action()
{
}
}

View File

@@ -0,0 +1,17 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\EventListener\Fixture;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
class FooControllerCacheAtMethod
{
const METHOD_SMAXAGE = 15;
/**
* @Cache(smaxage="15")
*/
public function barAction()
{
}
}

View File

@@ -0,0 +1,87 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\Request\ParamConverter;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\DoctrineParamConverter;
class DoctrineParamConverterTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Doctrine\Common\Persistence\ManagerRegistry
*/
private $manager;
/**
* @var DoctrineParamConverter
*/
private $converter;
public function setUp()
{
if (!interface_exists('Doctrine\Common\Persistence\ManagerRegistry')) {
$this->markTestSkipped();
}
$this->manager = $this->getMock('Doctrine\Common\Persistence\ManagerRegistry');
$this->converter = new DoctrineParamConverter($this->manager);
}
public function createConfiguration($class = null, array $options = null)
{
$config = $this->getMock(
'Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface', array(
'getClass', 'getAliasName', 'getOptions'
));
if ($options !== null) {
$config->expects($this->once())
->method('getOptions')
->will($this->returnValue($options));
}
if ($class !== null) {
$config->expects($this->any())
->method('getClass')
->will($this->returnValue($class));
}
return $config;
}
public function testApplyWithNoIdAndData()
{
$request = new Request();
$config = $this->createConfiguration(null, array());
$objectManager = $this->getMock('Doctrine\Common\Persistence\ObjectManager');
$this->manager->expects($this->never())->method('find');
$this->manager->expects($this->once())
->method('getManager')
->will($this->returnValue($objectManager));
$this->setExpectedException('LogicException');
$this->converter->apply($request, $config);
}
public function testSupports()
{
$config = $this->createConfiguration('stdClass', array());
$metadataFactory = $this->getMock('Doctrine\Common\Persistence\Mapping\ClassMetadataFactory');
$metadataFactory->expects($this->once())
->method('isTransient')
->with($this->equalTo('stdClass'))
->will($this->returnValue( false ));
$objectManager = $this->getMock('Doctrine\Common\Persistence\ObjectManager');
$objectManager->expects($this->once())
->method('getMetadataFactory')
->will($this->returnValue($metadataFactory));
$this->manager->expects($this->once())
->method('getManager')
->will($this->returnValue($objectManager));
$ret = $this->converter->supports($config);
$this->assertTrue($ret, "Should be supported");
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace Sensio\Bundle\FrameworkExtraBundle\Tests\Request\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager;
use Sensio\Bundle\FrameworkExtraBundle\Configuration;
use Symfony\Component\HttpFoundation\Request;
class ParamConverterManagerTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->manager = new ParamConverterManager();
}
public function testPriorities()
{
$this->assertEquals(array(), $this->manager->all());
$high = $this->createParamConverterMock();
$low = $this->createParamConverterMock();
$this->manager->add($low);
$this->manager->add($high, 10);
$this->assertEquals(array(
$high,
$low,
), $this->manager->all());
}
public function testApply()
{
$supported = $this->createParamConverterMock();
$supported
->expects($this->once())
->method('supports')
->will($this->returnValue(true))
;
$supported
->expects($this->once())
->method('apply')
->will($this->returnValue(false))
;
$invalid = $this->createParamConverterMock();
$invalid
->expects($this->once())
->method('supports')
->will($this->returnValue(false))
;
$invalid
->expects($this->never())
->method('apply')
;
$configurations = array(
new Configuration\ParamConverter(array(
'name' => 'var',
)),
);
$this->manager->add($supported);
$this->manager->add($invalid);
$this->manager->apply(new Request(), $configurations);
}
public function testApplyNotCalledOnAlreadyConvertedObjects()
{
$converter = $this->createParamConverterMock();
$converter
->expects($this->never())
->method('supports')
;
$converter
->expects($this->never())
->method('apply')
;
$this->manager->add($converter);
$request = new Request();
$request->attributes->set('converted', new \stdClass);
$configuration = new Configuration\ParamConverter(array(
'name' => 'converted',
'class' => 'stdClass',
));
$this->manager->apply($request, array($configuration));
}
protected function createParamConverterMock()
{
return $this->getMock('Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterInterface');
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="SensioFrameworkExtraBundle">
<directory suffix="Test.php">./Tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Resources</directory>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@@ -0,0 +1,3 @@
phpunit.xml
vendor
composer.lock

View File

@@ -55,7 +55,7 @@ conventions):
<info>php app/console generate:bundle --namespace=Acme/BlogBundle</info>
Note that you can use <comment>/</comment> instead of <comment>\\</comment> for the namespace delimiter to avoid any
Note that you can use <comment>/</comment> instead of <comment>\\ </comment>for the namespace delimiter to avoid any
problem.
If you want to disable any user interaction, use <comment>--no-interaction</comment> but don't forget to pass all needed options:

View File

@@ -0,0 +1,101 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\GeneratorBundle\Tests\Command;
use Symfony\Component\Console\Tester\CommandTester;
use Sensio\Bundle\GeneratorBundle\Command\GenerateBundleCommand;
class GenerateBundleCommandTest extends GenerateCommandTest
{
/**
* @dataProvider getInteractiveCommandData
*/
public function testInteractiveCommand($options, $input, $expected)
{
list($namespace, $bundle, $dir, $format, $structure) = $expected;
$generator = $this->getGenerator();
$generator
->expects($this->once())
->method('generate')
->with($namespace, $bundle, $dir, $format, $structure)
;
$tester = new CommandTester($this->getCommand($generator, $input));
$tester->execute($options);
}
public function getInteractiveCommandData()
{
$tmp = sys_get_temp_dir();
return array(
array(array('--dir' => $tmp), "Foo/BarBundle\n", array('Foo\BarBundle', 'FooBarBundle', $tmp.'/', 'annotation', false)),
array(array('--dir' => $tmp), "Foo/BarBundle\nBarBundle\nfoo\nyml\nn", array('Foo\BarBundle', 'BarBundle', 'foo/', 'yml', false)),
array(array('--dir' => $tmp, '--format' => 'yml', '--bundle-name' => 'BarBundle', '--structure' => true), "Foo/BarBundle\n", array('Foo\BarBundle', 'BarBundle', $tmp.'/', 'yml', true)),
);
}
/**
* @dataProvider getNonInteractiveCommandData
*/
public function testNonInteractiveCommand($options, $expected)
{
list($namespace, $bundle, $dir, $format, $structure) = $expected;
$generator = $this->getGenerator();
$generator
->expects($this->once())
->method('generate')
->with($namespace, $bundle, $dir, $format, $structure)
;
$tester = new CommandTester($this->getCommand($generator, ''));
$tester->execute($options, array('interactive' => false));
}
public function getNonInteractiveCommandData()
{
$tmp = sys_get_temp_dir();
return array(
array(array('--dir' => $tmp, '--namespace' => 'Foo/BarBundle'), array('Foo\BarBundle', 'FooBarBundle', $tmp.'/', 'annotation', false)),
array(array('--dir' => $tmp, '--namespace' => 'Foo/BarBundle', '--format' => 'yml', '--bundle-name' => 'BarBundle', '--structure' => true), array('Foo\BarBundle', 'BarBundle', $tmp.'/', 'yml', true)),
);
}
protected function getCommand($generator, $input)
{
$command = $this
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Command\GenerateBundleCommand')
->setMethods(array('checkAutoloader', 'updateKernel', 'updateRouting'))
->getMock()
;
$command->setContainer($this->getContainer());
$command->setHelperSet($this->getHelperSet($input));
$command->setGenerator($generator);
return $command;
}
protected function getGenerator()
{
// get a noop generator
return $this
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Generator\BundleGenerator')
->disableOriginalConstructor()
->setMethods(array('generate'))
->getMock()
;
}
}

View File

@@ -0,0 +1,74 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\GeneratorBundle\Tests\Command;
use Symfony\Component\Console\Helper\HelperSet;
use Symfony\Component\Console\Helper\FormatterHelper;
use Sensio\Bundle\GeneratorBundle\Command\Helper\DialogHelper;
use Symfony\Component\DependencyInjection\Container;
abstract class GenerateCommandTest extends \PHPUnit_Framework_TestCase
{
protected function getHelperSet($input)
{
$dialog = new DialogHelper();
$dialog->setInputStream($this->getInputStream($input));
return new HelperSet(array(new FormatterHelper(), $dialog));
}
protected function getBundle()
{
$bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\BundleInterface');
$bundle
->expects($this->any())
->method('getPath')
->will($this->returnValue(sys_get_temp_dir()))
;
return $bundle;
}
protected function getInputStream($input)
{
$stream = fopen('php://memory', 'r+', false);
fputs($stream, $input.str_repeat("\n", 10));
rewind($stream);
return $stream;
}
protected function getContainer()
{
$kernel = $this->getMock('Symfony\Component\HttpKernel\KernelInterface');
$kernel
->expects($this->any())
->method('getBundle')
->will($this->returnValue($this->getBundle()))
;
$filesystem = $this->getMock('Symfony\Component\Filesystem\Filesystem');
$filesystem
->expects($this->any())
->method('isAbsolutePath')
->will($this->returnValue(true))
;
$container = new Container();
$container->set('kernel', $kernel);
$container->set('filesystem', $filesystem);
$container->setParameter('kernel.root_dir', sys_get_temp_dir());
return $container;
}
}

View File

@@ -0,0 +1,141 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\GeneratorBundle\Tests\Command;
use Symfony\Component\Console\Tester\CommandTester;
use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCrudCommand;
class GenerateDoctrineCrudCommandTest extends GenerateCommandTest
{
/**
* @dataProvider getInteractiveCommandData
*/
public function testInteractiveCommand($options, $input, $expected)
{
list($entity, $format, $prefix, $withWrite) = $expected;
$generator = $this->getGenerator();
$generator
->expects($this->once())
->method('generate')
->with($this->getBundle(), $entity, $this->getDoctrineMetadata(), $format, $prefix, $withWrite)
;
$tester = new CommandTester($this->getCommand($generator, $input));
$tester->execute($options);
}
public function getInteractiveCommandData()
{
return array(
array(array(), "AcmeBlogBundle:Blog/Post\n", array('Blog\\Post', 'annotation', 'blog_post', false)),
array(array('--entity' => 'AcmeBlogBundle:Blog/Post'), '', array('Blog\\Post', 'annotation', 'blog_post', false)),
array(array(), "AcmeBlogBundle:Blog/Post\ny\nyml\nfoobar\n", array('Blog\\Post', 'yml', 'foobar', true)),
array(array(), "AcmeBlogBundle:Blog/Post\ny\nyml\n/foobar\n", array('Blog\\Post', 'yml', 'foobar', true)),
array(array('--entity' => 'AcmeBlogBundle:Blog/Post', '--format' => 'yml', '--route-prefix' => 'foo', '--with-write' => true), '', array('Blog\\Post', 'yml', 'foo', true)),
);
}
/**
* @dataProvider getNonInteractiveCommandData
*/
public function testNonInteractiveCommand($options, $expected)
{
list($entity, $format, $prefix, $withWrite) = $expected;
$generator = $this->getGenerator();
$generator
->expects($this->once())
->method('generate')
->with($this->getBundle(), $entity, $this->getDoctrineMetadata(), $format, $prefix, $withWrite)
;
$tester = new CommandTester($this->getCommand($generator, ''));
$tester->execute($options, array('interactive' => false));
}
public function getNonInteractiveCommandData()
{
return array(
array(array('--entity' => 'AcmeBlogBundle:Blog/Post'), array('Blog\\Post', 'annotation', 'blog_post', false)),
array(array('--entity' => 'AcmeBlogBundle:Blog/Post', '--format' => 'yml', '--route-prefix' => 'foo', '--with-write' => true), array('Blog\\Post', 'yml', 'foo', true)),
);
}
protected function getCommand($generator, $input)
{
$command = $this
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCrudCommand')
->setMethods(array('getEntityMetadata'))
->getMock()
;
$command
->expects($this->any())
->method('getEntityMetadata')
->will($this->returnValue(array($this->getDoctrineMetadata())))
;
$command->setContainer($this->getContainer());
$command->setHelperSet($this->getHelperSet($input));
$command->setGenerator($generator);
$command->setFormGenerator($this->getFormGenerator());
return $command;
}
protected function getDoctrineMetadata()
{
return $this
->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadataInfo')
->disableOriginalConstructor()
->getMock()
;
}
protected function getGenerator()
{
// get a noop generator
return $this
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator')
->disableOriginalConstructor()
->setMethods(array('generate'))
->getMock()
;
}
protected function getFormGenerator()
{
return $this
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Generator\DoctrineFormGenerator')
->disableOriginalConstructor()
->setMethods(array('generate'))
->getMock()
;
}
protected function getContainer()
{
$container = parent::getContainer();
$registry = $this->getMock('Symfony\Bridge\Doctrine\RegistryInterface');
$registry
->expects($this->any())
->method('getEntityNamespace')
->will($this->returnValue('Foo\\FooBundle\\Entity'))
;
$container->set('doctrine', $registry);
return $container;
}
}

View File

@@ -0,0 +1,104 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\GeneratorBundle\Tests\Command;
use Symfony\Component\Console\Tester\CommandTester;
use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineEntityCommand;
class GenerateDoctrineEntityCommandTest extends GenerateCommandTest
{
/**
* @dataProvider getInteractiveCommandData
*/
public function testInteractiveCommand($options, $input, $expected)
{
list($entity, $format, $fields) = $expected;
$generator = $this->getGenerator();
$generator
->expects($this->once())
->method('generate')
->with($this->getBundle(), $entity, $format, $fields)
;
$tester = new CommandTester($this->getCommand($generator, $input));
$tester->execute($options);
}
public function getInteractiveCommandData()
{
return array(
array(array(), "AcmeBlogBundle:Blog/Post\n", array('Blog\\Post', 'annotation', array())),
array(array('--entity' => 'AcmeBlogBundle:Blog/Post'), '', array('Blog\\Post', 'annotation', array())),
array(array(), "AcmeBlogBundle:Blog/Post\nyml\n\n", array('Blog\\Post', 'yml', array())),
array(array(), "AcmeBlogBundle:Blog/Post\nyml\ntitle\n\n255\ndescription\ntext\n\n", array('Blog\\Post', 'yml', array(
array('fieldName' => 'title', 'type' => 'string', 'length' => 255),
array('fieldName' => 'description', 'type' => 'text'),
))),
);
}
/**
* @dataProvider getNonInteractiveCommandData
*/
public function testNonInteractiveCommand($options, $expected)
{
list($entity, $format, $fields) = $expected;
$generator = $this->getGenerator();
$generator
->expects($this->once())
->method('generate')
->with($this->getBundle(), $entity, $format, $fields)
;
$generator
->expects($this->any())
->method('isReservedKeyword')
->will($this->returnValue(false))
;
$tester = new CommandTester($this->getCommand($generator, ''));
$tester->execute($options, array('interactive' => false));
}
public function getNonInteractiveCommandData()
{
return array(
array(array('--entity' => 'AcmeBlogBundle:Blog/Post'), array('Blog\\Post', 'annotation', array())),
array(array('--entity' => 'AcmeBlogBundle:Blog/Post', '--format' => 'yml', '--fields' => 'title:string(255) description:text'), array('Blog\\Post', 'yml', array(
array('fieldName' => 'title', 'type' => 'string', 'length' => 255),
array('fieldName' => 'description', 'type' => 'text', 'length' => ''),
))),
);
}
protected function getCommand($generator, $input)
{
$command = new GenerateDoctrineEntityCommand();
$command->setContainer($this->getContainer());
$command->setHelperSet($this->getHelperSet($input));
$command->setGenerator($generator);
return $command;
}
protected function getGenerator()
{
// get a noop generator
return $this
->getMockBuilder('Sensio\Bundle\GeneratorBundle\Generator\DoctrineEntityGenerator')
->disableOriginalConstructor()
->setMethods(array('generate', 'isReservedKeyword'))
->getMock()
;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\GeneratorBundle\Tests\Generator;
use Sensio\Bundle\GeneratorBundle\Generator\BundleGenerator;
class BundleGeneratorTest extends GeneratorTest
{
public function testGenerateYaml()
{
$generator = new BundleGenerator($this->filesystem, __DIR__.'/../../Resources/skeleton/bundle');
$generator->generate('Foo\BarBundle', 'FooBarBundle', $this->tmpDir, 'yml', false);
$files = array(
'FooBarBundle.php',
'Controller/DefaultController.php',
'Resources/views/Default/index.html.twig',
'Resources/config/routing.yml',
'Tests/Controller/DefaultControllerTest.php',
'Resources/config/services.yml',
'DependencyInjection/Configuration.php',
'DependencyInjection/FooBarExtension.php',
);
foreach ($files as $file) {
$this->assertTrue(file_exists($this->tmpDir.'/Foo/BarBundle/'.$file), sprintf('%s has been generated', $file));
}
$content = file_get_contents($this->tmpDir.'/Foo/BarBundle/FooBarBundle.php');
$this->assertContains('namespace Foo\\BarBundle', $content);
$content = file_get_contents($this->tmpDir.'/Foo/BarBundle/Controller/DefaultController.php');
$this->assertContains('public function indexAction', $content);
$this->assertNotContains('@Route("/hello/{name}"', $content);
$content = file_get_contents($this->tmpDir.'/Foo/BarBundle/Resources/views/Default/index.html.twig');
$this->assertContains('Hello {{ name }}!', $content);
}
public function testGenerateAnnotation()
{
$generator = new BundleGenerator($this->filesystem, __DIR__.'/../../Resources/skeleton/bundle');
$generator->generate('Foo\BarBundle', 'FooBarBundle', $this->tmpDir, 'annotation', false);
$this->assertFalse(file_exists($this->tmpDir.'/Foo/BarBundle/Resources/config/routing.yml'));
$this->assertFalse(file_exists($this->tmpDir.'/Foo/BarBundle/Resources/config/routing.xml'));
$content = file_get_contents($this->tmpDir.'/Foo/BarBundle/Controller/DefaultController.php');
$this->assertContains('@Route("/hello/{name}"', $content);
}
}

View File

@@ -0,0 +1,206 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\GeneratorBundle\Tests\Generator;
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineCrudGenerator;
class DoctrineCrudGeneratorTest extends GeneratorTest
{
public function testGenerateYamlFull()
{
$this->getGenerator()->generate($this->getBundle(), 'Post', $this->getMetadata(), 'yml', '/post', true);
$files = array(
'Controller/PostController.php',
'Tests/Controller/PostControllerTest.php',
'Resources/config/routing/post.yml',
'Resources/views/Post/index.html.twig',
'Resources/views/Post/show.html.twig',
'Resources/views/Post/new.html.twig',
'Resources/views/Post/edit.html.twig',
);
foreach ($files as $file) {
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
}
$files = array(
'Resources/config/routing/post.xml',
);
foreach ($files as $file) {
$this->assertFalse(file_exists($this->tmpDir.'/'.$file), sprintf('%s has not been generated', $file));
}
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
$strings = array(
'namespace Foo\BarBundle\Controller;',
'public function indexAction',
'public function showAction',
'public function newAction',
'public function editAction',
);
foreach ($strings as $string) {
$this->assertContains($string, $content);
}
}
public function testGenerateXml()
{
$this->getGenerator()->generate($this->getBundle(), 'Post', $this->getMetadata(), 'xml', '/post', false);
$files = array(
'Controller/PostController.php',
'Tests/Controller/PostControllerTest.php',
'Resources/config/routing/post.xml',
'Resources/views/Post/index.html.twig',
'Resources/views/Post/show.html.twig',
);
foreach ($files as $file) {
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
}
$files = array(
'Resources/config/routing/post.yml',
'Resources/views/Post/new.html.twig',
'Resources/views/Post/edit.html.twig',
);
foreach ($files as $file) {
$this->assertFalse(file_exists($this->tmpDir.'/'.$file), sprintf('%s has not been generated', $file));
}
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
$strings = array(
'namespace Foo\BarBundle\Controller;',
'public function indexAction',
'public function showAction',
);
foreach ($strings as $string) {
$this->assertContains($string, $content);
}
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
$strings = array(
'public function newAction',
'public function editAction',
'@Route',
);
foreach ($strings as $string) {
$this->assertNotContains($string, $content);
}
}
public function testGenerateAnnotationWrite()
{
$this->getGenerator()->generate($this->getBundle(), 'Post', $this->getMetadata(), 'annotation', '/post', true);
$files = array(
'Controller/PostController.php',
'Tests/Controller/PostControllerTest.php',
'Resources/views/Post/index.html.twig',
'Resources/views/Post/show.html.twig',
'Resources/views/Post/new.html.twig',
'Resources/views/Post/edit.html.twig',
);
foreach ($files as $file) {
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
}
$files = array(
'Resources/config/routing/post.yml',
'Resources/config/routing/post.xml',
);
foreach ($files as $file) {
$this->assertFalse(file_exists($this->tmpDir.'/'.$file), sprintf('%s has not been generated', $file));
}
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
$strings = array(
'namespace Foo\BarBundle\Controller;',
'public function indexAction',
'public function showAction',
'public function newAction',
'public function editAction',
'@Route',
);
foreach ($strings as $string) {
$this->assertContains($string, $content);
}
}
public function testGenerateAnnotation()
{
$this->getGenerator()->generate($this->getBundle(), 'Post', $this->getMetadata(), 'annotation', '/post', false);
$files = array(
'Controller/PostController.php',
'Tests/Controller/PostControllerTest.php',
'Resources/views/Post/index.html.twig',
'Resources/views/Post/show.html.twig',
);
foreach ($files as $file) {
$this->assertTrue(file_exists($this->tmpDir.'/'.$file), sprintf('%s has been generated', $file));
}
$files = array(
'Resources/config/routing/post.yml',
'Resources/config/routing/post.xml',
'Resources/views/Post/new.html.twig',
'Resources/views/Post/edit.html.twig',
);
foreach ($files as $file) {
$this->assertFalse(file_exists($this->tmpDir.'/'.$file), sprintf('%s has not been generated', $file));
}
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
$strings = array(
'namespace Foo\BarBundle\Controller;',
'public function indexAction',
'public function showAction',
'@Route',
);
foreach ($strings as $string) {
$this->assertContains($string, $content);
}
$content = file_get_contents($this->tmpDir.'/Controller/PostController.php');
$strings = array(
'public function newAction',
'public function editAction',
);
foreach ($strings as $string) {
$this->assertNotContains($string, $content);
}
}
protected function getGenerator()
{
return new DoctrineCrudGenerator($this->filesystem, __DIR__.'/../../Resources/skeleton/crud');
}
protected function getBundle()
{
$bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\BundleInterface');
$bundle->expects($this->any())->method('getPath')->will($this->returnValue($this->tmpDir));
$bundle->expects($this->any())->method('getName')->will($this->returnValue('FooBarBundle'));
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue('Foo\BarBundle'));
return $bundle;
}
public function getMetadata()
{
$metadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadataInfo')->disableOriginalConstructor()->getMock();
$metadata->identifier = array('id');
$metadata->fieldMappings = array('title' => array('type' => 'string'));
return $metadata;
}
}

View File

@@ -0,0 +1,40 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\GeneratorBundle\Tests\Generator;
use Sensio\Bundle\GeneratorBundle\Generator\DoctrineFormGenerator;
class DoctrineFormGeneratorTest extends GeneratorTest
{
public function testGenerate()
{
$generator = new DoctrineFormGenerator($this->filesystem, __DIR__.'/../../Resources/skeleton/form');
$bundle = $this->getMock('Symfony\Component\HttpKernel\Bundle\BundleInterface');
$bundle->expects($this->any())->method('getPath')->will($this->returnValue($this->tmpDir));
$bundle->expects($this->any())->method('getNamespace')->will($this->returnValue('Foo\BarBundle'));
$metadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadataInfo')->disableOriginalConstructor()->getMock();
$metadata->identifier = array('id');
$metadata->associationMappings = array('title' => array('type' => 'string'));
$generator->generate($bundle, 'Post', $metadata);
$this->assertTrue(file_exists($this->tmpDir.'/Form/PostType.php'));
$content = file_get_contents($this->tmpDir.'/Form/PostType.php');
$this->assertContains('->add(\'title\')', $content);
$this->assertContains('class PostType extends AbstractType', $content);
$this->assertContains("'data_class' => 'Foo\BarBundle\Entity\Post'", $content);
$this->assertContains("'foo_barbundle_posttype'", $content);
}
}

View File

@@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sensio\Bundle\GeneratorBundle\Tests\Generator;
use Symfony\Component\Filesystem\Filesystem;
abstract class GeneratorTest extends \PHPUnit_Framework_TestCase
{
protected $filesystem;
protected $tmpDir;
public function setUp()
{
$this->tmpDir = sys_get_temp_dir().'/sf2';
$this->filesystem = new Filesystem();
$this->filesystem->remove($this->tmpDir);
}
public function tearDown()
{
$this->filesystem->remove($this->tmpDir);
}
}

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="SensioGeneratorBundle">
<directory suffix="Test.php">./Tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Resources</directory>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View File

@@ -0,0 +1,6 @@
.DS_Store
tests/acceptance.conf.php
tests/smoke.conf.php
build/*
.project
.settings/*

100
vendor/swiftmailer/swiftmailer/CHANGES vendored Normal file
View File

@@ -0,0 +1,100 @@
Changelog since Version 4.x.x
=============================
4.2.2 (2012-XX-XX)
------------------
* n/a
4.2.1 (2012-07-13)
------------------
* changed the coding standards to PSR-1/2
* fixed issue with autoloading
* added NativeQpContentEncoder to enhance performance (for PHP 5.3+)
4.2.0 (2012-06-29)
------------------
* added documentation about how to use the Japanese support introduced in 4.1.8
* added a way to override the default configuration in a lazy way
* changed the PEAR init script to lazy-load the initialization
* fixed a bug when calling Swift_Preferences before anything else (regression introduced in 4.1.8)
4.1.8 (2012-06-17)
------------------
* added Japanese iso-2022-jp support
* changed the init script to lazy-load the initialization
* fixed docblocks (@id) which caused some problems with libraries parsing the dobclocks
* fixed Swift_Mime_Headers_IdentificationHeader::setId() when passed an array of ids
* fixed encoding of email addresses in headers
* added replacements setter to the Decorator plugin
4.1.7 (2012-04-26)
------------------
* fixed QpEncoder safeMapShareId property
4.1.6 (2012-03-23)
------------------
* reduced the size of serialized Messages
4.1.5 (2012-01-04)
------------------
* enforced Swift_Spool::queueMessage() to return a Boolean
* made an optimization to the memory spool: start the transport only when required
* prevented stream_socket_client() from generating an error and throw a Swift_TransportException instead
* fixed a PHP warning when calling to mail() when safe_mode is off
* many doc tweaks
4.1.4 (2011-12-16)
------------------
* added a memory spool (Swift_MemorySpool)
* fixed too many opened files when sending emails with attachments
4.1.3 (2011-10-27)
------------------
* added STARTTLS support
* added missing @return tags on fluent methods
* added a MessageLogger plugin that logs all sent messages
* added composer.json
4.1.2 (2011-09-13)
------------------
* fixed wrong detection of magic_quotes_runtime
* fixed fatal errors when no To or Subject header has been set
* fixed charset on parameter header continuations
* added documentation about how to install Swiftmailer from the PEAR channel
* fixed various typos and markup problem in the documentation
* fixed warning when cache directory does not exist
* fixed "slashes are escaped" bug
* changed require_once() to require() in autoload
4.1.1 (2011-07-04)
------------------
* added missing file in PEAR package
4.1.0 (2011-06-30)
------------------
* documentation has been converted to ReST
4.1.0 RC1 (2011-06-17)
----------------------
New features:
* changed the Decorator Plugin to allow replacements in all headers
* added Swift_Mime_Grammar and Swift_Validate to validate an email address
* modified the autoloader to lazy-initialize Swiftmailer
* removed Swift_Mailer::batchSend()
* added NullTransport
* added new plugins: RedirectingPlugin and ImpersonatePlugin
* added a way to send messages asynchronously (Spool)

16
vendor/swiftmailer/swiftmailer/README vendored Normal file
View File

@@ -0,0 +1,16 @@
Swift Mailer
------------
Swift Mailer is a component based mailing solution for PHP 5.
It is released under the LGPL license.
Homepage: http://swiftmailer.org
Documentation: http://swiftmailer.org/docs
Mailing List: http://groups.google.com/group/swiftmailer
Bugs: https://github.com/swiftmailer/swiftmailer/issues
Repository: https://github.com/swiftmailer/swiftmailer
Swift Mailer is highly object-oriented by design and lends itself
to use in complex web application with a great deal of flexibility.
For full details on usage, see the documentation.

View File

@@ -0,0 +1,67 @@
This README applies to anyone who checks out the source from git.
If you're reading this page on github.com, and you don't have git
installed or know about git, you can download this repository by
using the "download" button on github.com, right above the file
list.
PREAMBLE:
---------
The git repository is structured in the expected way where "master" is the
main branch you should use if you want to have bleeding-edge updates. Any
other branch should be ignored since it will likely contain unstable
and/or experimental developments.
Generally speaking you should feel safe using the "master" branch in
production code. Anything likely to break will be committed to another
branch. Only bugfixes and clean non-breaking feature additions will be
performed in master.
All releases (post version 4.0.0) are tagged using the version number of
that release. Earlier versions exist in a subversion repository at the
old sourceforge project page.
WHAT IS SWIFT MAILER?
---------------------
Swift Mailer is a component based mailing solution for PHP 5.
It is released under the LGPL license.
Homepage: http://swiftmailer.org/
Documentation: http://swiftmailer.org/docs
Mailing List: http://groups.google.com/group/swiftmailer
Bugs: https://github.com/swiftmailer/swiftmailer/issues
Repository: https://github.com/swiftmailer/swiftmailer
Swift Mailer is highly object-oriented by design and lends itself
to use in complex web application with a great deal of flexibility.
For full details on usage, see the documentation.
WHY SO MUCH CLUTTER?
--------------------
As you can probably see, there are a lot more files in here than you find in
the pre-packaged versions. That's because I store notes (UML, RFCs etc) in
the repository.
The main library files live in /lib and the tests live in /tests. You can run
the tests by pointing your web browser at /test-suite, or by running the
command "php test-suite/run.php". Some tests will be "skipped" if
tests/smoke.conf.php and tests/acceptance.conf.php are not editted. This is
harmless and normal.
If you want to create a bundled-up package from subversion you can do so if
you have Ant (http://ant.apache.org/) installed. Simply run "ant package"
from this directory and the tar.gz file will be created in the /build
directory.
Running the command "ant" with no arguments will bundle up the package without
compressing it into a tar.gz file.
Tests can also be run using "ant test" provided php is on your PATH
environment variable.
EoM

View File

@@ -1 +1 @@
Swift-4.2.1
Swift-4.2.2-DEV

112
vendor/swiftmailer/swiftmailer/build.xml vendored Normal file
View File

@@ -0,0 +1,112 @@
<!-- Ant build file for Swift Mailer (Standard Edition) -->
<project name="Swift Mailer SE" default="bundle">
<!-- Config settings -->
<property name="path" value="." />
<property name="builddir" value="${path}/build" />
<property name="src.versionfile" value="${path}/VERSION" />
<!-- Generate version info from VERSION file -->
<loadfile property="bundle.name" srcFile="${src.versionfile}">
<filterchain>
<striplinebreaks />
</filterchain>
</loadfile>
<!-- Generate version number -->
<loadfile property="bundle.version" srcFile="${src.versionfile}">
<filterchain>
<striplinebreaks />
<tokenfilter>
<replacestring from="Swift-" to=""/>
</tokenfilter>
</filterchain>
</loadfile>
<property name="src.readmefile" value="${path}/README" />
<property name="src.changesfile" value="${path}/CHANGES" />
<property name="src.libdir" value="${path}/lib" />
<property name="src.testsuite" value="${path}/test-suite" />
<property name="src.tests" value="${path}/tests" />
<property name="builddir.package" value="${builddir}/${bundle.name}" />
<property name="runtests" value="" />
<filelist id="src.licenses" dir="${path}">
<file name="LICENSE" />
</filelist>
<fileset id="build.simpletest.unneeded"
dir="${builddir.package}/test-suite/lib/simpletest">
<include name="docs/" />
<include name="tutorials/" />
<include name="extensions/" />
<include name="test/" />
<include name="packages/" />
</fileset>
<!-- Bundle all files into a central location -->
<target name="bundle" depends="prepare, clean, copy-classes">
<copy file="${src.versionfile}" todir="${builddir.package}" />
<copy file="${src.changesfile}" todir="${builddir.package}" />
<copy todir="${builddir.package}">
<filelist refid="src.licenses" />
</copy>
<copy file="${src.readmefile}" todir="${builddir.package}" />
<move file="${builddir.package}/tests/acceptance.conf.php.default"
tofile="${builddir.package}/tests/acceptance.conf.php" />
<move file="${builddir.package}/tests/smoke.conf.php.default"
tofile="${builddir.package}/tests/smoke.conf.php" />
</target>
<!-- Copy some *.default files to their required files if needed -->
<target name="prepare">
<copy file="${src.tests}/acceptance.conf.php.default"
tofile="${src.tests}/acceptance.conf.php" />
<copy file="${src.tests}/smoke.conf.php.default"
tofile="${src.tests}/smoke.conf.php" />
</target>
<!-- Clean out the build directory -->
<target name="clean">
<delete includeemptydirs="true">
<fileset dir="${builddir}" includes="**/*" />
</delete>
</target>
<!-- Copy all classes from the class path to the bundle -->
<target name="copy-classes">
<copy todir="${builddir.package}/lib">
<fileset dir="${src.libdir}" />
<filterchain>
<replacetokens>
<token key="SWIFT_VERSION_NUMBER" value="${bundle.version}"/>
</replacetokens>
</filterchain>
</copy>
<copy todir="${builddir.package}/test-suite">
<fileset dir="${src.testsuite}" />
</copy>
<copy todir="${builddir.package}/tests">
<fileset dir="${src.tests}" />
</copy>
<delete includeemptydirs="true">
<fileset refid="build.simpletest.unneeded" />
</delete>
</target>
<!-- Package up the project as a gzip file -->
<target name="package" depends="bundle">
<tar destfile="${builddir.package}.tar.gz" compression="gzip" longfile="gnu">
<fileset dir="${builddir}" />
</tar>
<delete includeemptydirs="true">
<fileset dir="${builddir.package}" includes="**" />
</delete>
</target>
<!-- Run the included unit tests -->
<target name="test" depends="prepare, clean, copy-classes">
<exec executable="php" failonerror="true">
<env key="_" value="php" />
<arg value="${builddir.package}/test-suite/run.php" />
<arg value="${runtests}" />
</exec>
</target>
</project>

View File

@@ -0,0 +1,42 @@
<?php
if (!isset($argv[1]))
{
die('You must provide the version (1.0.0)');
}
if (!isset($argv[2]))
{
die('You must provide the stability (alpha, beta, or stable)');
}
$context = array(
'date' => date('Y-m-d'),
'time' => date('H:m:00'),
'version' => $argv[1],
'api_version' => $argv[1],
'stability' => $argv[2],
'api_stability' => $argv[2],
);
$context['files'] = '';
$path = realpath(dirname(__FILE__).'/lib/classes/Swift');
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::LEAVES_ONLY) as $file)
{
if (preg_match('/\.php$/', $file))
{
$name = str_replace($path.'/', '', $file);
$context['files'] .= ' <file install-as="Swift/'.$name.'" name="'.$name.'" role="php" />'."\n";
}
}
$template = file_get_contents(dirname(__FILE__).'/package.xml.tpl');
$content = preg_replace_callback('/\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/', 'replace_parameters', $template);
file_put_contents(dirname(__FILE__).'/package.xml', $content);
function replace_parameters($matches)
{
global $context;
return isset($context[$matches[1]]) ? $context[$matches[1]] : null;
}

View File

@@ -20,7 +20,7 @@ class Swift_SmtpTransport extends Swift_Transport_EsmtpTransport
* Create a new SmtpTransport, optionally with $host, $port and $security.
* @param string $host
* @param int $port
* @param int $security
* @param string $security
*/
public function __construct($host = 'localhost', $port = 25, $security = null)
{
@@ -39,7 +39,7 @@ class Swift_SmtpTransport extends Swift_Transport_EsmtpTransport
* Create a new SmtpTransport instance.
* @param string $host
* @param int $port
* @param int $security
* @param string $security
* @return Swift_SmtpTransport
*/
public static function newInstance($host = 'localhost', $port = 25, $security = null)

View File

@@ -21,9 +21,11 @@ define('SWIFT_REQUIRED_LOADED', true);
//Load Swift utility class
require dirname(__FILE__) . '/classes/Swift.php';
function _swiftmailer_init()
{
require dirname(__FILE__) . '/swift_init.php';
if (!function_exists('_swiftmailer_init')) {
function _swiftmailer_init()
{
require dirname(__FILE__) . '/swift_init.php';
}
}
//Start the autoloader and lazy-load the init script to set up dependency injection

View File

@@ -21,9 +21,11 @@ define('SWIFT_REQUIRED_LOADED', true);
//Load Swift utility class
require dirname(__FILE__) . '/Swift.php';
function _swiftmailer_init()
{
require dirname(__FILE__) . '/swift_init.php';
if (!function_exists('_swiftmailer_init')) {
function _swiftmailer_init()
{
require dirname(__FILE__) . '/swift_init.php';
}
}
//Start the autoloader and lazy-load the init script to set up dependency injection

View File

@@ -0,0 +1,15 @@
Applications I need to test with
---------------------------------
Standalone (can read .eml files):
---------------------------------
Microsoft Entourage (can assume same as outlook)
Mozilla Thunderbird
Apple Mail
Web-based:
----------
Hotmail
Gmail
Yahoo!
Mail2Web

View File

@@ -0,0 +1,46 @@
Following is a list of character sets along with their widths:
--------------------------------------------------------------
1 Octet 8bit:
-------------
Windows 125* (CP125*)
CP*
ANSI
ISO-8859-* (IEC-8859-*)
Macintosh (Mac OS Roman)
KOI8-U (potentially KOI*8-*)
KOI8-R
MIK
Cork (T1)
ISCII
VISCII
1 Octet 7bit:
-------------
US-ASCII
K0I7
2 octets 16 bit:
----------------
UCS-2
UTF-16* (UTF-16BE etc)
4-octets 32 bit:
----------------
UCS-4
UTF-32
Variable-width:
----------------------------
Big5 - http://en.wikipedia.org/wiki/Big5 (1-2 bytes: 00-7f=1, 81-fe=2)
HKSCS - http://en.wikipedia.org/wiki/HKSCS (a big5 variant, but some variants use 10646)
ISO-10646 (IEC-10646) - http://en.wikipedia.org/wiki/ISO_10646 (unicode)
UTF-8 (1-5 bytes)
ISO-2022 (IEC-2022) - http://en.wikipedia.org/wiki/ISO_2022
Shift-JIS - http://en.wikipedia.org/wiki/Shift-JIS
A good resource:
----------------
http://en.wikipedia.org/wiki/Character_encoding#Simple_character_sets

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<message>
<subject>Some test message</subject>
<to name="Chris Corbyn">chris@w3style.co.uk</to>
<to name="Mark Corbyn">mark@swiftmailer.org</to>
<from>chris.corbyn@sitepoint.com</from>
<content-type>text/plain</content-type>
<body>
Here's a recipe for beef stifado
</body>
<part>
<content-type>text/html</content-type>
<body>
This is the other part
</body>
</part>
<attachment>
<content-type>application/pdf</content-type>
<filename>stifado.pdf</filename>
<body type="file">/path/to/stifado.pdf</body>
</attachment>
</message>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,395 @@
Network Working Group N. Freed
Request For Comments: 1854 Innosoft International, Inc.
Category: Standards Track A. Cargille, WG Chair
October 1995
SMTP Service Extension
for Command Pipelining
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Abstract
This memo defines an extension to the SMTP service whereby a server
can indicate the extent of its ability to accept multiple commands in
a single TCP send operation. Using a single TCP send operation for
multiple commands can improve SMTP performance significantly.
Introduction
Although SMTP is widely and robustly deployed, certain extensions may
nevertheless prove useful. In particular, many parts of the Internet
make use of high latency network links.
SMTP's intrinsic one command-one response structure is significantly
penalized by high latency links, often to the point where the factors
contributing to overall connection time are dominated by the time
spent waiting for responses to individual commands (turnaround time).
In the best of all worlds it would be possible to simply deploy SMTP
client software that makes use of command pipelining: batching up
multiple commands into single TCP send operations. Unfortunately, the
original SMTP specification [1] did not explicitly state that SMTP
servers must support this. As a result a non-trivial number of
Internet SMTP servers cannot adequately handle command pipelining.
Flaws known to exist in deployed servers include:
(1) Connection handoff and buffer flushes in the middle of
the SMTP dialogue. Creation of server processes for
incoming SMTP connections is a useful, obvious, and
harmless implementation technique. However, some SMTP
servers defer process forking and connection handoff
Freed & Cargille Standards Track [Page 1]
RFC 1854 SMTP Pipelining October 1995
until some intermediate point in the SMTP dialogue.
When this is done material read from the TCP connection
and kept in process buffers can be lost.
(2) Flushing the TCP input buffer when an SMTP command
fails. SMTP commands often fail but there is no reason
to flush the TCP input buffer when this happens.
Nevertheless, some SMTP servers do this.
(3) Improper processing and promulgation of SMTP command
failures. For example, some SMTP servers will refuse to
accept a DATA command if the last RCPT TO command
fails, paying no attention to the success or failure of
prior RCPT TO command results. Other servers will
accept a DATA command even when all previous RCPT TO
commands have failed. Although it is possible to
accommodate this sort of behavior in a client that
employs command pipelining, it does complicate the
construction of the client unnecessarily.
This memo uses the mechanism described in [2] to define an extension
to the SMTP service whereby an SMTP server can declare that it is
capable of handling pipelined commands. The SMTP client can then
check for this declaration and use pipelining only when the server
declares itself capable of handling it.
1. Framework for the Command Pipelining Extension
The Command Pipelining extension is defined as follows:
(1) the name of the SMTP service extension is Pipelining;
(2) the EHLO keyword value associated with the extension is
PIPELINING;
(3) no parameter is used with the PIPELINING EHLO keyword;
(4) no additional parameters are added to either the MAIL
FROM or RCPT TO commands.
(5) no additional SMTP verbs are defined by this extension;
and,
(6) the next section specifies how support for the
extension affects the behavior of a server and client
SMTP.
Freed & Cargille Standards Track [Page 2]
RFC 1854 SMTP Pipelining October 1995
2. The Pipelining Service Extension
When a client SMTP wishes to employ command pipelining, it first
issues the EHLO command to the server SMTP. If the server SMTP
responds with code 250 to the EHLO command, and the response includes
the EHLO keyword value PIPELINING, then the server SMTP has indicated
that it can accommodate SMTP command pipelining.
2.1. Client use of pipelining
Once the client SMTP has confirmed that support exists for the
pipelining extension, the client SMTP may then elect to transmit
groups of SMTP commands in batches without waiting for a response to
each individual command. In particular, the commands RSET, MAIL FROM,
SEND FROM, SOML FROM, SAML FROM, and RCPT TO can all appear anywhere
in a pipelined command group. The EHLO, DATA, VRFY, EXPN, TURN,
QUIT, and NOOP commands can only appear as the last command in a
group since their success or failure produces a change of state which
the client SMTP must accommodate. (NOOP is included in this group so
it can be used as a synchronization point.)
Additional commands added by other SMTP extensions may only appear as
the last command in a group unless otherwise specified by the
extensions that define the commands.
The actual transfer of message content is explicitly allowed to be
the first "command" in a group. That is, the RSET/MAIL FROM sequence
necessary to initiate a new message transaction can be placed in the
same group as the final transfer of the headers and body of the
previous message.
Client SMTP implementations that employ pipelining MUST check ALL
statuses associated with each command in a group. For example, if
none of the RCPT TO recipient addresses were accepted the client must
then check the response to the DATA command -- the client cannot
assume that the DATA command will be rejected just because none of
the RCPT TO commands worked. If the DATA command was properly
rejected the client SMTP can just issue RSET, but if the DATA command
was accepted the client SMTP should send a single dot.
Command statuses MUST be coordinated with responses by counting each
separate response and correlating that count with the number of
commands known to have been issued. Multiline responses MUST be
supported. Matching on the basis of either the error code value or
associated text is expressly forbidden.
Client SMTP implementations MAY elect to operate in a nonblocking
fashion, processing server responses immediately upon receipt, even
Freed & Cargille Standards Track [Page 3]
RFC 1854 SMTP Pipelining October 1995
if there is still data pending transmission from the client's
previous TCP send operation. If nonblocking operation is not
supported, however, client SMTP implementations MUST also check the
TCP window size and make sure that each group of commands fits
entirely within the window. The window size is usually, but not
always, 4K octets. Failure to perform this check can lead to
deadlock conditions.
Clients MUST NOT confuse responses to multiple commands with
multiline responses. Each command requires one or more lines of
response, the last line not containing a dash between the response
code and the response string.
2.2. Server support of pipelining
A server SMTP implementation that offers the pipelining extension:
(1) MUST NOT flush or otherwise lose the contents of the
TCP input buffer under any circumstances whatsoever.
(2) SHOULD issue a positive response to the DATA command if
and only if one or more valid RCPT TO addresses have
been previously received.
(3) MUST NOT, after issuing a positive response to a DATA
command with no valid recipients and subsequently
receiving an empty message, send any message whatsoever
to anybody.
(4) SHOULD elect to store responses to grouped RSET, MAIL
FROM, SEND FROM, SOML FROM, SAML FROM, and RCPT TO
commands in an internal buffer so they can sent as a
unit.
(5) MUST NOT buffer responses to EHLO, DATA, VRFY, EXPN,
TURN, QUIT, and NOOP.
(6) MUST NOT buffer responses to unrecognized commands.
(7) MUST send all pending responses immediately whenever
the local TCP input buffer is emptied.
(8) MUST NOT make assumptions about commands that are yet
to be received.
(9) SHOULD issue response text that indicates, either
implicitly or explicitly, what command the response
matches.
Freed & Cargille Standards Track [Page 4]
RFC 1854 SMTP Pipelining October 1995
The overriding intent of these server requirements is to make it as
easy as possible for servers to conform to these pipelining
extensions.
3. Examples
Consider the following SMTP dialogue that does not use pipelining:
S: <wait for open connection>
C: <open connection to server>
S: 220 innosoft.com SMTP service ready
C: HELO dbc.mtview.ca.us
S: 250 innosoft.com
C: MAIL FROM:<mrose@dbc.mtview.ca.us>
S: 250 sender <mrose@dbc.mtview.ca.us> OK
C: RCPT TO:<ned@innosoft.com>
S: 250 recipient <ned@innosoft.com> OK
C: RCPT TO:<dan@innosoft.com>
S: 250 recipient <dan@innosoft.com> OK
C: RCPT TO:<kvc@innosoft.com>
S: 250 recipient <kvc@innosoft.com> OK
C: DATA
S: 354 enter mail, end with line containing only "."
...
C: .
S: 250 message sent
C: QUIT
S: 221 goodbye
The client waits for a server response a total of 9 times in this
simple example. But if pipelining is employed the following dialogue
is possible:
S: <wait for open connection>
C: <open connection to server>
S: 220 innosoft.com SMTP service ready
C: EHLO dbc.mtview.ca.us
S: 250-innosoft.com
S: 250 PIPELINING
C: MAIL FROM:<mrose@dbc.mtview.ca.us>
C: RCPT TO:<ned@innosoft.com>
C: RCPT TO:<dan@innosoft.com>
C: RCPT TO:<kvc@innosoft.com>
C: DATA
S: 250 sender <mrose@dbc.mtview.ca.us> OK
S: 250 recipient <ned@innosoft.com> OK
S: 250 recipient <dan@innosoft.com> OK
S: 250 recipient <kvc@innosoft.com> OK
Freed & Cargille Standards Track [Page 5]
RFC 1854 SMTP Pipelining October 1995
S: 354 enter mail, end with line containing only "."
...
C: .
C: QUIT
S: 250 message sent
S: 221 goodbye
The total number of turnarounds has been reduced from 9 to 4.
The next example illustrates one possible form of behavior when
pipelining is used and all recipients are rejected:
S: <wait for open connection>
C: <open connection to server>
S: 220 innosoft.com SMTP service ready
C: EHLO dbc.mtview.ca.us
S: 250-innosoft.com
S: 250 PIPELINING
C: MAIL FROM:<mrose@dbc.mtview.ca.us>
C: RCPT TO:<nsb@thumper.bellcore.com>
C: RCPT TO:<galvin@tis.com>
C: DATA
S: 250 sender <mrose@dbc.mtview.ca.us> OK
S: 550 remote mail to <nsb@thumper.bellore.com> not allowed
S: 550 remote mail to <galvin@tis.com> not allowed
S: 554 no valid recipients given
C: QUIT
S: 221 goodbye
The client SMTP waits for the server 4 times here as well. If the
server SMTP does not check for at least one valid recipient prior to
accepting the DATA command, the following dialogue would result:
S: <wait for open connection>
C: <open connection to server>
S: 220 innosoft.com SMTP service ready
C: EHLO dbc.mtview.ca.us
S: 250-innosoft.com
S: 250 PIPELINING
C: MAIL FROM:<mrose@dbc.mtview.ca.us>
C: RCPT TO:<nsb@thumper.bellcore.com>
C: RCPT TO:<galvin@tis.com>
C: DATA
S: 250 sender <mrose@dbc.mtview.ca.us> OK
S: 550 remote mail to <nsb@thumper.bellore.com> not allowed
S: 550 remote mail to <galvin@tis.com> not allowed
S: 354 enter mail, end with line containing only "."
C: .
Freed & Cargille Standards Track [Page 6]
RFC 1854 SMTP Pipelining October 1995
C: QUIT
S: 554 no valid recipients
S: 221 goodbye
4. Security Considerations
This RFC does not discuss security issues and is not believed to
raise any security issues not endemic in electronic mail and present
in fully conforming implementations of [1].
5. Acknowledgements
This document is based on the SMTP service extension model presented
in RFC 1425. Marshall Rose's description of SMTP command pipelining
in his book "The Internet Message" also served as a source of
inspiration for this extension.
6. References
[1] Postel, J., "Simple Mail Transfer Protocol", STD 10
RFC 821, USC/Information Sciences Institute, August
1982.
[2] Klensin, J., Freed, N., Rose, M., Stefferud, E.,
and D. Crocker, "SMTP Service Extensions", RFC 1651,
MCI, Innosoft, Dover Beach Consulting, Inc.,
Network Management Associates, Inc., Silicon Graphics,
Inc., July 1994.
7. Author's Address
Ned Freed
Innosoft International, Inc.
1050 East Garvey Avenue South
West Covina, CA 91790
USA
Phone: +1 818 919 3600
Fax: +1 818 919 3614
EMail: ned@innosoft.com
Freed & Cargille Standards Track [Page 7]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,843 @@
Network Working Group K. Moore
Request for Comments: 2047 University of Tennessee
Obsoletes: 1521, 1522, 1590 November 1996
Category: Standards Track
MIME (Multipurpose Internet Mail Extensions) Part Three:
Message Header Extensions for Non-ASCII Text
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Abstract
STD 11, RFC 822, defines a message representation protocol specifying
considerable detail about US-ASCII message headers, and leaves the
message content, or message body, as flat US-ASCII text. This set of
documents, collectively called the Multipurpose Internet Mail
Extensions, or MIME, redefines the format of messages to allow for
(1) textual message bodies in character sets other than US-ASCII,
(2) an extensible set of different formats for non-textual message
bodies,
(3) multi-part message bodies, and
(4) textual header information in character sets other than US-ASCII.
These documents are based on earlier work documented in RFC 934, STD
11, and RFC 1049, but extends and revises them. Because RFC 822 said
so little about message bodies, these documents are largely
orthogonal to (rather than a revision of) RFC 822.
This particular document is the third document in the series. It
describes extensions to RFC 822 to allow non-US-ASCII text data in
Internet mail header fields.
Moore Standards Track [Page 1]
RFC 2047 Message Header Extensions November 1996
Other documents in this series include:
+ RFC 2045, which specifies the various headers used to describe
the structure of MIME messages.
+ RFC 2046, which defines the general structure of the MIME media
typing system and defines an initial set of media types,
+ RFC 2048, which specifies various IANA registration procedures
for MIME-related facilities, and
+ RFC 2049, which describes MIME conformance criteria and
provides some illustrative examples of MIME message formats,
acknowledgements, and the bibliography.
These documents are revisions of RFCs 1521, 1522, and 1590, which
themselves were revisions of RFCs 1341 and 1342. An appendix in RFC
2049 describes differences and changes from previous versions.
1. Introduction
RFC 2045 describes a mechanism for denoting textual body parts which
are coded in various character sets, as well as methods for encoding
such body parts as sequences of printable US-ASCII characters. This
memo describes similar techniques to allow the encoding of non-ASCII
text in various portions of a RFC 822 [2] message header, in a manner
which is unlikely to confuse existing message handling software.
Like the encoding techniques described in RFC 2045, the techniques
outlined here were designed to allow the use of non-ASCII characters
in message headers in a way which is unlikely to be disturbed by the
quirks of existing Internet mail handling programs. In particular,
some mail relaying programs are known to (a) delete some message
header fields while retaining others, (b) rearrange the order of
addresses in To or Cc fields, (c) rearrange the (vertical) order of
header fields, and/or (d) "wrap" message headers at different places
than those in the original message. In addition, some mail reading
programs are known to have difficulty correctly parsing message
headers which, while legal according to RFC 822, make use of
backslash-quoting to "hide" special characters such as "<", ",", or
":", or which exploit other infrequently-used features of that
specification.
While it is unfortunate that these programs do not correctly
interpret RFC 822 headers, to "break" these programs would cause
severe operational problems for the Internet mail system. The
extensions described in this memo therefore do not rely on little-
used features of RFC 822.
Moore Standards Track [Page 2]
RFC 2047 Message Header Extensions November 1996
Instead, certain sequences of "ordinary" printable ASCII characters
(known as "encoded-words") are reserved for use as encoded data. The
syntax of encoded-words is such that they are unlikely to
"accidentally" appear as normal text in message headers.
Furthermore, the characters used in encoded-words are restricted to
those which do not have special meanings in the context in which the
encoded-word appears.
Generally, an "encoded-word" is a sequence of printable ASCII
characters that begins with "=?", ends with "?=", and has two "?"s in
between. It specifies a character set and an encoding method, and
also includes the original text encoded as graphic ASCII characters,
according to the rules for that encoding method.
A mail composer that implements this specification will provide a
means of inputting non-ASCII text in header fields, but will
translate these fields (or appropriate portions of these fields) into
encoded-words before inserting them into the message header.
A mail reader that implements this specification will recognize
encoded-words when they appear in certain portions of the message
header. Instead of displaying the encoded-word "as is", it will
reverse the encoding and display the original text in the designated
character set.
NOTES
This memo relies heavily on notation and terms defined RFC 822 and
RFC 2045. In particular, the syntax for the ABNF used in this memo
is defined in RFC 822, as well as many of the terminal or nonterminal
symbols from RFC 822 are used in the grammar for the header
extensions defined here. Among the symbols defined in RFC 822 and
referenced in this memo are: 'addr-spec', 'atom', 'CHAR', 'comment',
'CTLs', 'ctext', 'linear-white-space', 'phrase', 'quoted-pair'.
'quoted-string', 'SPACE', and 'word'. Successful implementation of
this protocol extension requires careful attention to the RFC 822
definitions of these terms.
When the term "ASCII" appears in this memo, it refers to the "7-Bit
American Standard Code for Information Interchange", ANSI X3.4-1986.
The MIME charset name for this character set is "US-ASCII". When not
specifically referring to the MIME charset name, this document uses
the term "ASCII", both for brevity and for consistency with RFC 822.
However, implementors are warned that the character set name must be
spelled "US-ASCII" in MIME message and body part headers.
Moore Standards Track [Page 3]
RFC 2047 Message Header Extensions November 1996
This memo specifies a protocol for the representation of non-ASCII
text in message headers. It specifically DOES NOT define any
translation between "8-bit headers" and pure ASCII headers, nor is
any such translation assumed to be possible.
2. Syntax of encoded-words
An 'encoded-word' is defined by the following ABNF grammar. The
notation of RFC 822 is used, with the exception that white space
characters MUST NOT appear between components of an 'encoded-word'.
encoded-word = "=?" charset "?" encoding "?" encoded-text "?="
charset = token ; see section 3
encoding = token ; see section 4
token = 1*<Any CHAR except SPACE, CTLs, and especials>
especials = "(" / ")" / "<" / ">" / "@" / "," / ";" / ":" / "
<"> / "/" / "[" / "]" / "?" / "." / "="
encoded-text = 1*<Any printable ASCII character other than "?"
or SPACE>
; (but see "Use of encoded-words in message
; headers", section 5)
Both 'encoding' and 'charset' names are case-independent. Thus the
charset name "ISO-8859-1" is equivalent to "iso-8859-1", and the
encoding named "Q" may be spelled either "Q" or "q".
An 'encoded-word' may not be more than 75 characters long, including
'charset', 'encoding', 'encoded-text', and delimiters. If it is
desirable to encode more text than will fit in an 'encoded-word' of
75 characters, multiple 'encoded-word's (separated by CRLF SPACE) may
be used.
While there is no limit to the length of a multiple-line header
field, each line of a header field that contains one or more
'encoded-word's is limited to 76 characters.
The length restrictions are included both to ease interoperability
through internetwork mail gateways, and to impose a limit on the
amount of lookahead a header parser must employ (while looking for a
final ?= delimiter) before it can decide whether a token is an
"encoded-word" or something else.
Moore Standards Track [Page 4]
RFC 2047 Message Header Extensions November 1996
IMPORTANT: 'encoded-word's are designed to be recognized as 'atom's
by an RFC 822 parser. As a consequence, unencoded white space
characters (such as SPACE and HTAB) are FORBIDDEN within an
'encoded-word'. For example, the character sequence
=?iso-8859-1?q?this is some text?=
would be parsed as four 'atom's, rather than as a single 'atom' (by
an RFC 822 parser) or 'encoded-word' (by a parser which understands
'encoded-words'). The correct way to encode the string "this is some
text" is to encode the SPACE characters as well, e.g.
=?iso-8859-1?q?this=20is=20some=20text?=
The characters which may appear in 'encoded-text' are further
restricted by the rules in section 5.
3. Character sets
The 'charset' portion of an 'encoded-word' specifies the character
set associated with the unencoded text. A 'charset' can be any of
the character set names allowed in an MIME "charset" parameter of a
"text/plain" body part, or any character set name registered with
IANA for use with the MIME text/plain content-type.
Some character sets use code-switching techniques to switch between
"ASCII mode" and other modes. If unencoded text in an 'encoded-word'
contains a sequence which causes the charset interpreter to switch
out of ASCII mode, it MUST contain additional control codes such that
ASCII mode is again selected at the end of the 'encoded-word'. (This
rule applies separately to each 'encoded-word', including adjacent
'encoded-word's within a single header field.)
When there is a possibility of using more than one character set to
represent the text in an 'encoded-word', and in the absence of
private agreements between sender and recipients of a message, it is
recommended that members of the ISO-8859-* series be used in
preference to other character sets.
4. Encodings
Initially, the legal values for "encoding" are "Q" and "B". These
encodings are described below. The "Q" encoding is recommended for
use when most of the characters to be encoded are in the ASCII
character set; otherwise, the "B" encoding should be used.
Nevertheless, a mail reader which claims to recognize 'encoded-word's
MUST be able to accept either encoding for any character set which it
supports.
Moore Standards Track [Page 5]
RFC 2047 Message Header Extensions November 1996
Only a subset of the printable ASCII characters may be used in
'encoded-text'. Space and tab characters are not allowed, so that
the beginning and end of an 'encoded-word' are obvious. The "?"
character is used within an 'encoded-word' to separate the various
portions of the 'encoded-word' from one another, and thus cannot
appear in the 'encoded-text' portion. Other characters are also
illegal in certain contexts. For example, an 'encoded-word' in a
'phrase' preceding an address in a From header field may not contain
any of the "specials" defined in RFC 822. Finally, certain other
characters are disallowed in some contexts, to ensure reliability for
messages that pass through internetwork mail gateways.
The "B" encoding automatically meets these requirements. The "Q"
encoding allows a wide range of printable characters to be used in
non-critical locations in the message header (e.g., Subject), with
fewer characters available for use in other locations.
4.1. The "B" encoding
The "B" encoding is identical to the "BASE64" encoding defined by RFC
2045.
4.2. The "Q" encoding
The "Q" encoding is similar to the "Quoted-Printable" content-
transfer-encoding defined in RFC 2045. It is designed to allow text
containing mostly ASCII characters to be decipherable on an ASCII
terminal without decoding.
(1) Any 8-bit value may be represented by a "=" followed by two
hexadecimal digits. For example, if the character set in use
were ISO-8859-1, the "=" character would thus be encoded as
"=3D", and a SPACE by "=20". (Upper case should be used for
hexadecimal digits "A" through "F".)
(2) The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be
represented as "_" (underscore, ASCII 95.). (This character may
not pass through some internetwork mail gateways, but its use
will greatly enhance readability of "Q" encoded data with mail
readers that do not support this encoding.) Note that the "_"
always represents hexadecimal 20, even if the SPACE character
occupies a different code position in the character set in use.
(3) 8-bit values which correspond to printable ASCII characters other
than "=", "?", and "_" (underscore), MAY be represented as those
characters. (But see section 5 for restrictions.) In
particular, SPACE and TAB MUST NOT be represented as themselves
within encoded words.
Moore Standards Track [Page 6]
RFC 2047 Message Header Extensions November 1996
5. Use of encoded-words in message headers
An 'encoded-word' may appear in a message header or body part header
according to the following rules:
(1) An 'encoded-word' may replace a 'text' token (as defined by RFC 822)
in any Subject or Comments header field, any extension message
header field, or any MIME body part field for which the field body
is defined as '*text'. An 'encoded-word' may also appear in any
user-defined ("X-") message or body part header field.
Ordinary ASCII text and 'encoded-word's may appear together in the
same header field. However, an 'encoded-word' that appears in a
header field defined as '*text' MUST be separated from any adjacent
'encoded-word' or 'text' by 'linear-white-space'.
(2) An 'encoded-word' may appear within a 'comment' delimited by "(" and
")", i.e., wherever a 'ctext' is allowed. More precisely, the RFC
822 ABNF definition for 'comment' is amended as follows:
comment = "(" *(ctext / quoted-pair / comment / encoded-word) ")"
A "Q"-encoded 'encoded-word' which appears in a 'comment' MUST NOT
contain the characters "(", ")" or "
'encoded-word' that appears in a 'comment' MUST be separated from
any adjacent 'encoded-word' or 'ctext' by 'linear-white-space'.
It is important to note that 'comment's are only recognized inside
"structured" field bodies. In fields whose bodies are defined as
'*text', "(" and ")" are treated as ordinary characters rather than
comment delimiters, and rule (1) of this section applies. (See RFC
822, sections 3.1.2 and 3.1.3)
(3) As a replacement for a 'word' entity within a 'phrase', for example,
one that precedes an address in a From, To, or Cc header. The ABNF
definition for 'phrase' from RFC 822 thus becomes:
phrase = 1*( encoded-word / word )
In this case the set of characters that may be used in a "Q"-encoded
'encoded-word' is restricted to: <upper and lower case ASCII
letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
(underscore, ASCII 95.)>. An 'encoded-word' that appears within a
'phrase' MUST be separated from any adjacent 'word', 'text' or
'special' by 'linear-white-space'.
Moore Standards Track [Page 7]
RFC 2047 Message Header Extensions November 1996
These are the ONLY locations where an 'encoded-word' may appear. In
particular:
+ An 'encoded-word' MUST NOT appear in any portion of an 'addr-spec'.
+ An 'encoded-word' MUST NOT appear within a 'quoted-string'.
+ An 'encoded-word' MUST NOT be used in a Received header field.
+ An 'encoded-word' MUST NOT be used in parameter of a MIME
Content-Type or Content-Disposition field, or in any structured
field body except within a 'comment' or 'phrase'.
The 'encoded-text' in an 'encoded-word' must be self-contained;
'encoded-text' MUST NOT be continued from one 'encoded-word' to
another. This implies that the 'encoded-text' portion of a "B"
'encoded-word' will be a multiple of 4 characters long; for a "Q"
'encoded-word', any "=" character that appears in the 'encoded-text'
portion will be followed by two hexadecimal characters.
Each 'encoded-word' MUST encode an integral number of octets. The
'encoded-text' in each 'encoded-word' must be well-formed according
to the encoding specified; the 'encoded-text' may not be continued in
the next 'encoded-word'. (For example, "=?charset?Q?=?=
=?charset?Q?AB?=" would be illegal, because the two hex digits "AB"
must follow the "=" in the same 'encoded-word'.)
Each 'encoded-word' MUST represent an integral number of characters.
A multi-octet character may not be split across adjacent 'encoded-
word's.
Only printable and white space character data should be encoded using
this scheme. However, since these encoding schemes allow the
encoding of arbitrary octet values, mail readers that implement this
decoding should also ensure that display of the decoded data on the
recipient's terminal will not cause unwanted side-effects.
Use of these methods to encode non-textual data (e.g., pictures or
sounds) is not defined by this memo. Use of 'encoded-word's to
represent strings of purely ASCII characters is allowed, but
discouraged. In rare cases it may be necessary to encode ordinary
text that looks like an 'encoded-word'.
Moore Standards Track [Page 8]
RFC 2047 Message Header Extensions November 1996
6. Support of 'encoded-word's by mail readers
6.1. Recognition of 'encoded-word's in message headers
A mail reader must parse the message and body part headers according
to the rules in RFC 822 to correctly recognize 'encoded-word's.
'encoded-word's are to be recognized as follows:
(1) Any message or body part header field defined as '*text', or any
user-defined header field, should be parsed as follows: Beginning
at the start of the field-body and immediately following each
occurrence of 'linear-white-space', each sequence of up to 75
printable characters (not containing any 'linear-white-space')
should be examined to see if it is an 'encoded-word' according to
the syntax rules in section 2. Any other sequence of printable
characters should be treated as ordinary ASCII text.
(2) Any header field not defined as '*text' should be parsed
according to the syntax rules for that header field. However,
any 'word' that appears within a 'phrase' should be treated as an
'encoded-word' if it meets the syntax rules in section 2.
Otherwise it should be treated as an ordinary 'word'.
(3) Within a 'comment', any sequence of up to 75 printable characters
(not containing 'linear-white-space'), that meets the syntax
rules in section 2, should be treated as an 'encoded-word'.
Otherwise it should be treated as normal comment text.
(4) A MIME-Version header field is NOT required to be present for
'encoded-word's to be interpreted according to this
specification. One reason for this is that the mail reader is
not expected to parse the entire message header before displaying
lines that may contain 'encoded-word's.
6.2. Display of 'encoded-word's
Any 'encoded-word's so recognized are decoded, and if possible, the
resulting unencoded text is displayed in the original character set.
NOTE: Decoding and display of encoded-words occurs *after* a
structured field body is parsed into tokens. It is therefore
possible to hide 'special' characters in encoded-words which, when
displayed, will be indistinguishable from 'special' characters in the
surrounding text. For this and other reasons, it is NOT generally
possible to translate a message header containing 'encoded-word's to
an unencoded form which can be parsed by an RFC 822 mail reader.
Moore Standards Track [Page 9]
RFC 2047 Message Header Extensions November 1996
When displaying a particular header field that contains multiple
'encoded-word's, any 'linear-white-space' that separates a pair of
adjacent 'encoded-word's is ignored. (This is to allow the use of
multiple 'encoded-word's to represent long strings of unencoded text,
without having to separate 'encoded-word's where spaces occur in the
unencoded text.)
In the event other encodings are defined in the future, and the mail
reader does not support the encoding used, it may either (a) display
the 'encoded-word' as ordinary text, or (b) substitute an appropriate
message indicating that the text could not be decoded.
If the mail reader does not support the character set used, it may
(a) display the 'encoded-word' as ordinary text (i.e., as it appears
in the header), (b) make a "best effort" to display using such
characters as are available, or (c) substitute an appropriate message
indicating that the decoded text could not be displayed.
If the character set being used employs code-switching techniques,
display of the encoded text implicitly begins in "ASCII mode". In
addition, the mail reader must ensure that the output device is once
again in "ASCII mode" after the 'encoded-word' is displayed.
6.3. Mail reader handling of incorrectly formed 'encoded-word's
It is possible that an 'encoded-word' that is legal according to the
syntax defined in section 2, is incorrectly formed according to the
rules for the encoding being used. For example:
(1) An 'encoded-word' which contains characters which are not legal
for a particular encoding (for example, a "-" in the "B"
encoding, or a SPACE or HTAB in either the "B" or "Q" encoding),
is incorrectly formed.
(2) Any 'encoded-word' which encodes a non-integral number of
characters or octets is incorrectly formed.
A mail reader need not attempt to display the text associated with an
'encoded-word' that is incorrectly formed. However, a mail reader
MUST NOT prevent the display or handling of a message because an
'encoded-word' is incorrectly formed.
7. Conformance
A mail composing program claiming compliance with this specification
MUST ensure that any string of non-white-space printable ASCII
characters within a '*text' or '*ctext' that begins with "=?" and
ends with "?=" be a valid 'encoded-word'. ("begins" means: at the
Moore Standards Track [Page 10]
RFC 2047 Message Header Extensions November 1996
start of the field-body, immediately following 'linear-white-space',
or immediately following a "(" for an 'encoded-word' within '*ctext';
"ends" means: at the end of the field-body, immediately preceding
'linear-white-space', or immediately preceding a ")" for an
'encoded-word' within '*ctext'.) In addition, any 'word' within a
'phrase' that begins with "=?" and ends with "?=" must be a valid
'encoded-word'.
A mail reading program claiming compliance with this specification
must be able to distinguish 'encoded-word's from 'text', 'ctext', or
'word's, according to the rules in section 6, anytime they appear in
appropriate places in message headers. It must support both the "B"
and "Q" encodings for any character set which it supports. The
program must be able to display the unencoded text if the character
set is "US-ASCII". For the ISO-8859-* character sets, the mail
reading program must at least be able to display the characters which
are also in the ASCII set.
8. Examples
The following are examples of message headers containing 'encoded-
word's:
From: =?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>
To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>
CC: =?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>
Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=
Note: In the first 'encoded-word' of the Subject field above, the
last "=" at the end of the 'encoded-text' is necessary because each
'encoded-word' must be self-contained (the "=" character completes a
group of 4 base64 characters representing 2 octets). An additional
octet could have been encoded in the first 'encoded-word' (so that
the encoded-word would contain an exact multiple of 3 encoded
octets), except that the second 'encoded-word' uses a different
'charset' than the first one.
From: =?ISO-8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se>
To: ietf-822@dimacs.rutgers.edu, ojarnef@admin.kth.se
Subject: Time for ISO 10646?
To: Dave Crocker <dcrocker@mordor.stanford.edu>
Cc: ietf-822@dimacs.rutgers.edu, paf@comsol.se
From: =?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@nada.kth.se>
Subject: Re: RFC-HDR care and feeding
Moore Standards Track [Page 11]
RFC 2047 Message Header Extensions November 1996
From: Nathaniel Borenstein <nsb@thumper.bellcore.com>
(=?iso-8859-8?b?7eXs+SDv4SDp7Oj08A==?=)
To: Greg Vaudreuil <gvaudre@NRI.Reston.VA.US>, Ned Freed
<ned@innosoft.com>, Keith Moore <moore@cs.utk.edu>
Subject: Test of new header generator
MIME-Version: 1.0
Content-type: text/plain; charset=ISO-8859-1
The following examples illustrate how text containing 'encoded-word's
which appear in a structured field body. The rules are slightly
different for fields defined as '*text' because "(" and ")" are not
recognized as 'comment' delimiters. [Section 5, paragraph (1)].
In each of the following examples, if the same sequence were to occur
in a '*text' field, the "displayed as" form would NOT be treated as
encoded words, but be identical to the "encoded form". This is
because each of the encoded-words in the following examples is
adjacent to a "(" or ")" character.
encoded form displayed as
---------------------------------------------------------------------
(=?ISO-8859-1?Q?a?=) (a)
(=?ISO-8859-1?Q?a?= b) (a b)
Within a 'comment', white space MUST appear between an
'encoded-word' and surrounding text. [Section 5,
paragraph (2)]. However, white space is not needed between
the initial "(" that begins the 'comment', and the
'encoded-word'.
(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=) (ab)
White space between adjacent 'encoded-word's is not
displayed.
(=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=) (ab)
Even multiple SPACEs between 'encoded-word's are ignored
for the purpose of display.
(=?ISO-8859-1?Q?a?= (ab)
=?ISO-8859-1?Q?b?=)
Any amount of linear-space-white between 'encoded-word's,
even if it includes a CRLF followed by one or more SPACEs,
is ignored for the purposes of display.
Moore Standards Track [Page 12]
RFC 2047 Message Header Extensions November 1996
(=?ISO-8859-1?Q?a_b?=) (a b)
In order to cause a SPACE to be displayed within a portion
of encoded text, the SPACE MUST be encoded as part of the
'encoded-word'.
(=?ISO-8859-1?Q?a?= =?ISO-8859-2?Q?_b?=) (a b)
In order to cause a SPACE to be displayed between two strings
of encoded text, the SPACE MAY be encoded as part of one of
the 'encoded-word's.
9. References
[RFC 822] Crocker, D., "Standard for the Format of ARPA Internet Text
Messages", STD 11, RFC 822, UDEL, August 1982.
[RFC 2049] Borenstein, N., and N. Freed, "Multipurpose Internet Mail
Extensions (MIME) Part Five: Conformance Criteria and Examples",
RFC 2049, November 1996.
[RFC 2045] Borenstein, N., and N. Freed, "Multipurpose Internet Mail
Extensions (MIME) Part One: Format of Internet Message Bodies",
RFC 2045, November 1996.
[RFC 2046] Borenstein N., and N. Freed, "Multipurpose Internet Mail
Extensions (MIME) Part Two: Media Types", RFC 2046,
November 1996.
[RFC 2048] Freed, N., Klensin, J., and J. Postel, "Multipurpose
Internet Mail Extensions (MIME) Part Four: Registration
Procedures", RFC 2048, November 1996.
Moore Standards Track [Page 13]
RFC 2047 Message Header Extensions November 1996
10. Security Considerations
Security issues are not discussed in this memo.
11. Acknowledgements
The author wishes to thank Nathaniel Borenstein, Issac Chan, Lutz
Donnerhacke, Paul Eggert, Ned Freed, Andreas M. Kirchwitz, Olle
Jarnefors, Mike Rosin, Yutaka Sato, Bart Schaefer, and Kazuhiko
Yamamoto, for their helpful advice, insightful comments, and
illuminating questions in response to earlier versions of this
specification.
12. Author's Address
Keith Moore
University of Tennessee
107 Ayres Hall
Knoxville TN 37996-1301
EMail: moore@cs.utk.edu
Moore Standards Track [Page 14]
RFC 2047 Message Header Extensions November 1996
Appendix - changes since RFC 1522 (in no particular order)
+ explicitly state that the MIME-Version is not requried to use
'encoded-word's.
+ add explicit note that SPACEs and TABs are not allowed within
'encoded-word's, explaining that an 'encoded-word' must look like an
'atom' to an RFC822 parser.values, to be precise).
+ add examples from Olle Jarnefors (thanks!) which illustrate how
encoded-words with adjacent linear-white-space are displayed.
+ explicitly list terms defined in RFC822 and referenced in this memo
+ fix transcription typos that caused one or two lines and a couple of
characters to disappear in the resulting text, due to nroff quirks.
+ clarify that encoded-words are allowed in '*text' fields in both
RFC822 headers and MIME body part headers, but NOT as parameter
values.
+ clarify the requirement to switch back to ASCII within the encoded
portion of an 'encoded-word', for any charset that uses code switching
sequences.
+ add a note about 'encoded-word's being delimited by "(" and ")"
within a comment, but not in a *text (how bizarre!).
+ fix the Andre Pirard example to get rid of the trailing "_" after
the =E9. (no longer needed post-1342).
+ clarification: an 'encoded-word' may appear immediately following
the initial "(" or immediately before the final ")" that delimits a
comment, not just adjacent to "(" and ")" *within* *ctext.
+ add a note to explain that a "B" 'encoded-word' will always have a
multiple of 4 characters in the 'encoded-text' portion.
+ add note about the "=" in the examples
+ note that processing of 'encoded-word's occurs *after* parsing, and
some of the implications thereof.
+ explicitly state that you can't expect to translate between
1522 and either vanilla 822 or so-called "8-bit headers".
+ explicitly state that 'encoded-word's are not valid within a
'quoted-string'.
Moore Standards Track [Page 15]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,675 @@
Network Working Group R. Troost
Request for Comments: 2183 New Century Systems
Updates: 1806 S. Dorner
Category: Standards Track QUALCOMM Incorporated
K. Moore, Editor
University of Tennessee
August 1997
Communicating Presentation Information in
Internet Messages:
The Content-Disposition Header Field
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Abstract
This memo provides a mechanism whereby messages conforming to the
MIME specifications [RFC 2045, RFC 2046, RFC 2047, RFC 2048, RFC
2049] can convey presentational information. It specifies the
"Content-Disposition" header field, which is optional and valid for
any MIME entity ("message" or "body part"). Two values for this
header field are described in this memo; one for the ordinary linear
presentation of the body part, and another to facilitate the use of
mail to transfer files. It is expected that more values will be
defined in the future, and procedures are defined for extending this
set of values.
This document is intended as an extension to MIME. As such, the
reader is assumed to be familiar with the MIME specifications, and
[RFC 822]. The information presented herein supplements but does not
replace that found in those documents.
This document is a revision to the Experimental protocol defined in
RFC 1806. As compared to RFC 1806, this document contains minor
editorial updates, adds new parameters needed to support the File
Transfer Body Part, and references a separate specification for the
handling of non-ASCII and/or very long parameter values.
Troost, et. al. Standards Track [Page 1]
RFC 2183 Content-Disposition August 1997
1. Introduction
MIME specifies a standard format for encapsulating multiple pieces of
data into a single Internet message. That document does not address
the issue of presentation styles; it provides a framework for the
interchange of message content, but leaves presentation issues solely
in the hands of mail user agent (MUA) implementors.
Two common ways of presenting multipart electronic messages are as a
main document with a list of separate attachments, and as a single
document with the various parts expanded (displayed) inline. The
display of an attachment is generally construed to require positive
action on the part of the recipient, while inline message components
are displayed automatically when the message is viewed. A mechanism
is needed to allow the sender to transmit this sort of presentational
information to the recipient; the Content-Disposition header provides
this mechanism, allowing each component of a message to be tagged
with an indication of its desired presentation semantics.
Tagging messages in this manner will often be sufficient for basic
message formatting. However, in many cases a more powerful and
flexible approach will be necessary. The definition of such
approaches is beyond the scope of this memo; however, such approaches
can benefit from additional Content-Disposition values and
parameters, to be defined at a later date.
In addition to allowing the sender to specify the presentational
disposition of a message component, it is desirable to allow her to
indicate a default archival disposition; a filename. The optional
"filename" parameter provides for this. Further, the creation-date,
modification-date, and read-date parameters allow preservation of
those file attributes when the file is transmitted over MIME email.
NB: The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD,
SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL, when they appear in this
document, are to be interpreted as described in [RFC 2119].
2. The Content-Disposition Header Field
Content-Disposition is an optional header field. In its absence, the
MUA may use whatever presentation method it deems suitable.
It is desirable to keep the set of possible disposition types small
and well defined, to avoid needless complexity. Even so, evolving
usage will likely require the definition of additional disposition
types or parameters, so the set of disposition values is extensible;
see below.
Troost, et. al. Standards Track [Page 2]
RFC 2183 Content-Disposition August 1997
In the extended BNF notation of [RFC 822], the Content-Disposition
header field is defined as follows:
disposition := "Content-Disposition" ":"
disposition-type
*(";" disposition-parm)
disposition-type := "inline"
/ "attachment"
/ extension-token
; values are not case-sensitive
disposition-parm := filename-parm
/ creation-date-parm
/ modification-date-parm
/ read-date-parm
/ size-parm
/ parameter
filename-parm := "filename" "=" value
creation-date-parm := "creation-date" "=" quoted-date-time
modification-date-parm := "modification-date" "=" quoted-date-time
read-date-parm := "read-date" "=" quoted-date-time
size-parm := "size" "=" 1*DIGIT
quoted-date-time := quoted-string
; contents MUST be an RFC 822 `date-time'
; numeric timezones (+HHMM or -HHMM) MUST be used
NOTE ON PARAMETER VALUE LENGHTS: A short (length <= 78 characters)
parameter value containing only non-`tspecials' characters SHOULD be
represented as a single `token'. A short parameter value containing
only ASCII characters, but including `tspecials' characters, SHOULD
be represented as `quoted-string'. Parameter values longer than 78
characters, or which contain non-ASCII characters, MUST be encoded as
specified in [RFC 2184].
`Extension-token', `parameter', `tspecials' and `value' are defined
according to [RFC 2045] (which references [RFC 822] in the definition
of some of these tokens). `quoted-string' and `DIGIT' are defined in
[RFC 822].
Troost, et. al. Standards Track [Page 3]
RFC 2183 Content-Disposition August 1997
2.1 The Inline Disposition Type
A bodypart should be marked `inline' if it is intended to be
displayed automatically upon display of the message. Inline
bodyparts should be presented in the order in which they occur,
subject to the normal semantics of multipart messages.
2.2 The Attachment Disposition Type
Bodyparts can be designated `attachment' to indicate that they are
separate from the main body of the mail message, and that their
display should not be automatic, but contingent upon some further
action of the user. The MUA might instead present the user of a
bitmap terminal with an iconic representation of the attachments, or,
on character terminals, with a list of attachments from which the
user could select for viewing or storage.
2.3 The Filename Parameter
The sender may want to suggest a filename to be used if the entity is
detached and stored in a separate file. If the receiving MUA writes
the entity to a file, the suggested filename should be used as a
basis for the actual filename, where possible.
It is important that the receiving MUA not blindly use the suggested
filename. The suggested filename SHOULD be checked (and possibly
changed) to see that it conforms to local filesystem conventions,
does not overwrite an existing file, and does not present a security
problem (see Security Considerations below).
The receiving MUA SHOULD NOT respect any directory path information
that may seem to be present in the filename parameter. The filename
should be treated as a terminal component only. Portable
specification of directory paths might possibly be done in the future
via a separate Content-Disposition parameter, but no provision is
made for it in this draft.
Current [RFC 2045] grammar restricts parameter values (and hence
Content-Disposition filenames) to US-ASCII. We recognize the great
desirability of allowing arbitrary character sets in filenames, but
it is beyond the scope of this document to define the necessary
mechanisms. We expect that the basic [RFC 1521] `value'
specification will someday be amended to allow use of non-US-ASCII
characters, at which time the same mechanism should be used in the
Content-Disposition filename parameter.
Troost, et. al. Standards Track [Page 4]
RFC 2183 Content-Disposition August 1997
Beyond the limitation to US-ASCII, the sending MUA may wish to bear
in mind the limitations of common filesystems. Many have severe
length and character set restrictions. Short alphanumeric filenames
are least likely to require modification by the receiving system.
The presence of the filename parameter does not force an
implementation to write the entity to a separate file. It is
perfectly acceptable for implementations to leave the entity as part
of the normal mail stream unless the user requests otherwise. As a
consequence, the parameter may be used on any MIME entity, even
`inline' ones. These will not normally be written to files, but the
parameter could be used to provide a filename if the receiving user
should choose to write the part to a file.
2.4 The Creation-Date parameter
The creation-date parameter MAY be used to indicate the date at which
the file was created. If this parameter is included, the paramter
value MUST be a quoted-string which contains a representation of the
creation date of the file in [RFC 822] `date-time' format.
UNIX and POSIX implementors are cautioned that the `st_ctime' file
attribute of the `stat' structure is not the creation time of the
file; it is thus not appropriate as a source for the creation-date
parameter value.
2.5 The Modification-Date parameter
The modification-date parameter MAY be used to indicate the date at
which the file was last modified. If the modification-date parameter
is included, the paramter value MUST be a quoted-string which
contains a representation of the last modification date of the file
in [RFC 822] `date-time' format.
2.6 The Read-Date parameter
The read-date parameter MAY be used to indicate the date at which the
file was last read. If the read-date parameter is included, the
parameter value MUST be a quoted-string which contains a
representation of the last-read date of the file in [RFC 822] `date-
time' format.
2.7 The Size parameter
The size parameter indicates an approximate size of the file in
octets. It can be used, for example, to pre-allocate space before
attempting to store the file, or to determine whether enough space
exists.
Troost, et. al. Standards Track [Page 5]
RFC 2183 Content-Disposition August 1997
2.8 Future Extensions and Unrecognized Disposition Types
In the likely event that new parameters or disposition types are
needed, they should be registered with the Internet Assigned Numbers
Authority (IANA), in the manner specified in Section 9 of this memo.
Once new disposition types and parameters are defined, there is of
course the likelihood that implementations will see disposition types
and parameters they do not understand. Furthermore, since x-tokens
are allowed, implementations may also see entirely unregistered
disposition types and parameters.
Unrecognized parameters should be ignored. Unrecognized disposition
types should be treated as `attachment'. The choice of `attachment'
for unrecognized types is made because a sender who goes to the
trouble of producing a Content-Disposition header with a new
disposition type is more likely aiming for something more elaborate
than inline presentation.
Unless noted otherwise in the definition of a parameter, Content-
Disposition parameters are valid for all dispositions. (In contrast
to MIME content-type parameters, which are defined on a per-content-
type basis.) Thus, for example, the `filename' parameter still means
the name of the file to which the part should be written, even if the
disposition itself is unrecognized.
2.9 Content-Disposition and Multipart
If a Content-Disposition header is used on a multipart body part, it
applies to the multipart as a whole, not the individual subparts.
The disposition types of the subparts do not need to be consulted
until the multipart itself is presented. When the multipart is
displayed, then the dispositions of the subparts should be respected.
If the `inline' disposition is used, the multipart should be
displayed as normal; however, an `attachment' subpart should require
action from the user to display.
If the `attachment' disposition is used, presentation of the
multipart should not proceed without explicit user action. Once the
user has chosen to display the multipart, the individual subpart
dispositions should be consulted to determine how to present the
subparts.
Troost, et. al. Standards Track [Page 6]
RFC 2183 Content-Disposition August 1997
2.10 Content-Disposition and the Main Message
It is permissible to use Content-Disposition on the main body of an
[RFC 822] message.
3. Examples
Here is a an example of a body part containing a JPEG image that is
intended to be viewed by the user immediately:
Content-Type: image/jpeg
Content-Disposition: inline
Content-Description: just a small picture of me
<jpeg data>
The following body part contains a JPEG image that should be
displayed to the user only if the user requests it. If the JPEG is
written to a file, the file should be named "genome.jpg". The
recipient's user might also choose to set the last-modified date of
the stored file to date in the modification-date parameter:
Content-Type: image/jpeg
Content-Disposition: attachment; filename=genome.jpeg;
modification-date="Wed, 12 Feb 1997 16:29:51 -0500";
Content-Description: a complete map of the human genome
<jpeg data>
The following is an example of the use of the `attachment'
disposition with a multipart body part. The user should see text-
part-1 immediately, then take some action to view multipart-2. After
taking action to view multipart-2, the user will see text-part-2
right away, and be required to take action to view jpeg-1. Subparts
are indented for clarity; they would not be so indented in a real
message.
Troost, et. al. Standards Track [Page 7]
RFC 2183 Content-Disposition August 1997
Content-Type: multipart/mixed; boundary=outer
Content-Description: multipart-1
--outer
Content-Type: text/plain
Content-Disposition: inline
Content-Description: text-part-1
Some text goes here
--outer
Content-Type: multipart/mixed; boundary=inner
Content-Disposition: attachment
Content-Description: multipart-2
--inner
Content-Type: text/plain
Content-Disposition: inline
Content-Description: text-part-2
Some more text here.
--inner
Content-Type: image/jpeg
Content-Disposition: attachment
Content-Description: jpeg-1
<jpeg data>
--inner--
--outer--
4. Summary
Content-Disposition takes one of two values, `inline' and
`attachment'. `Inline' indicates that the entity should be
immediately displayed to the user, whereas `attachment' means that
the user should take additional action to view the entity.
The `filename' parameter can be used to suggest a filename for
storing the bodypart, if the user wishes to store it in an external
file.
Troost, et. al. Standards Track [Page 8]
RFC 2183 Content-Disposition August 1997
5. Security Considerations
There are security issues involved any time users exchange data.
While these are not to be minimized, neither does this memo change
the status quo in that regard, except in one instance.
Since this memo provides a way for the sender to suggest a filename,
a receiving MUA must take care that the sender's suggested filename
does not represent a hazard. Using UNIX as an example, some hazards
would be:
+ Creating startup files (e.g., ".login").
+ Creating or overwriting system files (e.g., "/etc/passwd").
+ Overwriting any existing file.
+ Placing executable files into any command search path
(e.g., "~/bin/more").
+ Sending the file to a pipe (e.g., "| sh").
In general, the receiving MUA should not name or place the file such
that it will get interpreted or executed without the user explicitly
initiating the action.
It is very important to note that this is not an exhaustive list; it
is intended as a small set of examples only. Implementors must be
alert to the potential hazards on their target systems.
6. References
[RFC 2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement
Levels", RFC 2119, March 1997.
[RFC 2184]
Freed, N. and K. Moore, "MIME Parameter value and Encoded Words:
Character Sets, Lanaguage, and Continuations", RFC 2184, August
1997.
[RFC 2045]
Freed, N. and N. Borenstein, "MIME (Multipurpose Internet Mail
Extensions) Part One: Format of Internet Message Bodies", RFC
2045, December 1996.
Troost, et. al. Standards Track [Page 9]
RFC 2183 Content-Disposition August 1997
[RFC 2046]
Freed, N. and N. Borenstein, "MIME (Multipurpose Internet Mail
Extensions) Part Two: Media Types", RFC 2046, December 1996.
[RFC 2047]
Moore, K., "MIME (Multipurpose Internet Mail Extensions) Part
Three: Message Header Extensions for non-ASCII Text", RFC 2047,
December 1996.
[RFC 2048]
Freed, N., Klensin, J. and J. Postel, "MIME (Multipurpose
Internet Mail Extensions) Part Four: Registration Procedures",
RFC 2048, December 1996.
[RFC 2049]
Freed, N. and N. Borenstein, "MIME (Multipurpose Internet Mail
Extensions) Part Five: Conformance Criteria and Examples", RFC
2049, December 1996.
[RFC 822]
Crocker, D., "Standard for the Format of ARPA Internet Text
Messages", STD 11, RFC 822, UDEL, August 1982.
7. Acknowledgements
We gratefully acknowledge the help these people provided during the
preparation of this draft:
Nathaniel Borenstein
Ned Freed
Keith Moore
Dave Crocker
Dan Pritchett
Troost, et. al. Standards Track [Page 10]
RFC 2183 Content-Disposition August 1997
8. Authors' Addresses
You should blame the editor of this version of the document for any
changes since RFC 1806:
Keith Moore
Department of Computer Science
University of Tennessee, Knoxville
107 Ayres Hall
Knoxville TN 37996-1301
USA
Phone: +1 (423) 974-5067
Fax: +1 (423) 974-8296
Email: moore@cs.utk.edu
The authors of RFC 1806 are:
Rens Troost
New Century Systems
324 East 41st Street #804
New York, NY, 10017 USA
Phone: +1 (212) 557-2050
Fax: +1 (212) 557-2049
EMail: rens@century.com
Steve Dorner
QUALCOMM Incorporated
6455 Lusk Boulevard
San Diego, CA 92121
USA
EMail: sdorner@qualcomm.com
9. Registration of New Content-Disposition Values and Parameters
New Content-Disposition values (besides "inline" and "attachment")
may be defined only by Internet standards-track documents, or in
Experimental documents approved by the Internet Engineering Steering
Group.
Troost, et. al. Standards Track [Page 11]
RFC 2183 Content-Disposition August 1997
New content-disposition parameters may be registered by supplying the
information in the following template and sending it via electronic
mail to IANA@IANA.ORG:
To: IANA@IANA.ORG
Subject: Registration of new Content-Disposition parameter
Content-Disposition parameter name:
Allowable values for this parameter:
(If the parameter can only assume a small number of values,
list each of those values. Otherwise, describe the values
that the parameter can assume.)
Description:
(What is the purpose of this parameter and how is it used?)
10. Changes since RFC 1806
The following changes have been made since the earlier version of
this document, published in RFC 1806 as an Experimental protocol:
+ Updated references to MIME documents. In some cases this
involved substituting a reference to one of the current MIME
RFCs for a reference to RFC 1521; in other cases, a reference to
RFC 1521 was simply replaced with the word "MIME".
+ Added a section on registration procedures, since none of the
procedures in RFC 2048 seemed to be appropriate.
+ Added new parameter types: creation-date, modification-date,
read-date, and size.
+ Incorporated a reference to draft-freed-pvcsc-* for encoding
long or non-ASCII parameter values.
+ Added reference to RFC 2119 to define MUST, SHOULD, etc.
keywords.
Troost, et. al. Standards Track [Page 12]

View File

@@ -0,0 +1,899 @@
Network Working Group J. Myers
Request for Comments: 2222 Netscape Communications
Category: Standards Track October 1997
Simple Authentication and Security Layer (SASL)
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (1997). All Rights Reserved.
Table of Contents
1. Abstract .............................................. 2
2. Organization of this Document ......................... 2
2.1. How to Read This Document ............................. 2
2.2. Conventions Used in this Document ..................... 2
2.3. Examples .............................................. 3
3. Introduction and Overview ............................. 3
4. Profiling requirements ................................ 4
5. Specific issues ....................................... 5
5.1. Client sends data first ............................... 5
5.2. Server returns success with additional data ........... 5
5.3. Multiple authentications .............................. 5
6. Registration procedures ............................... 6
6.1. Comments on SASL mechanism registrations .............. 6
6.2. Location of Registered SASL Mechanism List ............ 6
6.3. Change Control ........................................ 7
6.4. Registration Template ................................. 7
7. Mechanism definitions ................................. 8
7.1. Kerberos version 4 mechanism .......................... 8
7.2. GSSAPI mechanism ...................................... 9
7.2.1 Client side of authentication protocol exchange ....... 9
7.2.2 Server side of authentication protocol exchange ....... 10
7.2.3 Security layer ........................................ 11
7.3. S/Key mechanism ....................................... 11
7.4. External mechanism .................................... 12
8. References ............................................ 13
9. Security Considerations ............................... 13
10. Author's Address ...................................... 14
Myers Standards Track [Page 1]
RFC 2222 SASL October 1997
Appendix A. Relation of SASL to Transport Security .......... 15
Full Copyright Statement .................................... 16
1. Abstract
This document describes a method for adding authentication support to
connection-based protocols. To use this specification, a protocol
includes a command for identifying and authenticating a user to a
server and for optionally negotiating protection of subsequent
protocol interactions. If its use is negotiated, a security layer is
inserted between the protocol and the connection. This document
describes how a protocol specifies such a command, defines several
mechanisms for use by the command, and defines the protocol used for
carrying a negotiated security layer over the connection.
2. Organization of this Document
2.1. How to Read This Document
This document is written to serve two different audiences, protocol
designers using this specification to support authentication in their
protocol, and implementors of clients or servers for those protocols
using this specification.
The sections "Introduction and Overview", "Profiling requirements",
and "Security Considerations" cover issues that protocol designers
need to understand and address in profiling this specification for
use in a specific protocol.
Implementors of a protocol using this specification need the
protocol-specific profiling information in addition to the
information in this document.
2.2. Conventions Used in this Document
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively.
The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY"
in this document are to be interpreted as defined in "Key words for
use in RFCs to Indicate Requirement Levels" [RFC 2119].
Myers Standards Track [Page 2]
RFC 2222 SASL October 1997
2.3. Examples
Examples in this document are for the IMAP profile [RFC 2060] of this
specification. The base64 encoding of challenges and responses, as
well as the "+ " preceding the responses are part of the IMAP4
profile, not part of the SASL specification itself.
3. Introduction and Overview
The Simple Authentication and Security Layer (SASL) is a method for
adding authentication support to connection-based protocols. To use
this specification, a protocol includes a command for identifying and
authenticating a user to a server and for optionally negotiating a
security layer for subsequent protocol interactions.
The command has a required argument identifying a SASL mechanism.
SASL mechanisms are named by strings, from 1 to 20 characters in
length, consisting of upper-case letters, digits, hyphens, and/or
underscores. SASL mechanism names must be registered with the IANA.
Procedures for registering new SASL mechanisms are given in the
section "Registration procedures"
If a server supports the requested mechanism, it initiates an
authentication protocol exchange. This consists of a series of
server challenges and client responses that are specific to the
requested mechanism. The challenges and responses are defined by the
mechanisms as binary tokens of arbitrary length. The protocol's
profile then specifies how these binary tokens are then encoded for
transfer over the connection.
After receiving the authentication command or any client response, a
server may issue a challenge, indicate failure, or indicate
completion. The protocol's profile specifies how the server
indicates which of the above it is doing.
After receiving a challenge, a client may issue a response or abort
the exchange. The protocol's profile specifies how the client
indicates which of the above it is doing.
During the authentication protocol exchange, the mechanism performs
authentication, transmits an authorization identity (frequently known
as a userid) from the client to server, and negotiates the use of a
mechanism-specific security layer. If the use of a security layer is
agreed upon, then the mechanism must also define or negotiate the
maximum cipher-text buffer size that each side is able to receive.
Myers Standards Track [Page 3]
RFC 2222 SASL October 1997
The transmitted authorization identity may be different than the
identity in the client's authentication credentials. This permits
agents such as proxy servers to authenticate using their own
credentials, yet request the access privileges of the identity for
which they are proxying. With any mechanism, transmitting an
authorization identity of the empty string directs the server to
derive an authorization identity from the client's authentication
credentials.
If use of a security layer is negotiated, it is applied to all
subsequent data sent over the connection. The security layer takes
effect immediately following the last response of the authentication
exchange for data sent by the client and the completion indication
for data sent by the server. Once the security layer is in effect,
the protocol stream is processed by the security layer into buffers
of cipher-text. Each buffer is transferred over the connection as a
stream of octets prepended with a four octet field in network byte
order that represents the length of the following buffer. The length
of the cipher-text buffer must be no larger than the maximum size
that was defined or negotiated by the other side.
4. Profiling requirements
In order to use this specification, a protocol definition must supply
the following information:
1. A service name, to be selected from the IANA registry of "service"
elements for the GSSAPI host-based service name form [RFC 2078].
2. A definition of the command to initiate the authentication
protocol exchange. This command must have as a parameter the
mechanism name being selected by the client.
The command SHOULD have an optional parameter giving an initial
response. This optional parameter allows the client to avoid a
round trip when using a mechanism which is defined to have the
client send data first. When this initial response is sent by the
client and the selected mechanism is defined to have the server
start with an initial challenge, the command fails. See section
5.1 of this document for further information.
3. A definition of the method by which the authentication protocol
exchange is carried out, including how the challenges and
responses are encoded, how the server indicates completion or
failure of the exchange, how the client aborts an exchange, and
how the exchange method interacts with any line length limits in
the protocol.
Myers Standards Track [Page 4]
RFC 2222 SASL October 1997
4. Identification of the octet where any negotiated security layer
starts to take effect, in both directions.
5. A specification of how the authorization identity passed from the
client to the server is to be interpreted.
5. Specific issues
5.1. Client sends data first
Some mechanisms specify that the first data sent in the
authentication protocol exchange is from the client to the server.
If a protocol's profile permits the command which initiates an
authentication protocol exchange to contain an initial client
response, this parameter SHOULD be used with such mechanisms.
If the initial client response parameter is not given, or if a
protocol's profile does not permit the command which initiates an
authentication protocol exchange to contain an initial client
response, then the server issues a challenge with no data. The
client's response to this challenge is then used as the initial
client response. (The server then proceeds to send the next
challenge, indicates completion, or indicates failure.)
5.2. Server returns success with additional data
Some mechanisms may specify that server challenge data be sent to the
client along with an indication of successful completion of the
exchange. This data would, for example, authenticate the server to
the client.
If a protocol's profile does not permit this server challenge to be
returned with a success indication, then the server issues the server
challenge without an indication of successful completion. The client
then responds with no data. After receiving this empty response, the
server then indicates successful completion.
5.3. Multiple authentications
Unless otherwise stated by the protocol's profile, only one
successful SASL negotiation may occur in a protocol session. In this
case, once an authentication protocol exchange has successfully
completed, further attempts to initiate an authentication protocol
exchange fail.
Myers Standards Track [Page 5]
RFC 2222 SASL October 1997
In the case that a profile explicitly permits multiple successful
SASL negotiations to occur, then in no case may multiple security
layers be simultaneously in effect. If a security layer is in effect
and a subsequent SASL negotiation selects no security layer, the
original security layer remains in effect. If a security layer is in
effect and a subsequent SASL negotiation selects a second security
layer, then the second security layer replaces the first.
6. Registration procedures
Registration of a SASL mechanism is done by filling in the template
in section 6.4 and sending it in to iana@isi.edu. IANA has the right
to reject obviously bogus registrations, but will perform no review
of clams made in the registration form.
There is no naming convention for SASL mechanisms; any name that
conforms to the syntax of a SASL mechanism name can be registered.
While the registration procedures do not require it, authors of SASL
mechanisms are encouraged to seek community review and comment
whenever that is feasible. Authors may seek community review by
posting a specification of their proposed mechanism as an internet-
draft. SASL mechanisms intended for widespread use should be
standardized through the normal IETF process, when appropriate.
6.1. Comments on SASL mechanism registrations
Comments on registered SASL mechanisms should first be sent to the
"owner" of the mechanism. Submitters of comments may, after a
reasonable attempt to contact the owner, request IANA to attach their
comment to the SASL mechanism registration itself. If IANA approves
of this the comment will be made accessible in conjunction with the
SASL mechanism registration itself.
6.2. Location of Registered SASL Mechanism List
SASL mechanism registrations will be posted in the anonymous FTP
directory "ftp://ftp.isi.edu/in-notes/iana/assignments/sasl-
mechanisms/" and all registered SASL mechanisms will be listed in the
periodically issued "Assigned Numbers" RFC [currently STD 2, RFC
1700]. The SASL mechanism description and other supporting material
may also be published as an Informational RFC by sending it to "rfc-
editor@isi.edu" (please follow the instructions to RFC authors [RFC
2223]).
Myers Standards Track [Page 6]
RFC 2222 SASL October 1997
6.3. Change Control
Once a SASL mechanism registration has been published by IANA, the
author may request a change to its definition. The change request
follows the same procedure as the registration request.
The owner of a SASL mechanism may pass responsibility for the SASL
mechanism to another person or agency by informing IANA; this can be
done without discussion or review.
The IESG may reassign responsibility for a SASL mechanism. The most
common case of this will be to enable changes to be made to
mechanisms where the author of the registration has died, moved out
of contact or is otherwise unable to make changes that are important
to the community.
SASL mechanism registrations may not be deleted; mechanisms which are
no longer believed appropriate for use can be declared OBSOLETE by a
change to their "intended use" field; such SASL mechanisms will be
clearly marked in the lists published by IANA.
The IESG is considered to be the owner of all SASL mechanisms which
are on the IETF standards track.
6.4. Registration Template
To: iana@iana.org
Subject: Registration of SASL mechanism X
SASL mechanism name:
Security considerations:
Published specification (optional, recommended):
Person & email address to contact for further information:
Intended usage:
(One of COMMON, LIMITED USE or OBSOLETE)
Author/Change controller:
(Any other information that the author deems interesting may be
added below this line.)
Myers Standards Track [Page 7]
RFC 2222 SASL October 1997
7. Mechanism definitions
The following mechanisms are hereby defined.
7.1. Kerberos version 4 mechanism
The mechanism name associated with Kerberos version 4 is
"KERBEROS_V4".
The first challenge consists of a random 32-bit number in network
byte order. The client responds with a Kerberos ticket and an
authenticator for the principal "service.hostname@realm", where
"service" is the service name specified in the protocol's profile,
"hostname" is the first component of the host name of the server with
all letters in lower case, and where "realm" is the Kerberos realm of
the server. The encrypted checksum field included within the
Kerberos authenticator contains the server provided challenge in
network byte order.
Upon decrypting and verifying the ticket and authenticator, the
server verifies that the contained checksum field equals the original
server provided random 32-bit number. Should the verification be
successful, the server must add one to the checksum and construct 8
octets of data, with the first four octets containing the incremented
checksum in network byte order, the fifth octet containing a bit-mask
specifying the security layers supported by the server, and the sixth
through eighth octets containing, in network byte order, the maximum
cipher-text buffer size the server is able to receive. The server
must encrypt using DES ECB mode the 8 octets of data in the session
key and issue that encrypted data in a second challenge. The client
considers the server authenticated if the first four octets of the
un-encrypted data is equal to one plus the checksum it previously
sent.
The client must construct data with the first four octets containing
the original server-issued checksum in network byte order, the fifth
octet containing the bit-mask specifying the selected security layer,
the sixth through eighth octets containing in network byte order the
maximum cipher-text buffer size the client is able to receive, and
the following octets containing the authorization identity. The
client must then append from one to eight zero-valued octets so that
the length of the data is a multiple of eight octets. The client must
then encrypt using DES PCBC mode the data with the session key and
respond with the encrypted data. The server decrypts the data and
verifies the contained checksum. The server must verify that the
principal identified in the Kerberos ticket is authorized to connect
as that authorization identity. After this verification, the
authentication process is complete.
Myers Standards Track [Page 8]
RFC 2222 SASL October 1997
The security layers and their corresponding bit-masks are as follows:
1 No security layer
2 Integrity (krb_mk_safe) protection
4 Privacy (krb_mk_priv) protection
Other bit-masks may be defined in the future; bits which are not
understood must be negotiated off.
EXAMPLE: The following are two Kerberos version 4 login scenarios to
the IMAP4 protocol (note that the line breaks in the sample
authenticators are for editorial clarity and are not in real
authenticators)
S: * OK IMAP4 Server
C: A001 AUTHENTICATE KERBEROS_V4
S: + AmFYig==
C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT
+nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd
WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh
S: + or//EoAADZI=
C: DiAF5A4gA+oOIALuBkAAmw==
S: A001 OK Kerberos V4 authentication successful
S: * OK IMAP4 Server
C: A001 AUTHENTICATE KERBEROS_V4
S: + gcfgCA==
C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT
+nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd
WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh
S: A001 NO Kerberos V4 authentication failed
7.2. GSSAPI mechanism
The mechanism name associated with all mechanisms employing the
GSSAPI [RFC 2078] is "GSSAPI".
7.2.1 Client side of authentication protocol exchange
The client calls GSS_Init_sec_context, passing in 0 for
input_context_handle (initially) and a targ_name equal to output_name
from GSS_Import_Name called with input_name_type of
GSS_C_NT_HOSTBASED_SERVICE and input_name_string of
"service@hostname" where "service" is the service name specified in
the protocol's profile, and "hostname" is the fully qualified host
name of the server. The client then responds with the resulting
output_token. If GSS_Init_sec_context returns GSS_S_CONTINUE_NEEDED,
Myers Standards Track [Page 9]
RFC 2222 SASL October 1997
then the client should expect the server to issue a token in a
subsequent challenge. The client must pass the token to another call
to GSS_Init_sec_context, repeating the actions in this paragraph.
When GSS_Init_sec_context returns GSS_S_COMPLETE, the client takes
the following actions: If the last call to GSS_Init_sec_context
returned an output_token, then the client responds with the
output_token, otherwise the client responds with no data. The client
should then expect the server to issue a token in a subsequent
challenge. The client passes this token to GSS_Unwrap and interprets
the first octet of resulting cleartext as a bit-mask specifying the
security layers supported by the server and the second through fourth
octets as the maximum size output_message to send to the server. The
client then constructs data, with the first octet containing the
bit-mask specifying the selected security layer, the second through
fourth octets containing in network byte order the maximum size
output_message the client is able to receive, and the remaining
octets containing the authorization identity. The client passes the
data to GSS_Wrap with conf_flag set to FALSE, and responds with the
generated output_message. The client can then consider the server
authenticated.
7.2.2 Server side of authentication protocol exchange
The server passes the initial client response to
GSS_Accept_sec_context as input_token, setting input_context_handle
to 0 (initially). If GSS_Accept_sec_context returns
GSS_S_CONTINUE_NEEDED, the server returns the generated output_token
to the client in challenge and passes the resulting response to
another call to GSS_Accept_sec_context, repeating the actions in this
paragraph.
When GSS_Accept_sec_context returns GSS_S_COMPLETE, the client takes
the following actions: If the last call to GSS_Accept_sec_context
returned an output_token, the server returns it to the client in a
challenge and expects a reply from the client with no data. Whether
or not an output_token was returned (and after receipt of any
response from the client to such an output_token), the server then
constructs 4 octets of data, with the first octet containing a bit-
mask specifying the security layers supported by the server and the
second through fourth octets containing in network byte order the
maximum size output_token the server is able to receive. The server
must then pass the plaintext to GSS_Wrap with conf_flag set to FALSE
and issue the generated output_message to the client in a challenge.
The server must then pass the resulting response to GSS_Unwrap and
interpret the first octet of resulting cleartext as the bit-mask for
the selected security layer, the second through fourth octets as the
maximum size output_message to send to the client, and the remaining
Myers Standards Track [Page 10]
RFC 2222 SASL October 1997
octets as the authorization identity. The server must verify that
the src_name is authorized to authenticate as the authorization
identity. After these verifications, the authentication process is
complete.
7.2.3 Security layer
The security layers and their corresponding bit-masks are as follows:
1 No security layer
2 Integrity protection.
Sender calls GSS_Wrap with conf_flag set to FALSE
4 Privacy protection.
Sender calls GSS_Wrap with conf_flag set to TRUE
Other bit-masks may be defined in the future; bits which are not
understood must be negotiated off.
7.3. S/Key mechanism
The mechanism name associated with S/Key [RFC 1760] using the MD4
digest algorithm is "SKEY".
The client sends an initial response with the authorization identity.
The server then issues a challenge which contains the decimal
sequence number followed by a single space and the seed string for
the indicated authorization identity. The client responds with the
one-time-password, as either a 64-bit value in network byte order or
encoded in the "six English words" format.
The server must verify the one-time-password. After this
verification, the authentication process is complete.
S/Key authentication does not provide for any security layers.
EXAMPLE: The following are two S/Key login scenarios in the IMAP4
protocol.
S: * OK IMAP4 Server
C: A001 AUTHENTICATE SKEY
S: +
C: bW9yZ2Fu
S: + OTUgUWE1ODMwOA==
C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: A001 OK S/Key authentication successful
Myers Standards Track [Page 11]
RFC 2222 SASL October 1997
S: * OK IMAP4 Server
C: A001 AUTHENTICATE SKEY
S: +
C: c21pdGg=
S: + OTUgUWE1ODMwOA==
C: BsAY3g4gBNo=
S: A001 NO S/Key authentication failed
The following is an S/Key login scenario in an IMAP4-like protocol
which has an optional "initial response" argument to the AUTHENTICATE
command.
S: * OK IMAP4-Like Server
C: A001 AUTHENTICATE SKEY bW9yZ2Fu
S: + OTUgUWE1ODMwOA==
C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: A001 OK S/Key authentication successful
7.4. External mechanism
The mechanism name associated with external authentication is
"EXTERNAL".
The client sends an initial response with the authorization identity.
The server uses information, external to SASL, to determine whether
the client is authorized to authenticate as the authorization
identity. If the client is so authorized, the server indicates
successful completion of the authentication exchange; otherwise the
server indicates failure.
The system providing this external information may be, for example,
IPsec or TLS.
If the client sends the empty string as the authorization identity
(thus requesting the authorization identity be derived from the
client's authentication credentials), the authorization identity is
to be derived from authentication credentials which exist in the
system which is providing the external authentication.
Myers Standards Track [Page 12]
RFC 2222 SASL October 1997
8. References
[RFC 2060] Crispin, M., "Internet Message Access Protocol - Version
4rev1", RFC 2060, December 1996.
[RFC 2078] Linn, J., "Generic Security Service Application Program
Interface, Version 2", RFC 2078, January 1997.
[RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", RFC 2119, March 1997.
[RFC 2223] Postel, J., and J. Reynolds, "Instructions to RFC
Authors", RFC 2223, October 1997.
[RFC 1760] Haller, N., "The S/Key One-Time Password System", RFC
1760, February 1995.
[RFC 1700] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2,
RFC 1700, October 1994.
9. Security Considerations
Security issues are discussed throughout this memo.
The mechanisms that support integrity protection are designed such
that the negotiation of the security layer and authorization identity
is integrity protected. When the client selects a security layer
with at least integrity protection, this protects against an active
attacker hijacking the connection and modifying the authentication
exchange to negotiate a plaintext connection.
When a server or client supports multiple authentication mechanisms,
each of which has a different security strength, it is possible for
an active attacker to cause a party to use the least secure mechanism
supported. To protect against this sort of attack, a client or
server which supports mechanisms of different strengths should have a
configurable minimum strength that it will use. It is not sufficient
for this minimum strength check to only be on the server, since an
active attacker can change which mechanisms the client sees as being
supported, causing the client to send authentication credentials for
its weakest supported mechanism.
Myers Standards Track [Page 13]
RFC 2222 SASL October 1997
The client's selection of a SASL mechanism is done in the clear and
may be modified by an active attacker. It is important for any new
SASL mechanisms to be designed such that an active attacker cannot
obtain an authentication with weaker security properties by modifying
the SASL mechanism name and/or the challenges and responses.
Any protocol interactions prior to authentication are performed in
the clear and may be modified by an active attacker. In the case
where a client selects integrity protection, it is important that any
security-sensitive protocol negotiations be performed after
authentication is complete. Protocols should be designed such that
negotiations performed prior to authentication should be either
ignored or revalidated once authentication is complete.
10. Author's Address
John G. Myers
Netscape Communications
501 E. Middlefield Road
Mail Stop MV-029
Mountain View, CA 94043-4042
EMail: jgmyers@netscape.com
Myers Standards Track [Page 14]
RFC 2222 SASL October 1997
Appendix A. Relation of SASL to Transport Security
Questions have been raised about the relationship between SASL and
various services (such as IPsec and TLS) which provide a secured
connection.
Two of the key features of SASL are:
1. The separation of the authorization identity from the identity in
the client's credentials. This permits agents such as proxy
servers to authenticate using their own credentials, yet request
the access privileges of the identity for which they are proxying.
2. Upon successful completion of an authentication exchange, the
server knows the authorization identity the client wishes to use.
This allows servers to move to a "user is authenticated" state in
the protocol.
These features are extremely important to some application protocols,
yet Transport Security services do not always provide them. To
define SASL mechanisms based on these services would be a very messy
task, as the framing of these services would be redundant with the
framing of SASL and some method of providing these important SASL
features would have to be devised.
Sometimes it is desired to enable within an existing connection the
use of a security service which does not fit the SASL model. (TLS is
an example of such a service.) This can be done by adding a command,
for example "STARTTLS", to the protocol. Such a command is outside
the scope of SASL, and should be different from the command which
starts a SASL authentication protocol exchange.
In certain situations, it is reasonable to use SASL underneath one of
these Transport Security services. The transport service would
secure the connection, either service would authenticate the client,
and SASL would negotiate the authorization identity. The SASL
negotiation would be what moves the protocol from "unauthenticated"
to "authenticated" state. The "EXTERNAL" SASL mechanism is
explicitly intended to handle the case where the transport service
secures the connection and authenticates the client and SASL
negotiates the authorization identity.
When using SASL underneath a sufficiently strong Transport Security
service, a SASL security layer would most likely be redundant. The
client and server would thus probably want to negotiate off the use
of a SASL security layer.
Myers Standards Track [Page 15]
RFC 2222 SASL October 1997
Full Copyright Statement
Copyright (C) The Internet Society (1997). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implmentation may be prepared, copied, published
andand distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Myers Standards Track [Page 16]

View File

@@ -0,0 +1,563 @@
Network Working Group N. Freed
Request for Comments: 2231 Innosoft
Updates: 2045, 2047, 2183 K. Moore
Obsoletes: 2184 University of Tennessee
Category: Standards Track November 1997
MIME Parameter Value and Encoded Word Extensions:
Character Sets, Languages, and Continuations
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (1997). All Rights Reserved.
1. Abstract
This memo defines extensions to the RFC 2045 media type and RFC 2183
disposition parameter value mechanisms to provide
(1) a means to specify parameter values in character sets
other than US-ASCII,
(2) to specify the language to be used should the value be
displayed, and
(3) a continuation mechanism for long parameter values to
avoid problems with header line wrapping.
This memo also defines an extension to the encoded words defined in
RFC 2047 to allow the specification of the language to be used for
display as well as the character set.
2. Introduction
The Multipurpose Internet Mail Extensions, or MIME [RFC-2045, RFC-
2046, RFC-2047, RFC-2048, RFC-2049], define a message format that
allows for:
Freed & Moore Standards Track [Page 1]
RFC 2231 MIME Value and Encoded Word Extensions November 1997
(1) textual message bodies in character sets other than
US-ASCII,
(2) non-textual message bodies,
(3) multi-part message bodies, and
(4) textual header information in character sets other than
US-ASCII.
MIME is now widely deployed and is used by a variety of Internet
protocols, including, of course, Internet email. However, MIME's
success has resulted in the need for additional mechanisms that were
not provided in the original protocol specification.
In particular, existing MIME mechanisms provide for named media type
(content-type field) parameters as well as named disposition
(content-disposition field). A MIME media type may specify any
number of parameters associated with all of its subtypes, and any
specific subtype may specify additional parameters for its own use. A
MIME disposition value may specify any number of associated
parameters, the most important of which is probably the attachment
disposition's filename parameter.
These parameter names and values end up appearing in the content-type
and content-disposition header fields in Internet email. This
inherently imposes three crucial limitations:
(1) Lines in Internet email header fields are folded
according to RFC 822 folding rules. This makes long
parameter values problematic.
(2) MIME headers, like the RFC 822 headers they often
appear in, are limited to 7bit US-ASCII, and the
encoded-word mechanisms of RFC 2047 are not available
to parameter values. This makes it impossible to have
parameter values in character sets other than US-ASCII
without specifying some sort of private per-parameter
encoding.
(3) It has recently become clear that character set
information is not sufficient to properly display some
sorts of information -- language information is also
needed [RFC-2130]. For example, support for
handicapped users may require reading text string
Freed & Moore Standards Track [Page 2]
RFC 2231 MIME Value and Encoded Word Extensions November 1997
aloud. The language the text is written in is needed
for this to be done correctly. Some parameter values
may need to be displayed, hence there is a need to
allow for the inclusion of language information.
The last problem on this list is also an issue for the encoded words
defined by RFC 2047, as encoded words are intended primarily for
display purposes.
This document defines extensions that address all of these
limitations. All of these extensions are implemented in a fashion
that is completely compatible at a syntactic level with existing MIME
implementations. In addition, the extensions are designed to have as
little impact as possible on existing uses of MIME.
IMPORTANT NOTE: These mechanisms end up being somewhat gibbous when
they actually are used. As such, these mechanisms should not be used
lightly; they should be reserved for situations where a real need for
them exists.
2.1. Requirements notation
This document occasionally uses terms that appear in capital letters.
When the terms "MUST", "SHOULD", "MUST NOT", "SHOULD NOT", and "MAY"
appear capitalized, they are being used to indicate particular
requirements of this specification. A discussion of the meanings of
these terms appears in [RFC- 2119].
3. Parameter Value Continuations
Long MIME media type or disposition parameter values do not interact
well with header line wrapping conventions. In particular, proper
header line wrapping depends on there being places where linear
whitespace (LWSP) is allowed, which may or may not be present in a
parameter value, and even if present may not be recognizable as such
since specific knowledge of parameter value syntax may not be
available to the agent doing the line wrapping. The result is that
long parameter values may end up getting truncated or otherwise
damaged by incorrect line wrapping implementations.
A mechanism is therefore needed to break up parameter values into
smaller units that are amenable to line wrapping. Any such mechanism
MUST be compatible with existing MIME processors. This means that
(1) the mechanism MUST NOT change the syntax of MIME media
type and disposition lines, and
Freed & Moore Standards Track [Page 3]
RFC 2231 MIME Value and Encoded Word Extensions November 1997
(2) the mechanism MUST NOT depend on parameter ordering
since MIME states that parameters are not order
sensitive. Note that while MIME does prohibit
modification of MIME headers during transport, it is
still possible that parameters will be reordered when
user agent level processing is done.
The obvious solution, then, is to use multiple parameters to contain
a single parameter value and to use some kind of distinguished name
to indicate when this is being done. And this obvious solution is
exactly what is specified here: The asterisk character ("*") followed
by a decimal count is employed to indicate that multiple parameters
are being used to encapsulate a single parameter value. The count
starts at 0 and increments by 1 for each subsequent section of the
parameter value. Decimal values are used and neither leading zeroes
nor gaps in the sequence are allowed.
The original parameter value is recovered by concatenating the
various sections of the parameter, in order. For example, the
content-type field
Content-Type: message/external-body; access-type=URL;
URL*0="ftp://";
URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"
is semantically identical to
Content-Type: message/external-body; access-type=URL;
URL="ftp://cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"
Note that quotes around parameter values are part of the value
syntax; they are NOT part of the value itself. Furthermore, it is
explicitly permitted to have a mixture of quoted and unquoted
continuation fields.
4. Parameter Value Character Set and Language Information
Some parameter values may need to be qualified with character set or
language information. It is clear that a distinguished parameter
name is needed to identify when this information is present along
with a specific syntax for the information in the value itself. In
addition, a lightweight encoding mechanism is needed to accommodate 8
bit information in parameter values.
Freed & Moore Standards Track [Page 4]
RFC 2231 MIME Value and Encoded Word Extensions November 1997
Asterisks ("*") are reused to provide the indicator that language and
character set information is present and encoding is being used. A
single quote ("'") is used to delimit the character set and language
information at the beginning of the parameter value. Percent signs
("%") are used as the encoding flag, which agrees with RFC 2047.
Specifically, an asterisk at the end of a parameter name acts as an
indicator that character set and language information may appear at
the beginning of the parameter value. A single quote is used to
separate the character set, language, and actual value information in
the parameter value string, and an percent sign is used to flag
octets encoded in hexadecimal. For example:
Content-Type: application/x-stuff;
title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A
Note that it is perfectly permissible to leave either the character
set or language field blank. Note also that the single quote
delimiters MUST be present even when one of the field values is
omitted. This is done when either character set, language, or both
are not relevant to the parameter value at hand. This MUST NOT be
done in order to indicate a default character set or language --
parameter field definitions MUST NOT assign a default character set
or language.
4.1. Combining Character Set, Language, and Parameter Continuations
Character set and language information may be combined with the
parameter continuation mechanism. For example:
Content-Type: application/x-stuff
title*0*=us-ascii'en'This%20is%20even%20more%20
title*1*=%2A%2A%2Afun%2A%2A%2A%20
title*2="isn't it!"
Note that:
(1) Language and character set information only appear at
the beginning of a given parameter value.
(2) Continuations do not provide a facility for using more
than one character set or language in the same
parameter value.
(3) A value presented using multiple continuations may
contain a mixture of encoded and unencoded segments.
Freed & Moore Standards Track [Page 5]
RFC 2231 MIME Value and Encoded Word Extensions November 1997
(4) The first segment of a continuation MUST be encoded if
language and character set information are given.
(5) If the first segment of a continued parameter value is
encoded the language and character set field delimiters
MUST be present even when the fields are left blank.
5. Language specification in Encoded Words
RFC 2047 provides support for non-US-ASCII character sets in RFC 822
message header comments, phrases, and any unstructured text field.
This is done by defining an encoded word construct which can appear
in any of these places. Given that these are fields intended for
display, it is sometimes necessary to associate language information
with encoded words as well as just the character set. This
specification extends the definition of an encoded word to allow the
inclusion of such information. This is simply done by suffixing the
character set specification with an asterisk followed by the language
tag. For example:
From: =?US-ASCII*EN?Q?Keith_Moore?= <moore@cs.utk.edu>
6. IMAP4 Handling of Parameter Values
IMAP4 [RFC-2060] servers SHOULD decode parameter value continuations
when generating the BODY and BODYSTRUCTURE fetch attributes.
7. Modifications to MIME ABNF
The ABNF for MIME parameter values given in RFC 2045 is:
parameter := attribute "=" value
attribute := token
; Matching of attributes
; is ALWAYS case-insensitive.
This specification changes this ABNF to:
parameter := regular-parameter / extended-parameter
regular-parameter := regular-parameter-name "=" value
regular-parameter-name := attribute [section]
attribute := 1*attribute-char
Freed & Moore Standards Track [Page 6]
RFC 2231 MIME Value and Encoded Word Extensions November 1997
attribute-char := <any (US-ASCII) CHAR except SPACE, CTLs,
"*", "'", "%", or tspecials>
section := initial-section / other-sections
initial-section := "*0"
other-sections := "*" ("1" / "2" / "3" / "4" / "5" /
"6" / "7" / "8" / "9") *DIGIT)
extended-parameter := (extended-initial-name "="
extended-value) /
(extended-other-names "="
extended-other-values)
extended-initial-name := attribute [initial-section] "*"
extended-other-names := attribute other-sections "*"
extended-initial-value := [charset] "'" [language] "'"
extended-other-values
extended-other-values := *(ext-octet / attribute-char)
ext-octet := "%" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F")
charset := <registered character set name>
language := <registered language tag [RFC-1766]>
The ABNF given in RFC 2047 for encoded-words is:
encoded-word := "=?" charset "?" encoding "?" encoded-text "?="
This specification changes this ABNF to:
encoded-word := "=?" charset ["*" language] "?" encoded-text "?="
8. Character sets which allow specification of language
In the future it is likely that some character sets will provide
facilities for inline language labeling. Such facilities are
inherently more flexible than those defined here as they allow for
language switching in the middle of a string.
Freed & Moore Standards Track [Page 7]
RFC 2231 MIME Value and Encoded Word Extensions November 1997
If and when such facilities are developed they SHOULD be used in
preference to the language labeling facilities specified here. Note
that all the mechanisms defined here allow for the omission of
language labels so as to be able to accommodate this possible future
usage.
9. Security Considerations
This RFC does not discuss security issues and is not believed to
raise any security issues not already endemic in electronic mail and
present in fully conforming implementations of MIME.
10. References
[RFC-822]
Crocker, D., "Standard for the Format of ARPA Internet
Text Messages", STD 11, RFC 822 August 1982.
[RFC-1766]
Alvestrand, H., "Tags for the Identification of
Languages", RFC 1766, March 1995.
[RFC-2045]
Freed, N., and N. Borenstein, "Multipurpose Internet Mail
Extensions (MIME) Part One: Format of Internet Message
Bodies", RFC 2045, December 1996.
[RFC-2046]
Freed, N. and N. Borenstein, "Multipurpose Internet Mail
Extensions (MIME) Part Two: Media Types", RFC 2046,
December 1996.
[RFC-2047]
Moore, K., "Multipurpose Internet Mail Extensions (MIME)
Part Three: Representation of Non-ASCII Text in Internet
Message Headers", RFC 2047, December 1996.
[RFC-2048]
Freed, N., Klensin, J. and J. Postel, "Multipurpose
Internet Mail Extensions (MIME) Part Four: MIME
Registration Procedures", RFC 2048, December 1996.
[RFC-2049]
Freed, N. and N. Borenstein, "Multipurpose Internet Mail
Extensions (MIME) Part Five: Conformance Criteria and
Examples", RFC 2049, December 1996.
Freed & Moore Standards Track [Page 8]
RFC 2231 MIME Value and Encoded Word Extensions November 1997
[RFC-2060]
Crispin, M., "Internet Message Access Protocol - Version
4rev1", RFC 2060, December 1996.
[RFC-2119]
Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", RFC 2119, March 1997.
[RFC-2130]
Weider, C., Preston, C., Simonsen, K., Alvestrand, H.,
Atkinson, R., Crispin, M., and P. Svanberg, "Report from the
IAB Character Set Workshop", RFC 2130, April 1997.
[RFC-2183]
Troost, R., Dorner, S. and K. Moore, "Communicating
Presentation Information in Internet Messages: The
Content-Disposition Header", RFC 2183, August 1997.
11. Authors' Addresses
Ned Freed
Innosoft International, Inc.
1050 Lakes Drive
West Covina, CA 91790
USA
Phone: +1 626 919 3600
Fax: +1 626 919 3614
EMail: ned.freed@innosoft.com
Keith Moore
Computer Science Dept.
University of Tennessee
107 Ayres Hall
Knoxville, TN 37996-1301
USA
EMail: moore@cs.utk.edu
Freed & Moore Standards Track [Page 9]
RFC 2231 MIME Value and Encoded Word Extensions November 1997
12. Full Copyright Statement
Copyright (C) The Internet Society (1997). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.