Commit 60defaf5 authored by 姓刘名佳字子沐's avatar 姓刘名佳字子沐 Committed by seekArt
Browse files

!10 开源版4.4.2

Merge pull request !10 from 姓刘名佳字子沐/feature/tag-open-4.4.2
parents a04ba09f 26171103
Showing with 2041 additions and 33 deletions
+2041 -33
......@@ -19,7 +19,7 @@ $funcItems = array(
'file_get_contents' => array('status' => 1),
'scandir' => array('status' => 1),
'xml_parser_create' => array('status' => 1),
// 'bcmul' => array('status' => 1),
'bcmul' => array('status' => 1),
);
$filesockItems = array(
......@@ -43,12 +43,13 @@ $envItems = array(
'attachmentupload' => array('r' => '2M', 'b' => '20M'),
'gdversion' => array('r' => '1.0', 'b' => '2.0'),
'diskspace' => array('r' => '100M', 'b' => 'notset'),
// 'Zend Guard Loader' => array('r' => 'install', 'b' => 'install'),
'Zend Guard Loader' => array('r' => 'install', 'b' => 'install'),
);
// 要检测的文件、文件夹权限
$dirfileItems = array(
'config' => array('type' => 'file', 'path' => '/system/config/configDefault.php'),
'org' => array('type' => 'file', 'path' => '/data/org'),
'root' => array('type' => 'dir', 'path' => '/'),
'config_dir' => array('type' => 'dir', 'path' => '/system/config'),
'data' => array('type' => 'dir', 'path' => '/data'),
'attachment' => array('type' => 'dir', 'path' => '/data/attachment'),
......
......@@ -80,7 +80,7 @@ class YiiBase
*/
public static function getVersion()
{
return '1.1.17';
return '1.1.19';
}
/**
......@@ -179,6 +179,7 @@ class YiiBase
*/
public static function createComponent($config)
{
$args = func_get_args();
if(is_string($config))
{
$type=$config;
......@@ -197,7 +198,6 @@ class YiiBase
if(($n=func_num_args())>1)
{
$args=func_get_args();
if($n===2)
$object=new $type($args[1]);
elseif($n===3)
......
......@@ -133,7 +133,7 @@ abstract class CApplication extends CModule
{
Yii::setApplication($this);
// set basePath at early as possible to avoid trouble
// set basePath as early as possible to avoid trouble
if(is_string($config))
$config=require($config);
if(isset($config['basePath']))
......@@ -400,7 +400,7 @@ abstract class CApplication extends CModule
/**
* Returns the locale instance.
* @param string $localeID the locale ID (e.g. en_US). If null, the {@link getLanguage application language ID} will be used.
* @return an instance of CLocale
* @return CLocale an instance of CLocale
*/
public function getLocale($localeID=null)
{
......@@ -572,7 +572,7 @@ abstract class CApplication extends CModule
public function createAbsoluteUrl($route,$params=array(),$schema='',$ampersand='&')
{
$url=$this->createUrl($route,$params,$ampersand);
if(strpos($url,'http')===0)
if(strpos($url,'http')===0 || strpos($url,'//')===0)
return $url;
else
return $this->getRequest()->getHostInfo($schema).$url;
......
......@@ -609,7 +609,14 @@ class CComponent
if(is_string($_expression_))
{
extract($_data_);
return eval('return '.$_expression_.';');
try
{
return eval('return ' . $_expression_ . ';');
}
catch (ParseError $e)
{
return false;
}
}
else
{
......
......@@ -64,7 +64,7 @@ abstract class CModel extends CComponent implements IteratorAggregate, ArrayAcce
* <li>except: this specifies the scenarios when the validation rule should not be performed.
* Separate different scenarios with commas. Please see {@link scenario} for more details about this option.</li>
* <li>additional parameters are used to initialize the corresponding validator properties.
* Please refer to individal validator class API for possible properties.</li>
* Please refer to individual validator class API for possible properties.</li>
* </ul>
*
* The following are some examples:
......
......@@ -71,7 +71,7 @@ abstract class CModule extends CComponent
$this->_id=$id;
$this->_parentModule=$parent;
// set basePath at early as possible to avoid trouble
// set basePath as early as possible to avoid trouble
if(is_string($config))
$config=require($config);
if(isset($config['basePath']))
......
......@@ -222,11 +222,11 @@ class CSecurityManager extends CApplicationComponent
$this->validateEncryptionKey($key);
$module=$this->openCryptModule();
srand();
$iv=mcrypt_create_iv(mcrypt_enc_get_iv_size($module), MCRYPT_RAND);
mcrypt_generic_init($module,$key,$iv);
$encrypted=$iv.mcrypt_generic($module,$data);
mcrypt_generic_deinit($module);
mcrypt_module_close($module);
$iv=@mcrypt_create_iv(mcrypt_enc_get_iv_size($module), MCRYPT_RAND);
@mcrypt_generic_init($module,$key,$iv);
$encrypted=$iv.@mcrypt_generic($module,$data);
@mcrypt_generic_deinit($module);
@mcrypt_module_close($module);
return $encrypted;
}
......@@ -243,12 +243,12 @@ class CSecurityManager extends CApplicationComponent
$key=$this->getEncryptionKey();
$this->validateEncryptionKey($key);
$module=$this->openCryptModule();
$ivSize=mcrypt_enc_get_iv_size($module);
$ivSize=@mcrypt_enc_get_iv_size($module);
$iv=$this->substr($data,0,$ivSize);
mcrypt_generic_init($module,$key,$iv);
$decrypted=mdecrypt_generic($module,$this->substr($data,$ivSize,$this->strlen($data)));
mcrypt_generic_deinit($module);
mcrypt_module_close($module);
@mcrypt_generic_init($module,$key,$iv);
$decrypted=@mdecrypt_generic($module,$this->substr($data,$ivSize,$this->strlen($data)));
@mcrypt_generic_deinit($module);
@mcrypt_module_close($module);
return rtrim($decrypted,"\0");
}
......@@ -399,7 +399,7 @@ class CSecurityManager extends CApplicationComponent
}
if(function_exists('mcrypt_create_iv') &&
($bytes=mcrypt_create_iv($length, MCRYPT_DEV_URANDOM))!==false &&
($bytes=@mcrypt_create_iv($length, MCRYPT_DEV_URANDOM))!==false &&
$this->strlen($bytes)>=$length)
{
return $this->substr($bytes,0,$length);
......@@ -531,7 +531,7 @@ class CSecurityManager extends CApplicationComponent
{
$cryptAlgorithm = is_array($this->cryptAlgorithm) ? $this->cryptAlgorithm[0] : $this->cryptAlgorithm;
$supportedKeyLengths=mcrypt_module_get_supported_key_sizes($cryptAlgorithm);
$supportedKeyLengths=@mcrypt_module_get_supported_key_sizes($cryptAlgorithm);
if($supportedKeyLengths)
{
......@@ -542,7 +542,7 @@ class CSecurityManager extends CApplicationComponent
elseif(isset(self::$encryptionKeyMinimumLengths[$cryptAlgorithm]))
{
$minLength=self::$encryptionKeyMinimumLengths[$cryptAlgorithm];
$maxLength=mcrypt_module_get_algo_key_size($cryptAlgorithm);
$maxLength=@mcrypt_module_get_algo_key_size($cryptAlgorithm);
if($this->strlen($key)<$minLength || $this->strlen($key)>$maxLength)
throw new CException(Yii::t('yii','Encryption key length must be between {minLength} and {maxLength}.',array('{minLength}'=>$minLength,'{maxLength}'=>$maxLength)));
}
......@@ -586,13 +586,13 @@ class CSecurityManager extends CApplicationComponent
else
throw new CException(Yii::t('yii','CSecurityManager requires PHP mcrypt extension to be loaded in order to use data encryption feature.'));
$derivedKey=$this->substr($key,0,mcrypt_enc_get_key_size($module));
$ivSize=mcrypt_enc_get_iv_size($module);
$derivedKey=$this->substr($key,0,@mcrypt_enc_get_key_size($module));
$ivSize=@mcrypt_enc_get_iv_size($module);
$iv=$this->substr($data,0,$ivSize);
mcrypt_generic_init($module,$derivedKey,$iv);
$decrypted=mdecrypt_generic($module,$this->substr($data,$ivSize,$this->strlen($data)));
mcrypt_generic_deinit($module);
mcrypt_module_close($module);
@mcrypt_generic_init($module,$derivedKey,$iv);
$decrypted=@mdecrypt_generic($module,$this->substr($data,$ivSize,$this->strlen($data)));
@mcrypt_generic_deinit($module);
@mcrypt_module_close($module);
return rtrim($decrypted,"\0");
}
......@@ -614,4 +614,35 @@ class CSecurityManager extends CApplicationComponent
$diff|=(ord($actual[$i])^ord($expected[$i%$expectedLength]));
return $diff===0;
}
/**
* Masks a token to make it uncompressible.
* Applies a random mask to the token and prepends the mask used to the result making the string always unique.
* Used to mitigate BREACH attack by randomizing how token is outputted on each request.
* @param string $token An unmasked token.
* @return string A masked token.
* @since 1.1.18
*/
public function maskToken($token)
{
// The number of bytes in a mask is always equal to the number of bytes in a token.
$mask=$this->generateRandomString($this->strlen($token));
return strtr(base64_encode($mask.($mask^$token)),'+/','-_');
}
/**
* Unmasks a token previously masked by `maskToken`.
* @param string $maskedToken A masked token.
* @return string An unmasked token, or an empty string in case of token format is invalid.
* @since 1.1.18
*/
public function unmaskToken($maskedToken)
{
$decoded=base64_decode(strtr($maskedToken,'-_','+/'));
$length=$this->strlen($decoded)/2;
// Check if the masked token has an even length.
if(!is_int($length))
return '';
return $this->substr($decoded,$length,$length)^$this->substr($decoded,0,$length);
}
}
......@@ -105,7 +105,8 @@ class CStatePersister extends CApplicationComponent implements IStatePersister
* Loads content from file using a shared lock to avoid data corruption when reading
* the file while it is being written by save()
*
* @return string file contents
* @param string $filename file name
* @return bool|string file contents
* @since 1.1.17
*/
protected function getContent($filename)
......
......@@ -350,7 +350,7 @@ interface IAuthManager
* Creates an authorization item.
* An authorization item represents an action permission (e.g. creating a post).
* It has three types: operation, task and role.
* Authorization items form a hierarchy. Higher level items inheirt permissions representing
* Authorization items form a hierarchy. Higher level items inherit permissions representing
* by lower level items.
* @param string $name the item name. This must be a unique identifier.
* @param integer $type the item type (0: operation, 1: task, 2: role).
......
......@@ -130,7 +130,7 @@ class CFileCache extends CCache
{
$cacheFile=$this->getCacheFile($key);
if(($time=$this->filemtime($cacheFile))>time())
return @file_get_contents($cacheFile,false,null,$this->embedExpiry ? 10 : -1);
return @file_get_contents($cacheFile,false,null,$this->embedExpiry ? 10 : null);
elseif($time>0)
@unlink($cacheFile);
return false;
......
......@@ -114,7 +114,7 @@ class CMemCache extends CCache
$extension=$this->useMemcached ? 'memcached' : 'memcache';
if(!extension_loaded($extension))
throw new CException(Yii::t('yii',"CMemCache requires PHP {extension} extension to be loaded.",
array('{extension}'=>$extension)));
array('{extension}'=>$extension)));
return $this->_cache=$this->useMemcached ? new Memcached : new Memcache;
}
}
......
......@@ -95,7 +95,10 @@ class CRedisCache extends CCache
$this->executeCommand('SELECT',array($this->database));
}
else
{
$this->_socket = null;
throw new CException('Failed to connect to redis: '.$errorDescription,(int)$errorNumber);
}
}
/**
......
<?php
/**
* MessageCommand class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* MessageCommand extracts messages to be translated from source files.
* The extracted messages are saved as PHP message source files
* under the specified directory.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package system.cli.commands
* @since 1.0
*/
class MessageCommand extends CConsoleCommand
{
public function getHelp()
{
return <<<EOD
USAGE
yiic message <config-file>
DESCRIPTION
This command searches for messages to be translated in the specified
source files and compiles them into PHP arrays as message source.
PARAMETERS
* config-file: required, the path of the configuration file. You can find
an example in framework/messages/config.php.
The file can be placed anywhere and must be a valid PHP script which
returns an array of name-value pairs. Each name-value pair represents
a configuration option.
The following options are available:
- sourcePath: string, root directory of all source files.
- messagePath: string, root directory containing message translations.
- languages: array, list of language codes that the extracted messages
should be translated to. For example, array('zh_cn','en_au').
- fileTypes: array, a list of file extensions (e.g. 'php', 'xml').
Only the files whose extension name can be found in this list
will be processed. If empty, all files will be processed.
- exclude: array, a list of directory and file exclusions. Each
exclusion can be either a name or a path. If a file or directory name
or path matches the exclusion, it will not be copied. For example,
an exclusion of '.svn' will exclude all files and directories whose
name is '.svn'. And an exclusion of '/a/b' will exclude file or
directory 'sourcePath/a/b'.
- translator: the name of the function for translating messages.
Defaults to 'Yii::t'. This is used as a mark to find messages to be
translated. Accepts both string for single function name or array for
multiple function names.
- overwrite: if message file must be overwritten with the merged messages.
- removeOld: if message no longer needs translation it will be removed,
instead of being enclosed between a pair of '@@' marks.
- sort: sort messages by key when merging, regardless of their translation
state (new, obsolete, translated.)
- fileHeader: A boolean indicating whether the file should contain a default
comment that explains the message file or a string representing
some PHP code or comment to add before the return tag in the message file.
EOD;
}
/**
* Execute the action.
* @param array $args command line parameters specific for this command
*/
public function run($args)
{
if(!isset($args[0]))
$this->usageError('the configuration file is not specified.');
if(!is_file($args[0]))
$this->usageError("the configuration file {$args[0]} does not exist.");
$config=require($args[0]);
$translator='Yii::t';
extract($config);
if(!isset($sourcePath,$messagePath,$languages))
$this->usageError('The configuration file must specify "sourcePath", "messagePath" and "languages".');
if(!is_dir($sourcePath))
$this->usageError("The source path $sourcePath is not a valid directory.");
if(!is_dir($messagePath))
$this->usageError("The message path $messagePath is not a valid directory.");
if(empty($languages))
$this->usageError("Languages cannot be empty.");
if(!isset($overwrite))
$overwrite = false;
if(!isset($removeOld))
$removeOld = false;
if(!isset($sort))
$sort = false;
if(!isset($fileHeader))
$fileHeader = true;
$options=array();
if(isset($fileTypes))
$options['fileTypes']=$fileTypes;
if(isset($exclude))
$options['exclude']=$exclude;
$files=CFileHelper::findFiles(realpath($sourcePath),$options);
$messages=array();
foreach($files as $file)
$messages=array_merge_recursive($messages,$this->extractMessages($file,$translator));
foreach($languages as $language)
{
$dir=$messagePath.DIRECTORY_SEPARATOR.$language;
if(!is_dir($dir))
@mkdir($dir);
foreach($messages as $category=>$msgs)
{
$msgs=array_values(array_unique($msgs));
$this->generateMessageFile($msgs,$dir.DIRECTORY_SEPARATOR.$category.'.php',$overwrite,$removeOld,$sort,$fileHeader);
}
}
}
protected function extractMessages($fileName,$translator)
{
echo "Extracting messages from $fileName...\n";
$subject=file_get_contents($fileName);
$messages=array();
if(!is_array($translator))
$translator=array($translator);
foreach ($translator as $currentTranslator)
{
$n=preg_match_all('/\b'.$currentTranslator.'\s*\(\s*(\'[\w.\/]*?(?<!\.)\'|"[\w.]*?(?<!\.)")\s*,\s*(\'.*?(?<!\\\\)\'|".*?(?<!\\\\)")\s*[,\)]/s',$subject,$matches,PREG_SET_ORDER);
for($i=0;$i<$n;++$i)
{
if(($pos=strpos($matches[$i][1],'.'))!==false)
$category=substr($matches[$i][1],$pos+1,-1);
else
$category=substr($matches[$i][1],1,-1);
$message=$matches[$i][2];
try
{
$evalResult = eval("return $message;"); // use eval to eliminate quote escape
}
catch (ParseError $e)
{
$evalResult = false;
}
$messages[$category][] = $evalResult;
}
}
return $messages;
}
protected function generateMessageFile($messages,$fileName,$overwrite,$removeOld,$sort,$fileHeader)
{
echo "Saving messages to $fileName...";
if(is_file($fileName))
{
$translated=require($fileName);
sort($messages);
ksort($translated);
if(array_keys($translated)==$messages)
{
echo "nothing new...skipped.\n";
return;
}
$merged=array();
$untranslated=array();
foreach($messages as $message)
{
if(array_key_exists($message,$translated) && strlen($translated[$message])>0)
$merged[$message]=$translated[$message];
else
$untranslated[]=$message;
}
ksort($merged);
sort($untranslated);
$todo=array();
foreach($untranslated as $message)
$todo[$message]='';
ksort($translated);
foreach($translated as $message=>$translation)
{
if(!isset($merged[$message]) && !isset($todo[$message]) && !$removeOld)
{
if(substr($translation,0,2)==='@@' && substr($translation,-2)==='@@')
$todo[$message]=$translation;
else
$todo[$message]='@@'.$translation.'@@';
}
}
$merged=array_merge($todo,$merged);
if($sort)
ksort($merged);
if($overwrite === false)
$fileName.='.merged';
echo "translation merged.\n";
}
else
{
$merged=array();
foreach($messages as $message)
$merged[$message]='';
ksort($merged);
echo "saved.\n";
}
$array=str_replace("\r",'',var_export($merged,true));
if($fileHeader===true)
$fileHeader=<<<EOD
/**
* Message translations.
*
* This file is automatically generated by 'yiic message' command.
* It contains the localizable messages extracted from source code.
* You may modify this file by translating the extracted messages.
*
* Each array element represents the translation (value) of a message (key).
* If the value is empty, the message is considered as not translated.
* Messages that no longer need translation will have their translations
* enclosed between a pair of '@@' marks.
*
* Message string can be used with plural forms format. Check i18n section
* of the guide for details.
*
* NOTE, this file must be saved in UTF-8 encoding.
*/
EOD;
elseif($fileHeader===false)
$fileHeader='';
file_put_contents($fileName,<<<EOD
<?php
$fileHeader
return $array;
EOD
);
}
}
This diff is collapsed.
<?php
/**
* ShellCommand class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* ShellCommand executes the specified Web application and provides a shell for interaction.
*
* @property string $help The help information for the shell command.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package system.cli.commands
* @since 1.0
*/
class ShellCommand extends CConsoleCommand
{
/**
* @return string the help information for the shell command
*/
public function getHelp()
{
return <<<EOD
USAGE
yiic shell [entry-script | config-file]
DESCRIPTION
This command allows you to interact with a Web application
on the command line. It also provides tools to automatically
generate new controllers, views and data models.
It is recommended that you execute this command under
the directory that contains the entry script file of
the Web application.
PARAMETERS
* entry-script | config-file: optional, the path to
the entry script file or the configuration file for
the Web application. If not given, it is assumed to be
the 'index.php' file under the current directory.
EOD;
}
/**
* Execute the action.
* @param array $args command line parameters specific for this command
*/
public function run($args)
{
if(!isset($args[0]))
$args[0]='index.php';
$entryScript=isset($args[0]) ? $args[0] : 'index.php';
if(($entryScript=realpath($args[0]))===false || !is_file($entryScript))
$this->usageError("{$args[0]} does not exist or is not an entry script file.");
// fake the web server setting
$cwd=getcwd();
chdir(dirname($entryScript));
$_SERVER['SCRIPT_NAME']='/'.basename($entryScript);
$_SERVER['REQUEST_URI']=$_SERVER['SCRIPT_NAME'];
$_SERVER['SCRIPT_FILENAME']=$entryScript;
$_SERVER['HTTP_HOST']='localhost';
$_SERVER['SERVER_NAME']='localhost';
$_SERVER['SERVER_PORT']=80;
// reset context to run the web application
restore_error_handler();
restore_exception_handler();
Yii::setApplication(null);
Yii::setPathOfAlias('application',null);
ob_start();
$config=require($entryScript);
ob_end_clean();
// oops, the entry script turns out to be a config file
if(is_array($config))
{
chdir($cwd);
$_SERVER['SCRIPT_NAME']='/index.php';
$_SERVER['REQUEST_URI']=$_SERVER['SCRIPT_NAME'];
$_SERVER['SCRIPT_FILENAME']=$cwd.DIRECTORY_SEPARATOR.'index.php';
Yii::createWebApplication($config);
}
restore_error_handler();
restore_exception_handler();
$yiiVersion=Yii::getVersion();
echo <<<EOD
Yii Interactive Tool v1.1 (based on Yii v{$yiiVersion})
Please type 'help' for help. Type 'exit' to quit.
EOD;
$this->runShell();
}
protected function runShell()
{
// disable E_NOTICE so that the shell is more friendly
error_reporting(E_ALL ^ E_NOTICE);
$_runner_=$this->createCommandRunner();
$this->addCommands($_runner_);
$_commands_=$_runner_->commands;
$log=Yii::app()->log;
while(($_line_=$this->prompt("\n>>"))!==false)
{
$_line_=trim($_line_);
if($_line_==='exit')
return;
try
{
$_args_=preg_split('/[\s,]+/',rtrim($_line_,';'),-1,PREG_SPLIT_NO_EMPTY);
if(isset($_args_[0]) && isset($_commands_[$_args_[0]]))
{
$_command_=$_runner_->createCommand($_args_[0]);
array_shift($_args_);
$_command_->init();
$_command_->run($_args_);
}
else
{
try
{
$evalResult = eval($_line_ . ';');
}
catch (ParseError $e)
{
$evalResult = false;
}
echo $evalResult;
}
}
catch(Exception $e)
{
if($e instanceof ShellException)
echo $e->getMessage();
else
echo $e;
}
}
}
/**
* Creates a commands runner
* @return CConsoleCommandRunner
* @since 1.1.16
*/
protected function createCommandRunner()
{
return new CConsoleCommandRunner;
}
/**
* Adds commands to runner
* @param CConsoleCommandRunner $runner
* @since 1.1.16
*/
protected function addCommands(CConsoleCommandRunner $runner)
{
$runner->addCommands(Yii::getPathOfAlias('system.cli.commands.shell'));
$runner->addCommands(Yii::getPathOfAlias('application.commands.shell'));
if(($_path_=@getenv('YIIC_SHELL_COMMAND_PATH'))!==false)
$runner->addCommands($_path_);
}
}
class ShellException extends CException
{
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment