widget('Widget_User')->pass('administrator');
if($plugName){
$dir='.'.__TYPECHO_PLUGIN_DIR__;
if (is_writable($dir)){
chdir($dir);
if(is_dir($plugName)){
if(false==$this->delTree($plugName)){
$this->widget('Widget_Notice')->set(_t('插件:'.$plugName.'删除失败'), NULL, 'error');
}else{
$this->widget('Widget_Notice')->set(_t('成功删除插件:'.$plugName), NULL, 'success');
}
}else{
$file=$plugName.'.php';
if(@unlink($file)){
$this->widget('Widget_Notice')->set(_t('成功删除插件:'.$plugName), NULL, 'success');
}else{
$this->widget('Widget_Notice')->set(_t('插件:'.$plugName.'删除失败'), NULL, 'error');
}
}
}else{
$this->widget('Widget_Notice')->set(_t('插件主目录没有写权限:'.$plugName.'删除失败'), NULL, 'error');
}
}else{
$this->widget('Widget_Notice')->set(_t('插件不存在!'), NULL, 'notice');
}
}
/**
* 删除模板
* @param mixed $plugName 待删除的插件名称
* @access public
* @return void
*/
public function delTheme($themeName)
{
$this->widget('Widget_User')->pass('administrator');
$dir='.'.__TYPECHO_THEME_DIR__;
if (is_writable($dir)){
chdir($dir);
if(is_dir($themeName)){
if(false==$this->delTree($themeName)){
$this->widget('Widget_Notice')->set(_t('模板:'.$themeName.'删除失败'), NULL, 'error');
}else{
$this->widget('Widget_Notice')->set(_t('成功删除模板:'.$themeName), NULL, 'success');
}
}else{
$this->widget('Widget_Notice')->set(_t('没发现'.$themeName.'模板!'), NULL, 'notice');
}
}else{
$this->widget('Widget_Notice')->set(_t('themes主目录没有写权限:'.$themeName.'删除失败'), NULL, 'error');
}
}
/**
* 删除目录
* @param mixed $dir 待删除的插件目录
* @access public
* @return boolean
*/
private function delTree($dir){
chdir($dir);
$dh=opendir('.');
while(false !== ($et=readdir($dh))){
if(is_file($et)){
if(!@unlink($et)){
return false;
break;
}
}else{
if(is_dir($et) && $et!='.' && $et!='..'){
$this->delTree('./'.$et);
}
}
}
closedir($dh);
chdir('..');
if(@rmdir($dir)){
return true;
}else{
return false;
}
}
/**
* 上传处理功能
*/
public function upload($filead){
if (!empty($_FILES['file']['name']) || $filead) {
if (!$filead and !isset($_FILES['file']) || !is_uploaded_file($_FILES['file']['tmp_name']) || $_FILES['file']['error'] != 0) {
echo '';
exit(0);
}elseif ($filead) {
$this->_file = basename($filead);
$part = pathinfo($this->_file);
if($part['extension'] !== "zip"){
$this->_file = "tmp".Typecho_Common::randString(6).".zip";
}
$ff = @file_get_contents($filead);
if($ff){
file_put_contents($this->_file, $ff);
$up = False;
if(!$this->isZip($this->_file)) $this->showMsg('取得的文件不是zip类型' , FALSE, TRUE);
}else{
$this->showMsg('获取远程文件失败。' , FALSE, TRUE);
}
} else {
$this->_file = $_FILES['file']['tmp_name'];
$up = True;
}
$path = '';
$upType = '插件';
if (class_exists('ZipArchive')) {
$zip = new ZipArchive;
}else{
$this->showMsg("服务器不支持 php ZipArchive 类", $up);
}
if ($zip->open($this->_file) === TRUE) {
//单文件插件
if($zip->numFiles === 1){
$contents = $zip->getFromIndex(0);
if($this->isPlugin($contents)) $path= '.' . __TYPECHO_PLUGIN_DIR__.'/' ;
}else{
//多文件插件,搜索Plugin.php文件路径,获取插件信息
$index=$zip->locateName('Plugin.php', ZIPARCHIVE::FL_NOCASE|ZIPARCHIVE::FL_NODIR);
if($index || 0===$index){
$dirs = count(explode('/', $zip->getNameIndex($index)));
if($dirs>2){
$this->showMsg('压缩路径太深,无法正常安装', $up, TRUE) ;
}
$contents = $zip->getFromIndex($index);
$name = $this->isPlugin($contents);
if($name){
if(2==$dirs){
$path='.' . __TYPECHO_PLUGIN_DIR__.'/';
}else{
$path='.' . __TYPECHO_PLUGIN_DIR__ .'/'. $name.'/';
}
}
}else{
//如果不是插件,则按模板搜索判断
$index=$zip->locateName('index.php', ZIPARCHIVE::FL_NOCASE|ZIPARCHIVE::FL_NODIR);
if($index || 0===$index){
$upType = '外观';
$dirs = count(explode('/', $zip->getNameIndex($index)));
if($dirs>2){
$this->showMsg('压缩路径太深,无法正常安装', $up, TRUE) ;
}
$contents = $zip->getFromIndex($index);
if($this->isTheme($contents)){
if(2==$dirs){
$path='.' . __TYPECHO_THEME_DIR__.'/';
}else{
$name = basename($_FILES['file']['name'],'.zip');
$path='.' . __TYPECHO_THEME_DIR__ .'/'. $name.'/';
}
}
}
}
}
if($path!==''){
if($zip->extractTo($path)){
$zip->close();
$this->showMsg("安装成功,请到 控制台-->" . $upType . " 中激活使用。", $up, TRUE);
}else{
$this->showMsg("解压失败,请确认" . $upType . "目录是否有写权限。", $up) ;
}
} else {
$this->showMsg('上传的文件不是Typecho插件和模板', $up);
}
} else {
$this->showMsg('无法打开压缩包,请检查压缩包是否损坏。', $up);
}
@unlink($this->_file);
}else{
$this->widget('Widget_Archive@404', 'type=404')->render();
exit;
}
}
public function showMsg($str, $up = True, $exit=FALSE){
if($up && !$exit){
//echo("");
$this->widget('Widget_Notice')->set(_t($str), NULL, 'error');
}
if($up && $exit){
@unlink($this->_file);
//exit("");
$this->widget('Widget_Notice')->set(_t($str), NULL, 'success');
}
if(!$up && $exit){
@unlink($this->_file);
exit($str);
}
if(!$up && !$exit) echo($str);
}
/**
* 判断上传文件是否为插件
* @param type $contents
* @return boolean
*/
public function isPlugin($contents){
$info = $this->parseInfo($contents);
if( $info['description']!=="" && $info['name']!=="" && !empty($info['version']) && !empty($info['author'])){
return $info['name'] ;
}else{
return FALSE;
}
}
/**
* 判断上传文件是否为模板
* @param type $contents
* @return boolean
*/
public function isTheme($contents){
$info = $this->parseInfo($contents);
if($info['title']!=="" && !empty($info['version']) && !empty($info['author'])){
return TRUE;
}else{
return FALSE;
}
}
/**
*
* @param type $file
* @return boolean
*/
public function isZip($file){
$file = @fopen($file,"rb");
$bin = fread($file, 15);
fclose($file);
$blen=strlen(pack("H*","504B0304")); //得到文件头标记字节数
$tbin=substr($bin,0,intval($blen)); ///需要比较文件头长度
$upack = unpack("H*",$tbin);
if(strtolower("504B0304")==strtolower(array_shift($upack)))
{
return TRUE;
} else {
return FALSE;
}
}
//解析Plugin.php文件
public function parseInfo($pluginFile)
{
$tokens = token_get_all($pluginFile);
$isDoc = false;
$isClass = false;
/** 初始信息 */
$info = array(
'name' => '',
'description' => '',
'title' => '',
'author' => '',
'homepage' => '',
'version' => '',
'dependence' => '',
);
$map = array(
'package' => 'title',
'author' => 'author',
'link' => 'homepage',
'dependence'=> 'dependence',
'version' => 'version'
);
foreach ($tokens as $token) {
/** 获取doc comment */
if (!$isDoc && is_array($token) && T_DOC_COMMENT == $token[0]) {
/** 分行读取 */
$described = false;
$lines = preg_split("(\r|\n)", $token[1]);
foreach ($lines as $line) {
$line = trim($line);
if (!empty($line) && '*' == $line[0]) {
$line = trim(substr($line, 1));
if (!$described && !empty($line) && '@' == $line[0]) {
$described = true;
}
if (!$described && !empty($line)) {
$info['description'] .= $line . "\n";
} else if ($described && !empty($line) && '@' == $line[0]) {
$info['description'] = trim($info['description']);
$line = trim(substr($line, 1));
$args = explode(' ', $line);
$key = array_shift($args);
if (isset($map[$key])) {
$info[$map[$key]] = trim(implode(' ', $args));
}
}
}
}
$isDoc = true;
}
if (!$isClass && is_array($token) && T_CLASS == $token[0]) {
$isClass = true;
}
if ($isClass && is_array($token) && T_STRING == $token[0]){
$name=explode('_',$token[1]);
$info['name']=$name[0];
break;
}
}
return $info;
}
public function action()
{
$this->widget('Widget_User')->pass('administrator');
$this->on($this->request->is('del'))->del($this->request->del);
$this->on($this->request->is('delTheme'))->delTheme($this->request->delTheme);
$this->on($this->request->is('upload'))->upload($this->request->upload);
$this->response->goBack();
}
}
?>