Commits

Christoffer Niska committed 326a142

Upgraded demo Yii to 1.1.10.

  • Participants
  • Parent commits 537683f
  • Branches bootstrap-2.0.1

Comments (0)

Files changed (52)

File demo/css/styles.css

+body {
+  padding-top: 60px;
+  padding-bottom: 60px;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+  margin-bottom: 0.6em;
+}
+p {
+  font-size: 14px;
+  margin-bottom: 1.6em;
+}
+.hero-unit h1 {
+  margin-bottom: 0.4em;
+}
+.hero-unit p {
+  margin-bottom: 0;
+  text-align: justify;
+}
+.navbar .add-this {
+  background: #EEE;
+  margin: 6px 0;
+  padding: 6px 12px;
+  -webkit-border-radius: 16px;
+  -moz-border-radius: 16px;
+  border-radius: 16px;
+}
+.subnav {
+  border: 1px solid #E5E5E5;
+  font-size: 12px;
+  -webkit-border-radius: 4px;
+  -moz-border-radius: 4px;
+  border-radius: 4px;
+  width: 100%;
+  height: 36px;
+  background-color: #f2f2f2;
+  background-image: -moz-linear-gradient(top, #f5f5f5, #eeeeee);
+  background-image: -ms-linear-gradient(top, #f5f5f5, #eeeeee);
+  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#eeeeee));
+  background-image: -webkit-linear-gradient(top, #f5f5f5, #eeeeee);
+  background-image: -o-linear-gradient(top, #f5f5f5, #eeeeee);
+  background-image: linear-gradient(top, #f5f5f5, #eeeeee);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#eeeeee', GradientType=0);
+}
+.subnav.subnav-fixed {
+  border-color: #D5D5D5;
+  border-width: 1px 0 0;
+  bottom: 0;
+  left: 0;
+  position: fixed;
+  right: 0;
+  z-index: 1030;
+  -webkit-border-radius: 0;
+  -moz-border-radius: 0;
+  border-radius: 0;
+  -webkit-box-shadow: inset 0 1px 0 #ffffff;
+  -moz-box-shadow: inset 0 1px 0 #ffffff;
+  box-shadow: inset 0 1px 0 #ffffff;
+}
+.subnav .nav {
+  margin: 0 auto;
+  max-width: 1170px;
+}
+.subnav .nav  > li > a {
+  margin: 0;
+  padding: 11px;
+  border-left: 1px solid whiteSmoke;
+  border-right: 1px solid #E5E5E5;
+  -webkit-border-radius: 0;
+  -moz-border-radius: 0;
+  border-radius: 0;
+}
+.subnav .nav  > li:first-child > a {
+  border-left: 0;
+}
+.subnav .nav  > li:last-child > a {
+  border-right: 0;
+}
+.subnav .nav  > .active > a, .subnav .nav .action > a:hover {
+  background-color: #E9E9E9;
+  border-right-color: #DDD;
+  color: #777;
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.05);
+  -moz-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.05);
+  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.05);
+}
+footer .powered {
+  color: #888;
+  margin-bottom: 20px;
+}
+footer .copy {
+  color: #666;
+}
+span.required {
+  color: #F00;
+}
+.popover h3.popover-title {
+  margin-bottom: 0;
+}
+section {
+  padding-top: 40px;
+}
+section a.top {
+  display: block;
+  text-align: right;
+}
+#bootNavbar .navbar-inner > .container {
+  width: auto;
+}
+#bootMenu .menuCol {
+  min-height: 140px;
+}
+#bootTabbed .tabbed {
+  margin-bottom: 20px;
+}
+#bootThumbs .list-view {
+  padding-top: 30px;
+}
+#bootActiveForm .form-vertical .control-group > label {
+  font-weight: bold;
+}
+.hl-code {
+  margin-bottom: 20px;
+}
+.hl-code pre {
+  background: #FCFCFC;
+  border-color: #EEE transparent #EEE;
+  font-family: "Menlo", "Consolas", "Courier New", Courier, mono;
+  -webkit-border-radius: 0;
+  -moz-border-radius: 0;
+  border-radius: 0;
+}
+@media (max-width: 980px) {
+  body {
+    padding-top: 0px;
+  }
+}

File demo/yii/YiiBase.php

  * @link http://www.yiiframework.com/
  * @copyright Copyright © 2008-2011 Yii Software LLC
  * @license http://www.yiiframework.com/license/
- * @version $Id: YiiBase.php 3526 2012-01-01 03:18:43Z qiang.xue $
+ * @version $Id: YiiBase.php 3564 2012-02-13 01:29:03Z qiang.xue $
  * @package system
  * @since 1.0
  */
  * you can customize methods of YiiBase.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: YiiBase.php 3526 2012-01-01 03:18:43Z qiang.xue $
+ * @version $Id: YiiBase.php 3564 2012-02-13 01:29:03Z qiang.xue $
  * @package system
  * @since 1.0
  */
 	 */
 	public static function getVersion()
 	{
-		return '1.1.9';
+		return '1.1.10';
 	}
 
 	/**

File demo/yii/base/CErrorHandler.php

  * @property array $error The error details. Null if there is no error.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CErrorHandler.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CErrorHandler.php 3540 2012-01-16 10:17:01Z mdomba $
  * @package system.base
  * @since 1.0
  */
 			if($exception instanceof CHttpException || !YII_DEBUG)
 				$this->render('error',$data);
 			else
-				$this->render('exception',$data);
+			{
+				if($this->isAjaxRequest())
+					$app->displayException($exception);
+				else
+					$this->render('exception',$data);
+			}
 		}
 		else
 			$app->displayException($exception);

File demo/yii/base/CSecurityManager.php

  * @property string $validation
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CSecurityManager.php 3426 2011-10-25 00:01:09Z alexander.makarow $
+ * @version $Id: CSecurityManager.php 3555 2012-02-09 10:29:44Z mdomba $
  * @package system.base
  * @since 1.0
  */
 
 	private $_validationKey;
 	private $_encryptionKey;
+	private $_mbstring;
+
+	public function init()
+	{
+		parent::init();
+		$this->_mbstring=extension_loaded('mbstring');
+	}
 
 	/**
 	 * @return string a randomly generated private key
 	public function encrypt($data,$key=null)
 	{
 		$module=$this->openCryptModule();
-		$key=substr($key===null ? md5($this->getEncryptionKey()) : $key,0,mcrypt_enc_get_key_size($module));
+		$key=$this->substr($key===null ? md5($this->getEncryptionKey()) : $key,0,mcrypt_enc_get_key_size($module));
 		srand();
 		$iv=mcrypt_create_iv(mcrypt_enc_get_iv_size($module), MCRYPT_RAND);
 		mcrypt_generic_init($module,$key,$iv);
 	public function decrypt($data,$key=null)
 	{
 		$module=$this->openCryptModule();
-		$key=substr($key===null ? md5($this->getEncryptionKey()) : $key,0,mcrypt_enc_get_key_size($module));
+		$key=$this->substr($key===null ? md5($this->getEncryptionKey()) : $key,0,mcrypt_enc_get_key_size($module));
 		$ivSize=mcrypt_enc_get_iv_size($module);
-		$iv=substr($data,0,$ivSize);
+		$iv=$this->substr($data,0,$ivSize);
 		mcrypt_generic_init($module,$key,$iv);
-		$decrypted=mdecrypt_generic($module,substr($data,$ivSize));
+		$decrypted=mdecrypt_generic($module,$this->substr($data,$ivSize,$this->strlen($data)));
 		mcrypt_generic_deinit($module);
 		mcrypt_module_close($module);
 		return rtrim($decrypted,"\0");
 		if(extension_loaded('mcrypt'))
 		{
 			if(is_array($this->cryptAlgorithm))
-				$module=call_user_func_array('mcrypt_module_open',$this->cryptAlgorithm);
+				$module=@call_user_func_array('mcrypt_module_open',$this->cryptAlgorithm);
 			else
-				$module=mcrypt_module_open($this->cryptAlgorithm, '', MCRYPT_MODE_CBC, '');
+				$module=@mcrypt_module_open($this->cryptAlgorithm,'', MCRYPT_MODE_CBC,'');
 
 			if($module===false)
 				throw new CException(Yii::t('yii','Failed to initialize the mcrypt module.'));
 	 */
 	public function validateData($data,$key=null)
 	{
-		$len=strlen($this->computeHMAC('test'));
-		if(strlen($data)>=$len)
+		$len=$this->strlen($this->computeHMAC('test'));
+		if($this->strlen($data)>=$len)
 		{
-			$hmac=substr($data,0,$len);
-			$data2=substr($data,$len);
+			$hmac=$this->substr($data,0,$len);
+			$data2=$this->substr($data,$len,$this->strlen($data));
 			return $hmac===$this->computeHMAC($data2,$key)?$data2:false;
 		}
 		else
 			$pack='H32';
 			$func='md5';
 		}
-		if(strlen($key) > 64)
+		if($this->strlen($key) > 64)
 			$key=pack($pack, $func($key));
-		if(strlen($key) < 64)
+		if($this->strlen($key) < 64)
 			$key=str_pad($key, 64, chr(0));
-	    $key=substr($key,0,64);
+		$key=$this->substr($key,0,64);
 		return $func((str_repeat(chr(0x5C), 64) ^ $key) . pack($pack, $func((str_repeat(chr(0x36), 64) ^ $key) . $data)));
 	}
+
+	/**
+	 * Returns the length of the given string.
+	 * If available uses the multibyte string function mb_strlen.
+	 * @param string $string the string being measured for length
+	 * @return int the length of the string
+	 */
+	private function strlen($string)
+	{
+		return $this->_mbstring ? mb_strlen($string,'8bit') : strlen($string);
+	}
+
+	/**
+	 * Returns the portion of string specified by the start and length parameters.
+	 * If available uses the multibyte string function mb_substr
+	 * @param string $string the input string. Must be one character or longer.
+	 * @param int $start the starting position
+	 * @param int $length the desired portion length
+	 * @return string the extracted part of string, or FALSE on failure or an empty string.
+	 */
+	private function substr($string,$start,$length)
+	{
+		return $this->_mbstring ? mb_substr($string,$start,$length,'8bit') : substr($string,$start,$length);
+	}
 }

File demo/yii/console/CConsoleCommand.php

  * the help information for a single action.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CConsoleCommand.php 3501 2011-12-20 20:24:18Z alexander.makarow $
+ * @version $Id: CConsoleCommand.php 3548 2012-01-24 11:42:59Z mdomba $
  * @package system.console
  * @since 1.0
  */
 	public function pluralize($name)
 	{
 		$rules=array(
+			'/move$/i' => 'moves',
+			'/foot$/i' => 'feet',
+			'/child$/i' => 'children',
+			'/human$/i' => 'humans',
+			'/man$/i' => 'men',
+			'/tooth$/i' => 'teeth',
+			'/person$/i' => 'people',
+			'/([m|l])ouse$/i' => '\1ice',
 			'/(x|ch|ss|sh|us|as|is|os)$/i' => '\1es',
+			'/([^aeiouy]|qu)y$/i' => '\1ies',
 			'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
-			'/(m)an$/i' => '\1en',
-			'/(child)$/i' => '\1ren',
-			'/(r)y$/i' => '\1ies',
+			'/(shea|lea|loa|thie)f$/i' => '\1ves',
+			'/([ti])um$/i' => '\1a',
+			'/(tomat|potat|ech|her|vet)o$/i' => '\1oes',
+			'/(bu)s$/i' => '\1ses',
+			'/(ax|test)is$/i' => '\1es',
 			'/s$/' => 's',
 		);
 		foreach($rules as $rule=>$replacement)

File demo/yii/db/ar/CActiveFinder.php

  * {@link CActiveRecord}.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveFinder.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveFinder.php 3562 2012-02-13 01:27:06Z qiang.xue $
  * @package system.db.ar
  * @since 1.0
  */
  * CJoinElement represents a tree node in the join tree created by {@link CActiveFinder}.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveFinder.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveFinder.php 3562 2012-02-13 01:27:06Z qiang.xue $
  * @package system.db.ar
  * @since 1.0
  */
 	{
 		$schema=$this->_builder->getSchema();
 		$joins=array();
+		if(is_string($fks))
+			$fks=preg_split('/\s*,\s*/',$fks,-1,PREG_SPLIT_NO_EMPTY);
 		foreach($fks as $i=>$fk)
 		{
 			if(!is_int($i))
  * CJoinQuery represents a JOIN SQL statement.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveFinder.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveFinder.php 3562 2012-02-13 01:27:06Z qiang.xue $
  * @package system.db.ar
  * @since 1.0
  */
  * CStatElement represents STAT join element for {@link CActiveFinder}.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveFinder.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveFinder.php 3562 2012-02-13 01:27:06Z qiang.xue $
  * @package system.db.ar
  */
 class CStatElement

File demo/yii/db/ar/CActiveRecord.php

  * @property string $tableAlias The default table alias.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveRecord.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveRecord.php 3533 2012-01-08 22:07:55Z mdomba $
  * @package system.db.ar
  * @since 1.0
  */
 	 * Note, for composite foreign keys, they can be either listed together, separated by commas or specified as an array
 	 * in format of array('key1','key2'). In case you need to specify custom PK->FK association you can define it as
 	 * array('fk'=>'pk'). For composite keys it will be array('fk_c1'=>'pk_с1','fk_c2'=>'pk_c2').
-	 * and for foreign keys used in MANY_MANY relation, the joining table must be declared as well
+	 * For foreign keys used in MANY_MANY relation, the joining table must be declared as well
 	 * (e.g. 'join_table(fk1, fk2)').
 	 *
 	 * Additional options may be specified as name-value pairs in the rest array elements:
 /**
  * CBaseActiveRelation is the base class for all active relations.
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveRecord.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveRecord.php 3533 2012-01-08 22:07:55Z mdomba $
  * @package system.db.ar
  */
 class CBaseActiveRelation extends CComponent
 /**
  * CStatRelation represents a statistical relational query.
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveRecord.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveRecord.php 3533 2012-01-08 22:07:55Z mdomba $
  * @package system.db.ar
  */
 class CStatRelation extends CBaseActiveRelation
 /**
  * CActiveRelation is the base class for representing active relations that bring back related objects.
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveRecord.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveRecord.php 3533 2012-01-08 22:07:55Z mdomba $
  * @package system.db.ar
  * @since 1.0
  */
 /**
  * CBelongsToRelation represents the parameters specifying a BELONGS_TO relation.
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveRecord.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveRecord.php 3533 2012-01-08 22:07:55Z mdomba $
  * @package system.db.ar
  * @since 1.0
  */
 /**
  * CHasOneRelation represents the parameters specifying a HAS_ONE relation.
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveRecord.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveRecord.php 3533 2012-01-08 22:07:55Z mdomba $
  * @package system.db.ar
  * @since 1.0
  */
 /**
  * CHasManyRelation represents the parameters specifying a HAS_MANY relation.
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveRecord.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveRecord.php 3533 2012-01-08 22:07:55Z mdomba $
  * @package system.db.ar
  * @since 1.0
  */
 /**
  * CManyManyRelation represents the parameters specifying a MANY_MANY relation.
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveRecord.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveRecord.php 3533 2012-01-08 22:07:55Z mdomba $
  * @package system.db.ar
  * @since 1.0
  */
  * CActiveRecordMetaData represents the meta-data for an Active Record class.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CActiveRecord.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CActiveRecord.php 3533 2012-01-08 22:07:55Z mdomba $
  * @package system.db.ar
  * @since 1.0
  */

File demo/yii/db/schema/CDbColumnSchema.php

  * CDbColumnSchema class describes the column meta data of a database table.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CDbColumnSchema.php 3099 2011-03-19 01:26:47Z qiang.xue $
+ * @version $Id: CDbColumnSchema.php 3558 2012-02-09 17:39:04Z alexander.makarow $
  * @package system.db.schema
  * @since 1.0
  */
 	{
 		if(gettype($value)===$this->type || $value===null || $value instanceof CDbExpression)
 			return $value;
-		if($value==='')
+		if($value==='' && $this->allowNull)
 			return $this->type==='string' ? '' : null;
 		switch($this->type)
 		{

File demo/yii/gii/CCodeModel.php

  * @property string $stickyFile The file path that stores the sticky attribute values.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CCodeModel.php 3426 2011-10-25 00:01:09Z alexander.makarow $
+ * @version $Id: CCodeModel.php 3547 2012-01-24 10:07:28Z mdomba $
  * @package system.gii
  * @since 1.1.2
  */
 	const STATUS_SUCCESS=3;
 	const STATUS_ERROR=4;
 
+	static $keywords=array(
+		'__class__',
+		'__dir__',
+		'__file__',
+		'__function__',
+		'__line__',
+		'__method__',
+		'__namespace__',
+		'abstract',
+		'and',
+		'array',
+		'as',
+		'break',
+		'case',
+		'catch',
+		'cfunction',
+		'class',
+		'clone',
+		'const',
+		'continue',
+		'declare',
+		'default',
+		'die',
+		'do',
+		'echo',
+		'else',
+		'elseif',
+		'empty',
+		'enddeclare',
+		'endfor',
+		'endforeach',
+		'endif',
+		'endswitch',
+		'endwhile',
+		'eval',
+		'exception',
+		'exit',
+		'extends',
+		'final',
+		'final',
+		'for',
+		'foreach',
+		'function',
+		'global',
+		'goto',
+		'if',
+		'implements',
+		'include',
+		'include_once',
+		'instanceof',
+		'interface',
+		'isset',
+		'list',
+		'namespace',
+		'new',
+		'old_function',
+		'or',
+		'parent',
+		'php_user_filter',
+		'print',
+		'private',
+		'protected',
+		'public',
+		'require',
+		'require_once',
+		'return',
+		'static',
+		'switch',
+		'this',
+		'throw',
+		'try',
+		'unset',
+		'use',
+		'var',
+		'while',
+		'xor',
+	);
+
 	/**
 	 * @var array user confirmations on whether to overwrite existing code files with the newly generated ones.
 	 * The value of this property is internally managed by this class and {@link CCodeGenerator}.
 	public function pluralize($name)
 	{
 		$rules=array(
+			'/move$/i' => 'moves',
+			'/foot$/i' => 'feet',
+			'/child$/i' => 'children',
+			'/human$/i' => 'humans',
+			'/man$/i' => 'men',
+			'/tooth$/i' => 'teeth',
+			'/person$/i' => 'people',
+			'/([m|l])ouse$/i' => '\1ice',
 			'/(x|ch|ss|sh|us|as|is|os)$/i' => '\1es',
+			'/([^aeiouy]|qu)y$/i' => '\1ies',
 			'/(?:([^f])fe|([lr])f)$/i' => '\1\2ves',
-			'/(m)an$/i' => '\1en',
-			'/(child)$/i' => '\1ren',
-			'/(r|t)y$/i' => '\1ies',
+			'/(shea|lea|loa|thie)f$/i' => '\1ves',
+			'/([ti])um$/i' => '\1a',
+			'/(tomat|potat|ech|her|vet)o$/i' => '\1oes',
+			'/(bu)s$/i' => '\1ses',
+			'/(ax|test)is$/i' => '\1es',
 			'/s$/' => 's',
 		);
 		foreach($rules as $rule=>$replacement)
 	 */
 	public function validateReservedWord($attribute,$params)
 	{
-		static $keywords=array(
-			'__class__',
-			'__dir__',
-			'__file__',
-			'__function__',
-			'__line__',
-			'__method__',
-			'__namespace__',
-			'abstract',
-			'and',
-			'array',
-			'as',
-			'break',
-			'case',
-			'catch',
-			'cfunction',
-			'class',
-			'clone',
-			'const',
-			'continue',
-			'declare',
-			'default',
-			'die',
-			'do',
-			'echo',
-			'else',
-			'elseif',
-			'empty',
-			'enddeclare',
-			'endfor',
-			'endforeach',
-			'endif',
-			'endswitch',
-			'endwhile',
-			'eval',
-			'exception',
-			'exit',
-			'extends',
-			'final',
-			'final',
-			'for',
-			'foreach',
-			'function',
-			'global',
-			'goto',
-			'if',
-			'implements',
-			'include',
-			'include_once',
-			'instanceof',
-			'interface',
-			'isset',
-			'list',
-			'namespace',
-			'new',
-			'old_function',
-			'or',
-			'parent',
-			'php_user_filter',
-			'print',
-			'private',
-			'protected',
-			'public',
-			'require',
-			'require_once',
-			'return',
-			'static',
-			'switch',
-			'this',
-			'throw',
-			'try',
-			'unset',
-			'use',
-			'var',
-			'while',
-			'xor',
-		);
 		$value=$this->$attribute;
-		if(in_array(strtolower($value),$keywords))
+		if(in_array(strtolower($value),self::$keywords))
 			$this->addError($attribute, $this->getAttributeLabel($attribute).' cannot take a reserved PHP keyword.');
 	}
 }

File demo/yii/gii/generators/model/ModelCode.php

 
 	public function validateTableName($attribute,$params)
 	{
+		$invalidTables=array();
 		$invalidColumns=array();
 
 		if($this->tableName[strlen($this->tableName)-1]==='*')
 			{
 				if($this->tablePrefix=='' || strpos($table->name,$this->tablePrefix)===0)
 				{
+					if(in_array(strtolower($table->name),self::$keywords))
+						$invalidTables[]=$table->name;
 					if(($invalidColumn=$this->checkColumns($table))!==null)
 						$invalidColumns[]=$invalidColumn;
 				}
 					$invalidColumns[]=$invalidColumn;
 		}
 
+		if($invalidTables!=array())
+			$this->addError('tableName', 'Model class cannot take a reserved PHP keyword! Table name: '.implode(', ', $invalidTables).".");
 		if($invalidColumns!=array())
-			$this->addError('tableName',"Column names that does not follow PHP variable naming convention: ".implode(', ', $invalidColumns)."."	);
+			$this->addError('tableName', 'Column names that does not follow PHP variable naming convention: '.implode(', ', $invalidColumns).".");
 	}
 
 	/*

File demo/yii/messages/it/yii.php

  * @version $Id: $
  */
 return array (
-  'CHttpRequest is unable to determine the path info of the request.' => 'CHttpRequest non pu� determinare le informazioni sul path della richiesta.',
-  'CHttpRequest is unable to determine the request URI.' => 'CHttpRequest non pu� determinare l\'URI richiesto.',
+  'CHttpRequest is unable to determine the path info of the request.' => 'CHttpRequest non può determinare le informazioni sul path della richiesta.',
+  'CHttpRequest is unable to determine the request URI.' => 'CHttpRequest non può determinare l\'URI richiesto.',
   'CXCache requires PHP XCache extension to be loaded.' => 'CXCache richiede che l\'estensione XCache di PHP sia caricata.',
-  'Cannot add "{name}" as a child of itself.' => 'Non si pu� aggiungere "{name}" come figlio di se stesso.',
-  'The column "{column}" is not a foreign key in table "{table}".' => 'La colonna "{column}" non � una chiave esterna nella tabella  "{table}".',
+  'Cannot add "{name}" as a child of itself.' => 'Non si può aggiungere "{name}" come figlio di se stesso.',
+  'The column "{column}" is not a foreign key in table "{table}".' => 'La colonna "{column}" non è una chiave esterna nella tabella  "{table}".',
   '{class} does not have attribute "{attribute}".' => '{class} non ha un attributo "{attribute}".',
   '{class} does not have relation "{name}".' => '{class} non ha una relazione "{name}".',
   '{class} does not support fetching all table names.' => '{class} non supporta l\'ottenimento di tutti i nomi delle tabelle.',
-  '"{path}" is not a valid directory.' => '"{path}" non  una cartella valida.',
+  '"{path}" is not a valid directory.' => '"{path}" non è una cartella valida.',
   'Active Record requires a "db" CDbConnection application component.' => 'Active Record richiede un componente applicativo "db" di tipo CDbConnection.',
   'Active record "{class}" has an invalid configuration for relation "{relation}". It must specify the relation type, the related active record class and the foreign key.' => 'L\'active record "{class}" ha una configurazione non valida per la relazione "{relation}". Devono essere specificati il tipo di relazione, l\'active record relazionato e la chiave esterna.',
   'Active record "{class}" is trying to select an invalid column "{column}". Note, the column must exist in the table or be an expression with alias.' => 'Active record "{class}" sta cercando di selezionare la colonna non valida "{column}". Nota, la colonna deve esistere nella tabella o essere un\'espressione con alias.',
-  'Alias "{alias}" is invalid. Make sure it points to an existing directory or file.' => 'L\'alias "{alias}" non � valido. Verificare che punti ad una cartella o file esistente.',
-  'Application base path "{path}" is not a valid directory.' => 'Il percorso base dell\'applicazione "{path}" non � una cartella valida.',
-  'Application runtime path "{path}" is not valid. Please make sure it is a directory writable by the Web server process.' => 'Il percorso di runtime dell\'applicazione "{path}" non � valido. Verificare che sia una cartella con permesso di scrittura per il processo del Web server.',
-  'Authorization item "{item}" has already been assigned to user "{user}".' => 'L\'elemento di autorizzazione "{item}" � stato assegnato all\'utente "{user}".',
+  'Alias "{alias}" is invalid. Make sure it points to an existing directory or file.' => 'L\'alias "{alias}" non è valido. Verificare che punti ad una cartella o file esistente.',
+  'Application base path "{path}" is not a valid directory.' => 'Il percorso base dell\'applicazione "{path}" non è una cartella valida.',
+  'Application runtime path "{path}" is not valid. Please make sure it is a directory writable by the Web server process.' => 'Il percorso di runtime dell\'applicazione "{path}" non è valido. Verificare che sia una cartella con permesso di scrittura per il processo del Web server.',
+  'Authorization item "{item}" has already been assigned to user "{user}".' => 'L\'elemento di autorizzazione "{item}" è stato assegnato all\'utente "{user}".',
   'CApcCache requires PHP apc extension to be loaded.' => 'CApcCache richiede che l\'estensione apc di PHP sia caricata.',
-  'CAssetManager.basePath "{path}" is invalid. Please make sure the directory exists and is writable by the Web server process.' => 'CAssetManager.basePath "{path}" non � valido.  Verificare che la cartella esista e abbia permesso di scrittura per il processo del Web server.',
-  'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.' => 'CCacheHttpSession.cacheID non � valido. Verifica che "{id}" si riferisca ad un componente applicativo cache valido.',
-  'CCaptchaValidator.action "{id}" is invalid. Unable to find such an action in the current controller.' => 'CCaptchaValidator.action "{id}" non � valido. Non si � potuto trovare tale azione nell\'attuale controller.',
-  'CDbAuthManager.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => 'CDbAuthManager.connectionID "{id}" non � valido. Verificare che si riferisca all\'ID di un componente applicativo CDbConnection.',
+  'CAssetManager.basePath "{path}" is invalid. Please make sure the directory exists and is writable by the Web server process.' => 'CAssetManager.basePath "{path}" non è valido.  Verificare che la cartella esista e abbia permesso di scrittura per il processo del Web server.',
+  'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.' => 'CCacheHttpSession.cacheID non è valido. Verifica che "{id}" si riferisca ad un componente applicativo cache valido.',
+  'CCaptchaValidator.action "{id}" is invalid. Unable to find such an action in the current controller.' => 'CCaptchaValidator.action "{id}" non è valido. Non si è potuto trovare tale azione nell\'attuale controller.',
+  'CDbAuthManager.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => 'CDbAuthManager.connectionID "{id}" non è valido. Verificare che si riferisca all\'ID di un componente applicativo CDbConnection.',
   'CDbCache.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => 'CDbCache.connectionID "{id}" non valido. Verificare che si riferisca all\'ID di un componente applicativo CDbConnection.',
-  'CDbCacheDependency.sql cannot be empty.' => 'CDbCacheDependency.sql non pu essere vuoto.',
+  'CDbCacheDependency.sql cannot be empty.' => 'CDbCacheDependency.sql non può essere vuoto.',
   'CDbCommand failed to execute the SQL statement: {error}' => 'CDbCommand ha riportato un errore nell\'esecuzione della query SQL: {error}',
   'CDbCommand failed to prepare the SQL statement: {error}' => 'CDbCommand ha riportato un errore nella preparazione della query SQL: {error}',
   'CDbConnection does not support reading schema for {driver} database.' => 'CDbConnection non supporta la lettura dello schema per DB {driver}.',
   'CDbConnection failed to open the DB connection: {error}' => 'CDbConnection ha riportato un errore nell\'apertura della connessione al DB: {error}',
-  'CDbConnection is inactive and cannot perform any DB operations.' => 'CDbConnection � inattiva e non pu� realizzare alcuna operazione con il DB.',
-  'CDbConnection.connectionString cannot be empty.' => 'CDbConnection.connectionString non pu� essere vuoto',
-  'CDbDataReader cannot rewind. It is a forward-only reader.' => 'CDbDataReader non pu� tornare indietro. E\' un lettore che pu� solo avanzare.',
+  'CDbConnection is inactive and cannot perform any DB operations.' => 'CDbConnection è inattiva e non può realizzare alcuna operazione con il DB.',
+  'CDbConnection.connectionString cannot be empty.' => 'CDbConnection.connectionString non può essere vuoto',
+  'CDbDataReader cannot rewind. It is a forward-only reader.' => 'CDbDataReader non può tornare indietro. E\' un lettore che può solo avanzare.',
   'CDbHttpSession.connectionID "{id}" is invalid. Please make sure it refers to the ID of a CDbConnection application component.' => 'CDbHttpSession.connectionID "{id}" non valido. Verificare che si riferisca all\'ID di un componente applicativo CDbConnection',
   'CDbLogRoute requires database table "{table}" to store log messages.' => 'CDbLogRoute richiede la tabella "{table}" del DB per salvare i messaggi di log.',
   'CDbLogRoute.connectionID "{id}" does not point to a valid CDbConnection application component.' => 'CDbLogRoute.connectionID "{id}" non punta ad un componente applicativo CDbConnection valido.',
-  'CDbMessageSource.connectionID is invalid. Please make sure "{id}" refers to a valid database application component.' => 'CDbMessageSource.connectionID non � valido. Verificare che "{id}" si riferisca ad un componente applicativo DB valido.',
-  'CDbTransaction is inactive and cannot perform commit or roll back operations.' => 'CDbTransaction � inattiva e non pu� realizzare le operazioni di commit e roll back.',
-  'CDirectoryCacheDependency.directory cannot be empty.' => 'CDirectoryCacheDependency.directory non pu� essere vuoto.',
-  'CFileCacheDependency.fileName cannot be empty.' => 'CFileCacheDependency.fileName non pu� essere vuoto.',
+  'CDbMessageSource.connectionID is invalid. Please make sure "{id}" refers to a valid database application component.' => 'CDbMessageSource.connectionID non è valido. Verificare che "{id}" si riferisca ad un componente applicativo DB valido.',
+  'CDbTransaction is inactive and cannot perform commit or roll back operations.' => 'CDbTransaction è inattiva e non può realizzare le operazioni di commit e roll back.',
+  'CDirectoryCacheDependency.directory cannot be empty.' => 'CDirectoryCacheDependency.directory non può essere vuoto.',
+  'CFileCacheDependency.fileName cannot be empty.' => 'CFileCacheDependency.fileName non può essere vuoto.',
   'CFileLogRoute.logPath "{path}" does not point to a valid directory. Make sure the directory exists and is writable by the Web server process.' => 'CFileLogRoute.logPath "{path}" no punta ad una cartella valida. Verificare che la cartella esista e abbia permesso di scrittura per il processo del Web server.',
-  'CFilterChain can only take objects implementing the IFilter interface.' => 'CFilterChain pu� solamente prendere oggetti che implementino l\'interfaccia IFilter.',
-  'CFlexWidget.baseUrl cannot be empty.' => 'CFlexWidget.baseUrl non pu� essere vuoto.',
-  'CFlexWidget.name cannot be empty.' => 'CFlexWidget.name non pu� essere vuoto.',
-  'CGlobalStateCacheDependency.stateName cannot be empty.' => 'CGlobalStateCacheDependency.stateName non pu� essere vuoto.',
-  'CHttpCookieCollection can only hold CHttpCookie objects.' => 'CHttpCookieCollection pu� contenere solo oggetti CHttpCookie.',
-  'CHttpRequest is unable to determine the entry script URL.' => 'CHttpRequest non pu� determinare l\'URL dello script di entry.',
-  'CHttpSession.cookieMode can only be "none", "allow" or "only".' => 'CHttpSession.cookieMode pu� essere solo "none", "allow" o "only".',
-  'CHttpSession.gcProbability "{value}" is invalid. It must be an integer between 0 and 100.' => 'CHttpSession.gcProbability "{value}" non � valido. Deve essere un intero compreso tra 0 e 100.',
-  'CHttpSession.savePath "{path}" is not a valid directory.' => 'CHttpSession.savePath "{path}" non � una cartella valida.',
+  'CFilterChain can only take objects implementing the IFilter interface.' => 'CFilterChain può solamente prendere oggetti che implementino l\'interfaccia IFilter.',
+  'CFlexWidget.baseUrl cannot be empty.' => 'CFlexWidget.baseUrl non può essere vuoto.',
+  'CFlexWidget.name cannot be empty.' => 'CFlexWidget.name non può essere vuoto.',
+  'CGlobalStateCacheDependency.stateName cannot be empty.' => 'CGlobalStateCacheDependency.stateName non può essere vuoto.',
+  'CHttpCookieCollection can only hold CHttpCookie objects.' => 'CHttpCookieCollection può contenere solo oggetti CHttpCookie.',
+  'CHttpRequest is unable to determine the entry script URL.' => 'CHttpRequest non può determinare l\'URL dello script di entry.',
+  'CHttpSession.cookieMode can only be "none", "allow" or "only".' => 'CHttpSession.cookieMode può essere solo "none", "allow" o "only".',
+  'CHttpSession.gcProbability "{value}" is invalid. It must be an integer between 0 and 100.' => 'CHttpSession.gcProbability "{value}" non è valido. Deve essere un intero compreso tra 0 e 100.',
+  'CHttpSession.savePath "{path}" is not a valid directory.' => 'CHttpSession.savePath "{path}" non è una cartella valida.',
   'CMemCache requires PHP memcache extension to be loaded.' => 'CMemCache richiede che l\'estensione memcache di PHP sia caricata.',
   'CMemCache server configuration must be an array.' => 'La configurazione del server CMemCache deve essere un array.',
   'CMemCache server configuration must have "host" value.' => 'La configurazione del server CMemCache deve specificare un valore "host".',
-  'CMultiFileUpload.name is required.' => 'CMultiFileUpload.name  richiesto',
+  'CMultiFileUpload.name is required.' => 'CMultiFileUpload.name è richiesto',
   'CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.' => 'CProfileLogRoute ha trovato un blocco di codice "{token}" disallineato. Verificare che le chiamate a Yii::beginProfile() e a Yii::endProfile() siano correttamente annidate.',
-  'CProfileLogRoute.report "{report}" is invalid. Valid values include "summary" and "callstack".' => 'CProfileLogRoute.report "{report}" non � valido. I valori validi includono "summary" e "callstack".',
+  'CProfileLogRoute.report "{report}" is invalid. Valid values include "summary" and "callstack".' => 'CProfileLogRoute.report "{report}" non è valido. I valori validi includono "summary" e "callstack".',
   'CSecurityManager requires PHP mcrypt extension to be loaded in order to use data encryption feature.' => 'CSecurityManager richiede che l\'estensione mcrypt di PHP sia caricata per utilizzare l\'opzione di crittografia dei dati.',
-  'CSecurityManager.encryptionKey cannot be empty.' => 'CSecurityManager.encryptionKey non pu essere vuoto.',
+  'CSecurityManager.encryptionKey cannot be empty.' => 'CSecurityManager.encryptionKey non può essere vuoto.',
   'CSecurityManager.validation must be either "MD5" or "SHA1".' => 'CSecurityManager.validation deve essere "MD5" o "SHA1".',
-  'CSecurityManager.validationKey cannot be empty.' => 'CSecurityManager.validationKey non pu� essere vuoto.',
-  'CTypedList<{type}> can only hold objects of {type} class.' => 'CTypedList<{type}> pu� contenere solo oggetti della classe {type}.',
+  'CSecurityManager.validationKey cannot be empty.' => 'CSecurityManager.validationKey non può essere vuoto.',
+  'CTypedList<{type}> can only hold objects of {type} class.' => 'CTypedList<{type}> può contenere solo oggetti della classe {type}.',
   'CUrlManager.UrlFormat must be either "path" or "get".' => 'CUrlManager.UrlFormat deve essere "path" o "get".',
   'Cache table "{tableName}" does not exist.' => 'La tabella di cache "{tableName}" non esiste.',
-  'Cannot add "{child}" as a child of "{name}". A loop has been detected.' => 'Non si pu� aggiungere "{child}" come figlio di "{name}". E\' stato individuato un ciclo.',
-  'Cannot add "{child}" as a child of "{parent}". A loop has been detected.' => 'Non si pu� aggiungere "{child}" come figlio di "{parent}". E\' stato individuato un ciclo.',
-  'Cannot add an item of type "{child}" to an item of type "{parent}".' => 'Non si pu� aggiungere un elemento di tipo "{child}" ad uno di tipo "{parent}".',
+  'Cannot add "{child}" as a child of "{name}". A loop has been detected.' => 'Non si può aggiungere "{child}" come figlio di "{name}". E\' stato individuato un ciclo.',
+  'Cannot add "{child}" as a child of "{parent}". A loop has been detected.' => 'Non si può aggiungere "{child}" come figlio di "{parent}". E\' stato individuato un ciclo.',
+  'Cannot add an item of type "{child}" to an item of type "{parent}".' => 'Non si può aggiungere un elemento di tipo "{child}" ad uno di tipo "{parent}".',
   'Either "{parent}" or "{child}" does not exist.' => '"{parent}" o "{child}" non esistono',
   'Error: Table "{table}" does not have a primary key.' => 'Errore: La tabella "{table}" non ha una chiave primaria.',
-  'Error: Table "{table}" has a composite primary key which is not supported by crud command.' => 'Errore: La tabella "{table}" non ha una chiave primaria composta che non � supportata dal comando crud.',
-  'Event "{class}.{event}" is attached with an invalid handler "{handler}".' => 'L\'evento "{class}"."{event}" � associato ad un handler "{handler}" non valido.',
-  'Event "{class}.{event}" is not defined.' => 'L\'evento "{class}"."{event}" non � definito.',
+  'Error: Table "{table}" has a composite primary key which is not supported by crud command.' => 'Errore: La tabella "{table}" non ha una chiave primaria composta che non è supportata dal comando crud.',
+  'Event "{class}.{event}" is attached with an invalid handler "{handler}".' => 'L\'evento "{class}"."{event}" è associato ad un handler "{handler}" non valido.',
+  'Event "{class}.{event}" is not defined.' => 'L\'evento "{class}"."{event}" non è definito.',
   'Failed to write the uploaded file "{file}" to disk.' => 'Fallimento nella scrittura su disco del file caricato "{file}".',
   'File upload was stopped by extension.' => 'Carimento del file "{file}" interrotto a causa dell\'estensione.',
-  'Filter "{filter}" is invalid. Controller "{class}" does have the filter method "filter{filter}".' => 'Il filtro "{filter} non � valido. Il controller "{class}" non contiene il metodo di filter "filter{filter}".',
+  'Filter "{filter}" is invalid. Controller "{class}" does have the filter method "filter{filter}".' => 'Il filtro "{filter} non è valido. Il controller "{class}" non contiene il metodo di filter "filter{filter}".',
   'Get a new code' => 'Procurasi un codice nuovo',
   'Invalid MO file revision: {revision}.' => 'Revisione del file MO non valida: {revision}.',
   'Invalid MO file: {file} (magic: {magic}).' => 'File MO non valido: {file} (magic: {magic}).',
   'Invalid enumerable value "{value}". Please make sure it is among ({enum}).' => 'Valore enumerabile non valido "{value}". Verificare che sia entro ({enum}).',
   'List data must be an array or an object implementing Traversable.' => 'I dati della lista devono essere un array o un oggetto che implementi Traversable.',
-  'List index "{index}" is out of bound.' => 'L\'indice della lista "{index}"  fuori dai limiti.',
+  'List index "{index}" is out of bound.' => 'L\'indice della lista "{index}" è fuori dai limiti.',
   'Login Required' => 'Login richiesto.',
   'Map data must be an array or an object implementing Traversable.' => 'I dati di map devono essere un array o un oggetto che implementi Traversable.',
   'Missing the temporary folder to store the uploaded file "{file}".' => 'Impossibile trovare la cartella temporanea per effettuare il carimento del file "{file}".',
-  'No columns are being updated for table "{table}".' => 'Nessuna colonna � stata aggiornata per la tabella "{table}".',
-  'No counter columns are being updated for table "{table}".' => 'Nessuna contatore di colonna � stata aggiornata per la tabella "{table}".',
+  'No columns are being updated for table "{table}".' => 'Nessuna colonna è stata aggiornata per la tabella "{table}".',
+  'No counter columns are being updated for table "{table}".' => 'Nessuna contatore di colonna è stata aggiornata per la tabella "{table}".',
   'Object configuration must be an array containing a "class" element.' => 'La configurazione dell\'oggetto deve essere un array contenente un elemento "class".',
   'Please fix the following input errors:' => 'Per favore, correggere i seguenti errori di input:',
-  'Property "{class}.{property}" is not defined.' => 'La propriet� "{class}"."{property}" non � definita.',
-  'Property "{class}.{property}" is read only.' => 'La propriet� "{class}"."{property}" � di sola lettura.',
+  'Property "{class}.{property}" is not defined.' => 'La proprietà "{class}"."{property}" non è definita.',
+  'Property "{class}.{property}" is read only.' => 'La proprietà "{class}"."{property}" è di sola lettura.',
   'Queue data must be an array or an object implementing Traversable.' => 'I dati della coda devono essere un array o un oggetto che implementi Traversable.',
-  'Relation "{name}" is not defined in active record class "{class}".' => 'La relazione "{name}" non � definita nella classe active record "{class}".',
+  'Relation "{name}" is not defined in active record class "{class}".' => 'La relazione "{name}" non è definita nella classe active record "{class}".',
   'Stack data must be an array or an object implementing Traversable.' => 'I dati della pila devono essere un array o un oggetto che implementi Traversable.',
   'Table "{table}" does not have a column named "{column}".' => 'La tabella "{table}" non contiene la colonna "{column}".',
   'Table "{table}" does not have a primary key defined.' => 'La tabella "{table}" non ha definita nessuna chiave primaria.',
-  'The "filter" property must be specified with a valid callback.' => 'La propriet� "filter" deve essere specificata con un callback valido.',
-  'The "pattern" property must be specified with a valid regular expression.' => 'La propriet� "pattern" deve essere specificata come una espressione regolare valida.',
-  'The "view" property is required.' => 'La propriet� "view" � richiesta.',
-  'The CSRF token could not be verified.' => 'Il token CSRF non pu� essere verificato.',
-  'The URL pattern "{pattern}" for route "{route}" is not a valid regular expression.' => 'Il formato dell\'URL "{pattern}" per il percorso "{route}" non � un\'espressione regolare valida.',
-  'The active record cannot be deleted because it is new.' => 'L\'active record non pu� essere eliminato perch� � nuovo.',
-  'The active record cannot be inserted to database because it is not new.' => 'L\'active record non pu� essere inserito nel DB perch� non � nuovo.',
-  'The active record cannot be updated because it is new.' => 'L\'active record non pu� essere aggiornato perch� � nuovo.',
+  'The "filter" property must be specified with a valid callback.' => 'La proprietà "filter" deve essere specificata con un callback valido.',
+  'The "pattern" property must be specified with a valid regular expression.' => 'La proprietà "pattern" deve essere specificata come una espressione regolare valida.',
+  'The "view" property is required.' => 'La proprietà "view" è richiesta.',
+  'The CSRF token could not be verified.' => 'Il token CSRF non può essere verificato.',
+  'The URL pattern "{pattern}" for route "{route}" is not a valid regular expression.' => 'Il formato dell\'URL "{pattern}" per il percorso "{route}" non è un\'espressione regolare valida.',
+  'The active record cannot be deleted because it is new.' => 'L\'active record non può essere eliminato perchè è nuovo.',
+  'The active record cannot be inserted to database because it is not new.' => 'L\'active record non può essere inserito nel DB perchè non è nuovo.',
+  'The active record cannot be updated because it is new.' => 'L\'active record non può essere aggiornato perchè è nuovo.',
   'The asset "{asset}" to be pulished does not exist.' => 'El asset "{asset} che deve essere pubblicato non esiste.',
-  'The command path "{path}" is not a valid directory.' => 'Il percorso del comando "{path}" non � una cartella valida.',
-  'The controller path "{path}" is not a valid directory.' => 'Il percorso del controller "{path}" non � una cartella valida.',
-  'The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.' => 'Il caricamento del file "{file}" non pu� essere effettuato. Solo i file con le seguenti estensioni sono permessi: {extensions}.',
-  'The file "{file}" is too large. Its size cannot exceed {limit} bytes.' => 'Il file "{file}" � troppo grande. La dimensione non pu� superare {limit} bytes.',
-  'The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.' => 'Il file "{file}" � troppo piccol. La dimensione deve essere di almeno {limit} bytes.',
-  'The file "{file}" was only partially uploaded.' => 'Il file "{file}" � stato caricato parzialmente.',
+  'The command path "{path}" is not a valid directory.' => 'Il percorso del comando "{path}" non è una cartella valida.',
+  'The controller path "{path}" is not a valid directory.' => 'Il percorso del controller "{path}" non è una cartella valida.',
+  'The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.' => 'Il caricamento del file "{file}" non può essere effettuato. Solo i file con le seguenti estensioni sono permessi: {extensions}.',
+  'The file "{file}" is too large. Its size cannot exceed {limit} bytes.' => 'Il file "{file}" è troppo grande. La dimensione non può superare {limit} bytes.',
+  'The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.' => 'Il file "{file}" è troppo piccol. La dimensione deve essere di almeno {limit} bytes.',
+  'The file "{file}" was only partially uploaded.' => 'Il file "{file}" è stato caricato parzialmente.',
   'The first element in a filter configuration must be the filter class.' => 'Il primo elemento nella configurazione di un filtro deve essere la classe del filtro.',
   'The item "{name}" does not exist.' => 'L\'elemento "{name}" non esiste.',
-  'The item "{parent}" already has a child "{child}".' => 'L\'elemento "{parent}" contiene gi� un figlio "{child}".',
-  'The layout path "{path}" is not a valid directory.' => 'Il percorso del layout "{path}" non � una cartella valida.',
-  'The list is read only.' => 'La lista � di sola lettura',
-  'The map is read only.' => 'Il map � di sola lettura',
+  'The item "{parent}" already has a child "{child}".' => 'L\'elemento "{parent}" contiene già un figlio "{child}".',
+  'The layout path "{path}" is not a valid directory.' => 'Il percorso del layout "{path}" non è una cartella valida.',
+  'The list is read only.' => 'La lista è di sola lettura',
+  'The map is read only.' => 'Il map è di sola lettura',
   'The pattern for 12 hour format must be "h" or "hh".' => 'Il formato per le 12 ore deve essere "h" o "hh".',
   'The pattern for 24 hour format must be "H" or "HH".' => 'Il formato per le 24 ore deve essere "H" o "HH".',
   'The pattern for AM/PM marker must be "a".' => 'Il formato per l\'indicatore AM/PM deve essere "a".',
   'The pattern for time zone must be "z" or "v".' => 'Il formato per la timezone deve essere "z" o "v".',
   'The pattern for week in month must be "W".' => 'Il formato per la settimana nel mese deve essere "W".',
   'The pattern for week in year must be "w".' => 'Il formato per la settimana nell\'anno deve essere "w".',
-  'The queue is empty.' => 'La coda � vuota',
-  'The relation "{relation}" in active record class "{class}" is not specified correctly: the join table "{joinTable}" given in the foreign key cannot be found in the database.' => 'La relazione "{relation}" nella classe active record "{class}" non � specificata correttamente: la tabla di join "{join table}" specificata nella chiave esterna non pu� essere trovata nel DB.',
-  'The relation "{relation}" in active record class "{class}" is specified with an incomplete foreign key. The foreign key must consist of columns referencing both joining tables.' => 'La relazione "{relation}" nella classe active record "{class}" � specificata con una chiave esterna non completa. La chiave esterna deve consistere nelle colonne che referenziano entrambe le tabelle di join.',
-  'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key "{key}". The foreign key does not point to either joining table.' => 'La relazione "{relation}" nella classe active record "{class}" � specificata con una chiave esterna non valida "{key}". La chiave esterna non punta a nessuna tabella di join.',
-  'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key. The format of the foreign key must be "joinTable(fk1,fk2,...)".' => 'La relazione "{relation}" nella classe active record "{class}" � specificata con una chiave esterna non valida. Il formato della chiave esterna deve essere "joinTable(fk1,fk2,...)".',
+  'The queue is empty.' => 'La coda è vuota',
+  'The relation "{relation}" in active record class "{class}" is not specified correctly: the join table "{joinTable}" given in the foreign key cannot be found in the database.' => 'La relazione "{relation}" nella classe active record "{class}" non è specificata correttamente: la tabla di join "{join table}" specificata nella chiave esterna non può essere trovata nel DB.',
+  'The relation "{relation}" in active record class "{class}" is specified with an incomplete foreign key. The foreign key must consist of columns referencing both joining tables.' => 'La relazione "{relation}" nella classe active record "{class}" è specificata con una chiave esterna non completa. La chiave esterna deve consistere nelle colonne che referenziano entrambe le tabelle di join.',
+  'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key "{key}". The foreign key does not point to either joining table.' => 'La relazione "{relation}" nella classe active record "{class}" è specificata con una chiave esterna non valida "{key}". La chiave esterna non punta a nessuna tabella di join.',
+  'The relation "{relation}" in active record class "{class}" is specified with an invalid foreign key. The format of the foreign key must be "joinTable(fk1,fk2,...)".' => 'La relazione "{relation}" nella classe active record "{class}" è specificata con una chiave esterna non valida. Il formato della chiave esterna deve essere "joinTable(fk1,fk2,...)".',
   'The requested controller "{controller}" does not exist.' => 'Il controller "{controller}" richiesto non esiste.',
   'The requested view "{name}" is not found.' => 'Impossibile trovare la vista "{name}" richiesta.',
-  'The stack is empty.' => 'La pila  vuota',
+  'The stack is empty.' => 'La pila è vuota',
   'The system is unable to find the requested action "{action}".' => 'Il sistema non ha potuto trovare l\'azione "{action}" richiesta.',
-  'The system view path "{path}" is not a valid directory.' => 'Il percorso della vista di sistema "{path}" non � una cartella valida.',
-  'The table "{table}" for active record class "{class}" cannot be found in the database.' => 'La tabella "{table}" definita nella classe active record "{class}" non � presente nel DB.',
-  'The value for the primary key "{key}" is not supplied when querying the table "{table}".' => 'Il valore della chiave primaria "{key}" non � stato fornito per interrogare la tabella "{table}".',
-  'The verification code is incorrect.' => 'Il codice di verifica non � corretto.',
-  'The view path "{path}" is not a valid directory.' => 'Il percorso della vista "{path}" non � una cartella valida.',
+  'The system view path "{path}" is not a valid directory.' => 'Il percorso della vista di sistema "{path}" non è una cartella valida.',
+  'The table "{table}" for active record class "{class}" cannot be found in the database.' => 'La tabella "{table}" definita nella classe active record "{class}" non è presente nel DB.',
+  'The value for the primary key "{key}" is not supplied when querying the table "{table}".' => 'Il valore della chiave primaria "{key}" non è stato fornito per interrogare la tabella "{table}".',
+  'The verification code is incorrect.' => 'Il codice di verifica non è corretto.',
+  'The view path "{path}" is not a valid directory.' => 'Il percorso della vista "{path}" non è una cartella valida.',
   'Theme directory "{directory}" does not exist.' => 'La cartella dei temi "{directory}" non esiste.',
   'This content requires the <a href="http://www.adobe.com/go/getflash/">Adobe Flash Player</a>.' => 'Il contenuto richiede <a href="http://www.adobe.com/go/getflash/">Adobe Flash Player</a>.',
-  'Unable to add an item whose name is the same as an existing item.' => 'Non si pu� aggiungere un elemento il cui nome sia lo stesso di quello di un altro elemento.',
-  'Unable to change the item name. The name "{name}" is already used by another item.' => 'Impossibile cambiare il nome dell\'elemento. Il nome "{name}" � gi� utilizzato da un altro elemento.',
+  'Unable to add an item whose name is the same as an existing item.' => 'Non si può aggiungere un elemento il cui nome sia lo stesso di quello di un altro elemento.',
+  'Unable to change the item name. The name "{name}" is already used by another item.' => 'Impossibile cambiare il nome dell\'elemento. Il nome "{name}" è già utilizzato da un altro elemento.',
   'Unable to create application state file "{file}". Make sure the directory containing the file exists and is writable by the Web server process.' => 'Impossibile creare il file di stato dell\'applicazione "{file}". Verificare che la cartella che contiene il file esista e abbia permesso di scrittura per il processo del Web server.',
   'Unable to find the decorator view "{view}".' => 'Impossibile trovare la vista del decoratore "{view}".',
   'Unable to find the list item.' => 'Impossibile trovare l\'item della lista.',
   'Unable to lock file "{file}" for reading.' => 'Impossibile avere il lock sul file "{file}" per la lettura.',
   'Unable to lock file "{file}" for writing.' => 'Impossibile avere il lock sul "{file}" per la scrittura.',
   'Unable to read file "{file}".' => 'Impossibile leggere il file "{file}".',
-  'Unable to replay the action "{object}.{method}". The method does not exist.' => 'Impossibile replicare l\'azione "{object}.{method}". Il metodo � inesistente.',
+  'Unable to replay the action "{object}.{method}". The method does not exist.' => 'Impossibile replicare l\'azione "{object}.{method}". Il metodo è inesistente.',
   'Unable to write file "{file}".' => 'Impossibile scrivere il file "{file}".',
   'Unknown authorization item "{name}".' => 'Elemento di autorizzazione "{name}" sconosciuto.',
   'Unrecognized locale "{locale}".' => 'Localizzazione non riconosciuta "{locale}".',
   'View file "{file}" does not exist.' => 'Il file della vista "{view}" non esiste.',
-  'Yii application can only be created once.' => 'Si pu creare una sola applicazione Yii.',
+  'Yii application can only be created once.' => 'Si può creare una sola applicazione Yii.',
   'You are not authorized to perform this action.' => 'Non si ha l\'autorizzazione ad effettuare l\'operazione.',
-  'Your request is not valid.' => 'La richiesta non � valida.',
-  '{attribute} "{value}" has already been taken.' => '{attribute} "{value}" � gi� stato preso.',
-  '{attribute} cannot be blank.' => '{attribute} non pu� essere nullo.',
-  '{attribute} is invalid.' => '{attribute} non � valido.',
-  '{attribute} is not a valid URL.' => '{attribute} non � un URL valido.',
-  '{attribute} is not a valid email address.' => '{attribute} non � una email valida.',
-  '{attribute} is not in the list.' => '{attribute} non � nella lista.',
-  '{attribute} is of the wrong length (should be {length} characters).' => '{attribute} � della lunghezza sbagliata (deve essere di {length} caratteri)',
-  '{attribute} is too big (maximum is {max}).' => '{attribute} � troppo grande (il massimo � {max}).',
-  '{attribute} is too long (maximum is {max} characters).' => '{attribute} � troppo lungo (il massimo � di {max} caratteri)',
-  '{attribute} is too short (minimum is {min} characters).' => '{attribute} � troppo corto (il minimo � di {min} caratteri)',
-  '{attribute} is too small (minimum is {min}).' => '{attribute} � troppo piccolo (il minimo � {min}).',
+  'Your request is not valid.' => 'La richiesta non è valida.',
+  '{attribute} "{value}" has already been taken.' => '{attribute} "{value}" è già stato preso.',
+  '{attribute} cannot be blank.' => '{attribute} non può essere nullo.',
+  '{attribute} is invalid.' => '{attribute} non è valido.',
+  '{attribute} is not a valid URL.' => '{attribute} non è un URL valido.',
+  '{attribute} is not a valid email address.' => '{attribute} non è una email valida.',
+  '{attribute} is not in the list.' => '{attribute} non è nella lista.',
+  '{attribute} is of the wrong length (should be {length} characters).' => '{attribute} è della lunghezza sbagliata (deve essere di {length} caratteri)',
+  '{attribute} is too big (maximum is {max}).' => '{attribute} è troppo grande (il massimo è {max}).',
+  '{attribute} is too long (maximum is {max} characters).' => '{attribute} è troppo lungo (il massimo è di {max} caratteri)',
+  '{attribute} is too short (minimum is {min} characters).' => '{attribute} è troppo corto (il minimo è di {min} caratteri)',
+  '{attribute} is too small (minimum is {min}).' => '{attribute} è troppo piccolo (il minimo è {min}).',
   '{attribute} must be a number.' => '{attribute} deve essere un numero.',
   '{attribute} must be an integer.' => '{attribute} deve essere un intero.',
   '{attribute} must be repeated exactly.' => '{attribute} deve essere ripetuto esattamente.',
   '{attribute} must be {type}.' => '{attribute} deve essere {type}.',
-  '{className} does not support add() functionality.' => '{className} non supporta la funzionalit� add().',
-  '{className} does not support delete() functionality.' => '{className} non supporta la funzionalit� delete().',
-  '{className} does not support flush() functionality.' => '{className} non supporta la funzionalit� flush().',
-  '{className} does not support get() functionality.' => '{className} non supporta la funzionalit� get().',
-  '{className} does not support set() functionality.' => '{className} non supporta la funzionalit� set().',
+  '{className} does not support add() functionality.' => '{className} non supporta la funzionalità add().',
+  '{className} does not support delete() functionality.' => '{className} non supporta la funzionalità delete().',
+  '{className} does not support flush() functionality.' => '{className} non supporta la funzionalità flush().',
+  '{className} does not support get() functionality.' => '{className} non supporta la funzionalità get().',
+  '{className} does not support set() functionality.' => '{className} non supporta la funzionalità set().',
   '{class} does not have attribute "{name}".' => '{class} non contiene l\'attributo "{name}".',
   '{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.' => '{class} ha una regola di validazione non valida. La regola deve specificare gli attributi che devono essere validati e il nome del validatore.',
-  '{class} must specify "model" and "attribute" or "name" property values.' => '{class} deve specificare i valori delle propriet� "model" e "attribute" oppure "name".',
+  '{class} must specify "model" and "attribute" or "name" property values.' => '{class} deve specificare i valori delle proprietà "model" e "attribute" oppure "name".',
   '{class}.allowAutoLogin must be set true in order to use cookie-based authentication.' => '{class}.allowAutoLogin deve essere impostato a true per utilizzare l\'autenticazione basata su cookie.',
   '{class}::authenticate() must be implemented.' => '{class}::authenticate() deve essere implementata.',
   '{controller} cannot find the requested view "{view}".' => '{controller} non ha potuto trovare la vista "{view}" richiesta.',

File demo/yii/messages/pt_br/yii.php

   'The asset "{asset}" to be published does not exist.' => 'O recurso "{asset}", a ser publicado, não existe.',
   'The command path "{path}" is not a valid directory.' => 'O caminho "{path}" do "command" não é um diretório válido.',
   'The controller path "{path}" is not a valid directory.' => 'O endereço "{path}" do controle não é um diretório válido.',
-  'The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.' => 'O upload do arquivo "{file}" falhou. Somente são aceitos os arquivos com as extenções: {extensions}.',
+  'The file "{file}" cannot be uploaded. Only files with these extensions are allowed: {extensions}.' => 'O upload do arquivo "{file}" falhou. Somente são aceitos os arquivos com as extensões: {extensions}.',
   'The file "{file}" is too large. Its size cannot exceed {limit} bytes.' => 'O arquivo "{file}" é muito grande. Seu tamanho não pode exceder {limit} bytes.',
   'The file "{file}" is too small. Its size cannot be smaller than {limit} bytes.' => 'O arquivo "{file}" é muito pequeno. Seu tamanho não pode ser menor que {limit} bytes.',
   'The file "{file}" was only partially uploaded.' => 'O upload do arquivo "{file}" foi realizado parcialmente.',

File demo/yii/utils/CFormatter.php

  * @property CHtmlPurifier $htmlPurifier The HTML purifier instance.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CFormatter.php 3426 2011-10-25 00:01:09Z alexander.makarow $
+ * @version $Id: CFormatter.php 3553 2012-02-06 22:07:58Z alexander.makarow $
  * @package system.utils
  * @since 1.1.0
  */
 	 * Formats the value as a boolean.
 	 * @param mixed $value the value to be formatted
 	 * @return string the formatted result
-	 * @see trueText
-	 * @see falseText
+	 * @see booleanFormat
 	 */
 	public function formatBoolean($value)
 	{

File demo/yii/validators/CExistValidator.php

  * </ul>
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CExistValidator.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CExistValidator.php 3549 2012-01-27 15:36:43Z qiang.xue $
  * @package system.validators
  */
 class CExistValidator extends CValidator
 		if(!$finder->exists($criteria))
 		{
 			$message=$this->message!==null?$this->message:Yii::t('yii','{attribute} "{value}" is invalid.');
-			$this->addError($object,$attribute,$message,array('{value}'=>$value));
+			$this->addError($object,$attribute,$message,array('{value}'=>CHtml::encode($value)));
 		}
 	}
 }

File demo/yii/validators/CUniqueValidator.php

  * </ul>
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id: CUniqueValidator.php 3515 2011-12-28 12:29:24Z mdomba $
+ * @version $Id: CUniqueValidator.php 3549 2012-01-27 15:36:43Z qiang.xue $
  * @package system.validators
  * @since 1.0
  */
 		if($exists)
 		{
 			$message=$this->message!==null?$this->message:Yii::t('yii','{attribute} "{value}" has already been taken.');
-			$this->addError($object,$attribute,$message,array('{value}'=>$value));
+			$this->addError($object,$attribute,$message,array('{value}'=>CHtml::encode($value)));
 		}
 	}
 }

File demo/yii/vendors/README.html

   <td>most JavaScript-related functionalities</td>
 </tr>
 <tr>
-  <td><a href="http://www.jqueryui.com">jQuery UI 1.8.16</a></td>
-  <td><a href="jqueryui/LICENSE.txt">MIT</a></td>
+  <td><a href="http://www.jqueryui.com">jQuery UI 1.8.17</a></td>
+  <td><a href="jqueryui/MIT-LICENSE.txt">MIT</a></td>
   <td>the widgets under zii/widgets/jui</td>
 </tr>
 <tr>
 </tr>
 <tr>
   <td><a href="http://www.fyneworks.com/jquery/multiple-file-upload/">jQuery Multi File Upload 1.47</a></td>
-  <td><a href="jquery/multifile/LICENSE.txt">MIT</a></td>
+  <td><a href="http://www.fyneworks.com/jquery/multiple-file-upload/#tab-License">MIT</a></td>
   <td>CMultiFileUpload</td>
 </tr>
 <tr>
   <td>CGettextMoFile</td>
 </tr>
 <tr>
-  <td><a href="http://htmlpurifier.org/">HTML Purifier</a> (v4.3.0)</td>
+  <td><a href="http://htmlpurifier.org/">HTML Purifier</a> (v4.4.0)</td>
   <td><a href="htmlpurifier/LICENSE.txt">LGPL</a></td>
   <td>CHtmlPurifier</td>
 </tr>

File demo/yii/vendors/htmlpurifier/HTMLPurifier.standalone.php

  * primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
  * FILE, changes will be overwritten the next time the script is run.
  *
- * @version 4.3.0
+ * @version 4.4.0
  *
  * @warning
  *      You must *not* include any other HTML Purifier files before this file,
  */
 
 /*
-    HTML Purifier 4.3.0 - Standards Compliant HTML Filtering
+    HTML Purifier 4.4.0 - Standards Compliant HTML Filtering
     Copyright (C) 2006-2008 Edward Z. Yang
 
     This library is free software; you can redistribute it and/or
 {
 
     /** Version of HTML Purifier */
-    public $version = '4.3.0';
+    public $version = '4.4.0';
 
     /** Constant with version of HTML Purifier */
-    const VERSION = '4.3.0';
+    const VERSION = '4.4.0';
 
     /** Global configuration object */
     public $config;
      * types.
      */
     public function __construct() {
+        // XXX This is kind of poor, since we don't actually /clone/
+        // instances; instead, we use the supplied make() attribute. So,
+        // the underlying class must know how to deal with arguments.
+        // With the old implementation of Enum, that ignored its
+        // arguments when handling a make dispatch, the IAlign
+        // definition wouldn't work.
+
         // pseudo-types, must be instantiated via shorthand
         $this->info['Enum']    = new HTMLPurifier_AttrDef_Enum();
         $this->info['Bool']    = new HTMLPurifier_AttrDef_HTML_Bool();
         $this->info['URI']      = new HTMLPurifier_AttrDef_URI();
         $this->info['LanguageCode'] = new HTMLPurifier_AttrDef_Lang();
         $this->info['Color']    = new HTMLPurifier_AttrDef_HTML_Color();
+        $this->info['IAlign']   = self::makeEnum('top,middle,bottom,left,right');
+        $this->info['LAlign']   = self::makeEnum('top,bottom,left,right');
+        $this->info['FrameTarget'] = new HTMLPurifier_AttrDef_HTML_FrameTarget();
 
         // unimplemented aliases
         $this->info['ContentType'] = new HTMLPurifier_AttrDef_Text();
         $this->info['Number']   = new HTMLPurifier_AttrDef_Integer(false, false, true);
     }
 
+    private static function makeEnum($in) {
+        return new HTMLPurifier_AttrDef_Clone(new HTMLPurifier_AttrDef_Enum(explode(',', $in)));
+    }
+
     /**
      * Retrieves a type
      * @param $type String type name
     /**
      * HTML Purifier's version
      */
-    public $version = '4.3.0';
+    public $version = '4.4.0';
 
     /**
      * Bool indicator whether or not to automatically finalize
     /**
      * Parser for variables
      */
-    protected $parser;
+    protected $parser = null;
 
     /**
      * Reference HTMLPurifier_ConfigSchema for value checking
      */
     public function finalize() {
         $this->finalized = true;
-        unset($this->parser);
+        $this->parser = null;
     }
 
     /**
     public static function muteErrorHandler() {}
 
     /**
+     * iconv wrapper which mutes errors, but doesn't work around bugs.
+     */
+    public static function unsafeIconv($in, $out, $text) {
+        set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
+        $r = iconv($in, $out, $text);
+        restore_error_handler();
+        return $r;
+    }
+
+    /**
+     * iconv wrapper which mutes errors and works around bugs.
+     */
+    public static function iconv($in, $out, $text, $max_chunk_size = 8000) {
+        $code = self::testIconvTruncateBug();
+        if ($code == self::ICONV_OK) {
+            return self::unsafeIconv($in, $out, $text);
+        } elseif ($code == self::ICONV_TRUNCATES) {
+            // we can only work around this if the input character set
+            // is utf-8
+            if ($in == 'utf-8') {
+                if ($max_chunk_size < 4) {
+                    trigger_error('max_chunk_size is too small', E_USER_WARNING);
+                    return false;
+                }
+                // split into 8000 byte chunks, but be careful to handle
+                // multibyte boundaries properly
+                if (($c = strlen($text)) <= $max_chunk_size) {
+                    return self::unsafeIconv($in, $out, $text);
+                }
+                $r = '';
+                $i = 0;
+                while (true) {
+                    if ($i + $max_chunk_size >= $c) {
+                        $r .= self::unsafeIconv($in, $out, substr($text, $i));
+                        break;
+                    }
+                    // wibble the boundary
+                    if (0x80 != (0xC0 & ord($text[$i + $max_chunk_size]))) {
+                        $chunk_size = $max_chunk_size;
+                    } elseif (0x80 != (0xC0 & ord($text[$i + $max_chunk_size - 1]))) {
+                        $chunk_size = $max_chunk_size - 1;
+                    } elseif (0x80 != (0xC0 & ord($text[$i + $max_chunk_size - 2]))) {
+                        $chunk_size = $max_chunk_size - 2;
+                    } elseif (0x80 != (0xC0 & ord($text[$i + $max_chunk_size - 3]))) {
+                        $chunk_size = $max_chunk_size - 3;
+                    } else {
+                        return false; // rather confusing UTF-8...
+                    }
+                    $chunk = substr($text, $i, $chunk_size); // substr doesn't mind overlong lengths
+                    $r .= self::unsafeIconv($in, $out, $chunk);
+                    $i += $chunk_size;
+                }
+                return $r;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    /**
      * Cleans a UTF-8 string for well-formedness and SGML validity
      *
      * It will parse according to UTF-8 and return a valid UTF8 string, with
         return $ret;
     }
 
+    public static function iconvAvailable() {
+        static $iconv = null;
+        if ($iconv === null) {
+            $iconv = function_exists('iconv') && self::testIconvTruncateBug() != self::ICONV_UNUSABLE;
+        }
+        return $iconv;
+    }
+
     /**
      * Converts a string to UTF-8 based on configuration.
      */
         $encoding = $config->get('Core.Encoding');
         if ($encoding === 'utf-8') return $str;
         static $iconv = null;
-        if ($iconv === null) $iconv = function_exists('iconv');
-        set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
+        if ($iconv === null) $iconv = self::iconvAvailable();
         if ($iconv && !$config->get('Test.ForceNoIconv')) {
-            $str = iconv($encoding, 'utf-8//IGNORE', $str);
+            // unaffected by bugs, since UTF-8 support all characters
+            $str = self::unsafeIconv($encoding, 'utf-8//IGNORE', $str);
             if ($str === false) {
                 // $encoding is not a valid encoding
-                restore_error_handler();
                 trigger_error('Invalid encoding ' . $encoding, E_USER_ERROR);
                 return '';
             }
             // If the string is bjorked by Shift_JIS or a similar encoding
             // that doesn't support all of ASCII, convert the naughty
             // characters to their true byte-wise ASCII/UTF-8 equivalents.
-            $str = strtr($str, HTMLPurifier_Encoder::testEncodingSupportsASCII($encoding));
-            restore_error_handler();
+            $str = strtr($str, self::testEncodingSupportsASCII($encoding));
             return $str;
         } elseif ($encoding === 'iso-8859-1') {
             $str = utf8_encode($str);
-            restore_error_handler();
             return $str;
         }
         trigger_error('Encoding not supported, please install iconv', E_USER_ERROR);
      */
     public static function convertFromUTF8($str, $config, $context) {
         $encoding = $config->get('Core.Encoding');
+        if ($escape = $config->get('Core.EscapeNonASCIICharacters')) {
+            $str = self::convertToASCIIDumbLossless($str);
+        }
         if ($encoding === 'utf-8') return $str;
         static $iconv = null;
-        if ($iconv === null) $iconv = function_exists('iconv');
-        if ($escape = $config->get('Core.EscapeNonASCIICharacters')) {
-            $str = HTMLPurifier_Encoder::convertToASCIIDumbLossless($str);
-        }
-        set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
+        if ($iconv === null) $iconv = self::iconvAvailable();
         if ($iconv && !$config->get('Test.ForceNoIconv')) {
             // Undo our previous fix in convertToUTF8, otherwise iconv will barf
-            $ascii_fix = HTMLPurifier_Encoder::testEncodingSupportsASCII($encoding);
+            $ascii_fix = self::testEncodingSupportsASCII($encoding);
             if (!$escape && !empty($ascii_fix)) {
                 $clear_fix = array();
                 foreach ($ascii_fix as $utf8 => $native) $clear_fix[$utf8] = '';
             }
             $str = strtr($str, array_flip($ascii_fix));
             // Normal stuff
-            $str = iconv('utf-8', $encoding . '//IGNORE', $str);
-            restore_error_handler();
+            $str = self::iconv('utf-8', $encoding . '//IGNORE', $str);
             return $str;
         } elseif ($encoding === 'iso-8859-1') {
             $str = utf8_decode($str);
-            restore_error_handler();
             return $str;
         }
         trigger_error('Encoding not supported', E_USER_ERROR);
+        // You might be tempted to assume that the ASCII representation
+        // might be OK, however, this is *not* universally true over all
+        // encodings.  So we take the conservative route here, rather
+        // than forcibly turn on %Core.EscapeNonASCIICharacters
     }
 
     /**
         return $result;
     }
 
+    /** No bugs detected in iconv. */
+    const ICONV_OK = 0;
+
+    /** Iconv truncates output if converting from UTF-8 to another
+     *  character set with //IGNORE, and a non-encodable character is found */
+    const ICONV_TRUNCATES = 1;
+
+    /** Iconv does not support //IGNORE, making it unusable for
+     *  transcoding purposes */
+    const ICONV_UNUSABLE = 2;
+
+    /**
+     * glibc iconv has a known bug where it doesn't handle the magic
+     * //IGNORE stanza correctly.  In particular, rather than ignore
+     * characters, it will return an EILSEQ after consuming some number
+     * of characters, and expect you to restart iconv as if it were
+     * an E2BIG.  Old versions of PHP did not respect the errno, and
+     * returned the fragment, so as a result you would see iconv
+     * mysteriously truncating output. We can work around this by
+     * manually chopping our input into segments of about 8000
+     * characters, as long as PHP ignores the error code.  If PHP starts
+     * paying attention to the error code, iconv becomes unusable.
+     *
+     * @returns Error code indicating severity of bug.
+     */
+    public static function testIconvTruncateBug() {
+        static $code = null;
+        if ($code === null) {
+            // better not use iconv, otherwise infinite loop!
+            $r = self::unsafeIconv('utf-8', 'ascii//IGNORE', "\xCE\xB1" . str_repeat('a', 9000));
+            if ($r === false) {
+                $code = self::ICONV_UNUSABLE;
+            } elseif (($c = strlen($r)) < 9000) {
+                $code = self::ICONV_TRUNCATES;
+            } elseif ($c > 9000) {
+                trigger_error('Your copy of iconv is extremely buggy. Please notify HTML Purifier maintainers: include your iconv version as per phpversion()', E_USER_ERROR);
+            } else {
+                $code = self::ICONV_OK;
+            }
+        }
+        return $code;
+    }
+
     /**
      * This expensive function tests whether or not a given character
      * encoding supports ASCII. 7/8-bit encodings like Shift_JIS will
      *      which can be used to "undo" any overzealous iconv action.
      */
     public static function testEncodingSupportsASCII($encoding, $bypass = false) {
+        // All calls to iconv here are unsafe, proof by case analysis:
+        // If ICONV_OK, no difference.
+        // If ICONV_TRUNCATE, all calls involve one character inputs,
+        // so bug is not triggered.
+        // If ICONV_UNUSABLE, this call is irrelevant
         static $encodings = array();
         if (!$bypass) {
             if (isset($encodings[$encoding])) return $encodings[$encoding];
             if (strpos($lenc, 'iso-8859-') === 0) return array();
         }
         $ret = array();
-        set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
-        if (iconv('UTF-8', $encoding, 'a') === false) return false;
+        if (self::unsafeIconv('UTF-8', $encoding, 'a') === false) return false;
         for ($i = 0x20; $i <= 0x7E; $i++) { // all printable ASCII chars
             $c = chr($i); // UTF-8 char
-            $r = iconv('UTF-8', "$encoding//IGNORE", $c); // initial conversion
+            $r = self::unsafeIconv('UTF-8', "$encoding//IGNORE", $c); // initial conversion
             if (
                 $r === '' ||
                 // This line is needed for iconv implementations that do not
                 // omit characters that do not exist in the target character set
-                ($r === $c && iconv($encoding, 'UTF-8//IGNORE', $r) !== $c)
+                ($r === $c && self::unsafeIconv($encoding, 'UTF-8//IGNORE', $r) !== $c)
             ) {
                 // Reverse engineer: what's the UTF-8 equiv of this byte
                 // sequence? This assumes that there's no variable width
                 // encoding that doesn't support ASCII.
-                $ret[iconv($encoding, 'UTF-8//IGNORE', $c)] = $c;
-            }
-        }
-        restore_error_handler();
+                $ret[self::unsafeIconv($encoding, 'UTF-8//IGNORE', $c)] = $c;
+            }
+        }
         $encodings[$encoding] = $ret;
         return $ret;
     }
         return $this->_anonModule;
     }
 
-    private $_anonModule;
+    private $_anonModule = null;
 
 
     // PUBLIC BUT INTERNAL VARIABLES --------------------------------------
             'Presentation', 'Edit', 'Bdo', 'Tables', 'Image',
             'StyleAttribute',
             // Unsafe:
-            'Scripting', 'Object',  'Forms',
+            'Scripting', 'Object', 'Forms',
             // Sorta legacy, but present in strict:
             'Name',
         );
-        $transitional = array('Legacy', 'Target');
+        $transitional = array('Legacy', 'Target', 'Iframe');
         $xml = array('XMLCommonAttributes');
         $non_xml = array('NonXMLCommonAttributes');
 
 
         $this->doctypes->register(
             'XHTML 1.1', true,
-            array_merge($common, $xml, array('Ruby')),
+            // Iframe is a real XHTML 1.1 module, despite being
+            // "transitional"!
+            array_merge($common, $xml, array('Ruby', 'Iframe')),
             array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Proprietary', 'Tidy_Strict', 'Tidy_Name'), // Tidy_XHTML1_1
             array(),
             '-//W3C//DTD XHTML 1.1//EN',
         if ($config->get('HTML.Nofollow')) {
             $modules[] = 'Nofollow';
         }
+        if ($config->get('HTML.TargetBlank')) {
+            $modules[] = 'TargetBlank';
+        }
 
         // merge in custom modules
         $modules = array_merge($modules, $this->userModules);
                 // :TODO:
                 // non-standalone definitions that don't have a standalone
                 // to merge into could be deferred to the end
+                // HOWEVER, it is perfectly valid for a non-standalone
+                // definition to lack a standalone definition, even
+                // after all processing: this allows us to safely
+                // specify extra attributes for elements that may not be
+                // enabled all in one place.  In particular, this might
+                // be the case for trusted elements.  WARNING: care must
+                // be taken that the /extra/ definitions are all safe.
                 continue;
             }
 
         } else {
             // no scheme: retrieve the default one
             $def = $config->getDefinition('URI');
-            $scheme_obj = $registry->getScheme($def->defaultScheme, $config, $context);
+            $scheme_obj = $def->getDefaultScheme($config, $context);
             if (!$scheme_obj) {
                 // something funky happened to the default scheme object
                 trigger_error(
         return $result;
     }
 
+    /**
+     * Returns true if this URL might be considered a 'local' URL given
+     * the current context.  This is true when the host is null, or
+     * when it matches the host supplied to the configuration.
+     *
+     * Note that this does not do any scheme checking, so it is mostly
+     * only appropriate for metadata that doesn't care about protocol
+     * security.  isBenign is probably what you actually want.
+     */
+    public function isLocal($config, $context) {
+        if ($this->host === null) return true;
+        $uri_def = $config->getDefinition('URI');
+        if ($uri_def->host === $this->host) return true;
+        return false;
+    }
+
+    /**
+     * Returns true if this URL should be considered a 'benign' URL,
+     * that is:
+     *
+     *      - It is a local URL (isLocal), and
+     *      - It has a equal or better level of security
+     */
+    public function isBenign($config, $context) {
+        if (!$this->isLocal($config, $context)) return false;
+
+        $scheme_obj = $this->getSchemeObj($config, $context);
+        if (!$scheme_obj) return false; // conservative approach
+
+        $current_scheme_obj = $config->getDefinition('URI')->getDefaultScheme($config, $context);
+        if ($current_scheme_obj->secure) {
+            if (!$scheme_obj->secure) {
+                return false;
+            }
+        }
+        return true;
+    }
+
 }
 
 
         $this->registerFilter(new HTMLPurifier_URIFilter_DisableExternal());
         $this->registerFilter(new HTMLPurifier_URIFilter_DisableExternalResources());
         $this->registerFilter(new HTMLPurifier_URIFilter_HostBlacklist());
+        $this->registerFilter(new HTMLPurifier_URIFilter_SafeIframe());
         $this->registerFilter(new HTMLPurifier_URIFilter_MakeAbsolute());
         $this->registerFilter(new HTMLPurifier_URIFilter_Munge());
     }
 
     protected function setupFilters($config) {
         foreach ($this->registeredFilters as $name => $filter) {
-            $conf = $config->get('URI.' . $name);
-            if ($conf !== false && $conf !== null) {
+            if ($filter->always_load) {
                 $this->addFilter($filter, $config);
+            } else {
+                $conf = $config->get('URI.' . $name);
+                if ($conf !== false && $conf !== null) {
+                    $this->addFilter($filter, $config);
+                }
             }
         }
         unset($this->registeredFilters);
         if (is_null($this->defaultScheme)) $this->defaultScheme = $config->get('URI.DefaultScheme');
     }
 
+    public function getDefaultScheme($config, $context) {
+        return HTMLPurifier_URISchemeRegistry::instance()->getScheme($this->defaultScheme, $config, $context);
+    }
+
     public function filter(&$uri, $config, $context) {
         foreach ($this->filters as $name => $f) {
             $result = $f->filter($uri, $config, $context);
  * Chainable filters for custom URI processing.
  *
  * These filters can perform custom actions on a URI filter object,
- * including transformation or blacklisting.
+ * including transformation or blacklisting.  A filter named Foo
+ * must have a corresponding configuration directive %URI.Foo,
+ * unless always_load is specified to be true.
+ *
+ * The following contexts may be available while URIFilters are being
+ * processed:
+ *
+ *      - EmbeddedURI: true if URI is an embedded resource that will
+ *        be loaded automatically on page load
+ *      - CurrentToken: a reference to the token that is currently
+ *        being processed
+ *      - CurrentAttr: the name of the attribute that is currently being
+ *        processed
+ *      - CurrentCSSProperty: the name of the CSS property that is
+ *        currently being processed (if applicable)
  *
  * @warning This filter is called before scheme object validation occurs.
  *          Make sure, if you require a specific scheme object, you
     public $post = false;
 
     /**
-     * Performs initialization for the filter
+     * True if this filter should always be loaded (this permits
+     * a filter to be named Foo without the corresponding %URI.Foo
+     * directive existing.)
+     */
+    public $always_load = false;
+
+    /**
+     * Performs initialization for the filter.  If the filter returns
+     * false, this means that it shouldn't be considered active.
      */
     public function prepare($config) {return true;}
 
     public $browsable = false;
 
     /**
+     * Whether or not data transmitted over this scheme is encrypted.
+     * https is secure, http is not.
+     */
+    public $secure = false;
+
+    /**
      * Whether or not the URI always uses <hier_part>, resolves edge cases
      * with making relative URIs absolute
      */
 
 
 
+/**
+ * Dummy AttrDef that mimics another AttrDef, BUT it generates clones
+ * with make.
+ */
+class HTMLPurifier_AttrDef_Clone extends HTMLPurifier_AttrDef
+{
+    /**
+     * What we're cloning
+     */
+    protected $clone;
+
+    public function __construct($clone) {
+        $this->clone = $clone;
+    }
+
+    public function validate($v, $config, $context) {
+        return $this->clone->validate($v, $config, $context);
+    }
+
+    public function make($string) {
+        return clone $this->clone;
+    }
+
+}
+
+
+
+
+
 // Enum = Enumerated
 /**
  * Validates a keyword against a list of valid values.
     }
 
     public function make($string) {
-        $embeds = (bool) $string;
+        $embeds = ($string === 'embedded');
         return new HTMLPurifier_AttrDef_URI($embeds);
     }
 
 
 
 /**
+ * Validates based on {ident} CSS grammar production
+ */
+class HTMLPurifier_AttrDef_CSS_Ident extends HTMLPurifier_AttrDef
+{
+
+    public function validate($string, $config, $context) {
+
+        $string = trim($string);
+
+        // early abort: '' and '0' (strings that convert to false) are invalid
+        if (!$string) return false;
+
+        $pattern = '/^(-?[A-Za-z_][A-Za-z_\-0-9]*)$/';
+        if (!preg_match($pattern, $string)) return false;
+        return $string;
+
+    }
+
+}
+
+
+
+
+
+/**
  * Decorator which enables !important to be used in CSS values.
  */
 class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
         $string = trim($string);
 
         if (empty($string)) return false;
-        if (isset($colors[$string])) return $colors[$string];
+        if (isset($colors[strtolower($string)])) return $colors[$string];
         if ($string[0] === '#') $hex = substr($string, 1);
         else $hex = $string;
 
 class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
 {
 
-    // ref functionality disabled, since we also have to verify
-    // whether or not the ID it refers to exists
+    // selector is NOT a valid thing to use for IDREFs, because IDREFs
+    // *must* target IDs that exist, whereas selector #ids do not.
+
+    /**
+     * Determines whether or not we're validating an ID in a CSS
+     * selector context.
+     */
+    protected $selector;
+
+    public function __construct($selector = false) {
+        $this->selector = $selector;
+    }
 
     public function validate($id, $config, $context) {
 
-        if (!$config->get('Attr.EnableID')) return false;
+        if (!$this->selector && !$config->get('Attr.EnableID')) return false;
 
         $id = trim($id); // trim it first
 
                 '%Attr.IDPrefix is set', E_USER_WARNING);
         }
 
-        //if (!$this->ref) {
+        if (!$this->selector) {
             $id_accumulator =& $context->get('IDAccumulator');
             if (isset($id_accumulator->ids[$id])) return false;
-        //}
+        }
 
         // we purposely avoid using regex, hopefully this is faster
 
             return false;
         }
 
-        if (/*!$this->ref && */$result) $id_accumulator->add($id);
+        if (!$this->selector && $result) $id_accumulator->add($id);