Delete ability to install or update third-party software via FTP/SFTP

This commit is contained in:
Kijin Sung 2020-09-06 15:07:43 +09:00
parent 215f143e70
commit 49b95477b0
8 changed files with 19 additions and 632 deletions

View file

@ -185,7 +185,6 @@ class admin extends ModuleObject
),
'configuration' => array(
'admin.adminConfigurationGeneral',
'admin.adminConfigurationFtp',
'admin.adminMenuSetup',
'module.filebox',
),

View file

@ -334,6 +334,7 @@ $lang->cmd_admin_menu_reset = 'Initialize admin menu';
$lang->confirm_reset_admin_menu = 'Are you sure initialize the admin menu?';
$lang->cmd_view_server_env = 'View Server Env.';
$lang->server_env = 'Server Environment';
$lang->ftp_deprecated = 'FTP functionality is deprecated in Rhymix.<br>If you are having difficulty installing and updating third-party software, please check your server permissions.';
$lang->ftp_form_title = 'FTP Account Information';
$lang->ftp = 'FTP';
$lang->ftp_host = 'FTP hostname';

View file

@ -330,6 +330,7 @@ $lang->cmd_admin_menu_reset = '관리자 메뉴 초기화';
$lang->confirm_reset_admin_menu = '관리자 메뉴를 초기화하시겠습니까?';
$lang->cmd_view_server_env = '서버 환경 표시';
$lang->server_env = '서버 환경';
$lang->ftp_deprecated = 'FTP 기능은 Rhymix에서 삭제되었습니다.<br>자료 설치 및 업데이트가 되지 않는 경우 퍼미션 조정으로 해결하십시오.';
$lang->ftp_form_title = 'FTP 계정 정보 입력';
$lang->ftp = 'FTP';
$lang->ftp_host = 'FTP 서버 주소';

View file

@ -6,6 +6,12 @@
<div class="x_page-header">
<h1>{$lang->menu_gnb_sub['adminConfigurationFtp']}</h1>
</div>
<div class="message">
<p>{$lang->ftp_deprecated}</p>
</div>
<!--@if(FALSE)-->
<div cond="$XE_VALIDATOR_MESSAGE && $XE_VALIDATOR_ID == 'modules/admin/tpl/config_ftp/1'" class="message {$XE_VALIDATOR_MESSAGE_TYPE}">
<p>{$XE_VALIDATOR_MESSAGE}</p>
</div>
@ -73,3 +79,4 @@
<input type="submit" value="{$lang->cmd_save}" class="x_btn x_btn-primary x_pull-right" />
</div>
</form>
<!--@end-->

View file

@ -190,17 +190,7 @@ class autoinstallAdminController extends autoinstall
$oModel = getModel('autoinstall');
$oAdminModel = getAdminModel('autoinstall');
$packages = explode(',', $package_srls);
$ftp_info = Context::getFTPInfo();
if(!$_SESSION['ftp_password'])
{
$ftp_password = Context::get('ftp_password');
}
else
{
$ftp_password = $_SESSION['ftp_password'];
}
$isSftpSupported = function_exists(ssh2_sftp);
foreach($packages as $package_srl)
{
$package = $oModel->getPackage($package_srl);
@ -210,28 +200,16 @@ class autoinstallAdminController extends autoinstall
continue;
}
if($oAdminModel->checkUseDirectModuleInstall($package)->toBool())
if(!$oAdminModel->checkUseDirectModuleInstall($package)->toBool())
{
$oModuleInstaller = new DirectModuleInstaller($package);
}
else if($ftp_info->sftp && $ftp_info->sftp == 'Y' && $isSftpSupported)
{
$oModuleInstaller = new SFTPModuleInstaller($package);
}
else if(function_exists(ftp_connect))
{
$oModuleInstaller = new PHPFTPModuleInstaller($package);
}
else
{
$oModuleInstaller = new FTPModuleInstaller($package);
return new BaseObject(-1, 'msg_no_permission_to_install');
}
$oAdminModel = getAdminModel('autoinstall');
$config = $oAdminModel->getAutoInstallAdminModuleConfig();
$oModuleInstaller = new DirectModuleInstaller($package);
$oModuleInstaller->setServerUrl($config->download_server);
$oModuleInstaller->setPassword($ftp_password);
//$oModuleInstaller->setPassword($ftp_password);
$output = $oModuleInstaller->install();
if(!$output->toBool())
{
@ -371,44 +349,17 @@ class autoinstallAdminController extends autoinstall
private function _uninstallPackage($package)
{
$path = $package->path;
$oAdminModel = getAdminModel('autoinstall');
if(!$_SESSION['ftp_password'])
if(!$oAdminModel->checkUseDirectModuleInstall($package)->toBool())
{
$ftp_password = Context::get('ftp_password');
}
else
{
$ftp_password = $_SESSION['ftp_password'];
}
$ftp_info = Context::getFTPInfo();
$isSftpSupported = function_exists(ssh2_sftp);
if($oAdminModel->checkUseDirectModuleInstall($package)->toBool())
{
$oModuleInstaller = new DirectModuleInstaller($package);
}
else if($ftp_info->sftp && $ftp_info->sftp == 'Y' && $isSftpSupported)
{
$oModuleInstaller = new SFTPModuleInstaller($package);
}
else if(function_exists('ftp_connect'))
{
$oModuleInstaller = new PHPFTPModuleInstaller($package);
}
else
{
$oModuleInstaller = new FTPModuleInstaller($package);
return new BaseObject(-1, 'msg_no_permission_to_install');
}
$oAdminModel = getAdminModel('autoinstall');
$config = $oAdminModel->getAutoInstallAdminModuleConfig();
$oModuleInstaller = new DirectModuleInstaller($package);
$oModuleInstaller->setServerUrl($config->download_server);
$oModuleInstaller->setPassword($ftp_password);
//$oModuleInstaller->setPassword($ftp_password);
$output = $oModuleInstaller->uninstall();
if(!$output->toBool())
{

View file

@ -313,580 +313,6 @@ class ModuleInstaller
}
/**
* Module installer for SFTP
* @author NAVER (developers@xpressengine.com)
*/
class SFTPModuleInstaller extends ModuleInstaller
{
/**
* FTP information
* @var object
*/
var $ftp_info = NULL;
/**
* SFTP connection
* @var resource
*/
var $connection = NULL;
/**
* SFTP resource
* @var resource
*/
var $sftp = NULL;
/**
* Constructor
*
* @param object $package Package information
* @return void
*/
function __construct(&$package)
{
$this->package = &$package;
$this->ftp_info = Context::getFTPInfo();
}
/**
* Connect to SFTP
*
* @return Object
*/
function _connect()
{
if(!function_exists('ssh2_connect'))
{
return new BaseObject(-1, 'msg_sftp_not_supported');
}
if(!$this->ftp_info->ftp_user || !$this->ftp_info->sftp || $this->ftp_info->sftp != 'Y')
{
return new BaseObject(-1, 'msg_ftp_invalid_auth_info');
}
if($this->ftp_info->ftp_host)
{
$ftp_host = $this->ftp_info->ftp_host;
}
else
{
$ftp_host = "127.0.0.1";
}
$this->connection = ssh2_connect($ftp_host, $this->ftp_info->ftp_port);
if(!@ssh2_auth_password($this->connection, $this->ftp_info->ftp_user, $this->ftp_password))
{
return new BaseObject(-1, 'msg_ftp_invalid_auth_info');
}
$_SESSION['ftp_password'] = $this->ftp_password;
$this->sftp = ssh2_sftp($this->connection);
return new BaseObject();
}
/**
* Close
*
* @return void
*/
function _close()
{
}
/**
* Remove file
*
* @param string $path Path to remove
* @return Object
*/
function _removeFile($path)
{
if(substr($path, 0, 2) == "./")
{
$path = substr($path, 2);
}
$target_path = $this->ftp_info->ftp_root_path . $path;
if(!@ssh2_sftp_unlink($this->sftp, $target_path))
{
return new BaseObject(-1, sprintf(lang('msg_delete_file_failed'), $path));
}
return new BaseObject();
}
/**
* Remove Directory
*
* @param string $path Path to remove
* @return Object
*/
function _removeDir_real($path)
{
if(substr($path, 0, 2) == "./")
{
$path = substr($path, 2);
}
$target_path = $this->ftp_info->ftp_root_path . $path;
if(!@ssh2_sftp_rmdir($this->sftp, $target_path))
{
return new BaseObject(-1, sprintf(lang('msg_delete_dir_failed'), $path));
}
return new BaseObject();
}
/**
* Copy directory
*
* @param array $file_list File list to copy
* @return Object
*/
function _copyDir(&$file_list)
{
if(!$this->ftp_password)
{
return new BaseObject(-1, 'msg_ftp_password_input');
}
$output = $this->_connect();
if(!$output->toBool())
{
return $output;
}
$target_dir = $this->ftp_info->ftp_root_path . $this->target_path;
$copied = array();
if(is_array($file_list))
{
foreach($file_list as $k => $file)
{
$org_file = $file;
if($this->package->path == ".")
{
$file = substr($file, 3);
}
$path = FileHandler::getRealPath("./" . $this->target_path . "/" . $file);
$pathname = dirname($target_dir . "/" . $file);
if(!file_exists(FileHandler::getRealPath($real_path)))
{
ssh2_sftp_mkdir($this->sftp, $pathname, 0755, TRUE);
}
ssh2_scp_send($this->connection, FileHandler::getRealPath($this->download_path . "/" . $org_file), $target_dir . "/" . $file);
$copied[] = $path;
}
}
FileHandler::clearStatCache($copied, true);
FileHandler::invalidateOpcache($copied);
return new BaseObject();
}
}
/**
* Module installer for PHP FTP
* @author NAVER (developers@xpressengine.com)
*/
class PHPFTPModuleInstaller extends ModuleInstaller
{
/**
* FTP information
* @var object
*/
var $ftp_info = NULL;
/**
* FTP connection
* @var resource
*/
var $connection = NULL;
/**
* Constructor
*
* @param object $package Package information
* @var void
*/
function __construct(&$package)
{
$this->package = &$package;
$this->ftp_info = Context::getFTPInfo();
}
/**
* Connect to FTP
*
* @return Object
*/
function _connect()
{
if($this->ftp_info->ftp_host)
{
$ftp_host = $this->ftp_info->ftp_host;
}
else
{
$ftp_host = "127.0.0.1";
}
$this->connection = ftp_connect($ftp_host, $this->ftp_info->ftp_port);
if(!$this->connection)
{
return new BaseObject(-1, sprintf(lang('msg_ftp_not_connected'), 'host'));
}
$login_result = @ftp_login($this->connection, $this->ftp_info->ftp_user, $this->ftp_password);
if(!$login_result)
{
$this->_close();
return new BaseObject(-1, 'msg_ftp_invalid_auth_info');
}
$_SESSION['ftp_password'] = $this->ftp_password;
if($this->ftp_info->ftp_pasv != "N")
{
ftp_pasv($this->connection, TRUE);
}
return new BaseObject();
}
/**
* Remove file
*
* @param string $path Path to remove
* @return Object
*/
function _removeFile($path)
{
if(substr($path, 0, 2) == "./")
{
$path = substr($path, 2);
}
$target_path = $this->ftp_info->ftp_root_path . $path;
if(!@ftp_delete($this->connection, $target_path))
{
return new BaseObject(-1, "failed to delete file " . $path);
}
return new BaseObject();
}
/**
* Remove directory
*
* @param string $path Path to remove
* @return Object
*/
function _removeDir_real($path)
{
if(substr($path, 0, 2) == "./")
{
$path = substr($path, 2);
}
$target_path = $this->ftp_info->ftp_root_path . $path;
if(!@ftp_rmdir($this->connection, $target_path))
{
return new BaseObject(-1, "failed to delete directory " . $path);
}
return new BaseObject();
}
/**
* Close
*
* @return void
*/
function _close()
{
ftp_close($this->connection);
}
/**
* Copy directory
*
* @param array $file_list File list to copy
* @return Object
*/
function _copyDir(&$file_list)
{
if(!$this->ftp_password)
{
return new BaseObject(-1, 'msg_ftp_password_input');
}
$output = $this->_connect();
if(!$output->toBool())
{
return $output;
}
if(!$this->target_path)
{
$this->target_path = '.';
}
if(substr($this->download_path, -1) == '/')
{
$this->download_path = substr($this->download_path, 0, -1);
}
$target_dir = $this->ftp_info->ftp_root_path . $this->target_path;
$copied = array();
if(is_array($file_list))
{
foreach($file_list as $k => $file)
{
if(!$file)
{
continue;
}
$org_file = $file;
if($this->package->path == ".")
{
$file = substr($file, 3);
}
$path = FileHandler::getRealPath("./" . $this->target_path . "/" . $file);
$path_list = explode('/', dirname($this->target_path . "/" . $file));
$real_path = "./";
$ftp_path = $this->ftp_info->ftp_root_path;
for($i = 0; $i < count($path_list); $i++)
{
if($path_list == "")
{
continue;
}
$real_path .= $path_list[$i] . "/";
$ftp_path .= $path_list[$i] . "/";
if(!file_exists(FileHandler::getRealPath($real_path)))
{
if(!@ftp_mkdir($this->connection, $ftp_path))
{
return new BaseObject(-1, "msg_make_directory_failed");
}
if(strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
{
if(function_exists('ftp_chmod'))
{
if(!ftp_chmod($this->connection, 0755, $ftp_path))
{
return new BaseObject(-1, "msg_permission_adjust_failed");
}
}
else
{
if(!ftp_site($this->connection, "CHMOD 755 " . $ftp_path))
{
return new BaseObject(-1, "msg_permission_adjust_failed");
}
}
}
}
}
if(!ftp_put($this->connection, $target_dir . '/' . $file, FileHandler::getRealPath($this->download_path . "/" . $org_file), FTP_BINARY))
{
return new BaseObject(-1, "msg_ftp_upload_failed");
}
$copied[] = $path;
}
}
FileHandler::clearStatCache($copied, true);
FileHandler::invalidateOpcache($copied);
$this->_close();
return new BaseObject();
}
}
/**
* Module installer for FTP
* @author NAVER (developers@xpressengine.com)
*/
class FTPModuleInstaller extends ModuleInstaller
{
/**
* FTP instance
* @var FTP
*/
var $oFtp = NULL;
/**
* FTP information
* @var object
*/
var $ftp_info = NULL;
/**
* Constructor
*
* @param object $package Package information
*/
function __construct(&$package)
{
$this->package = &$package;
$this->ftp_info = Context::getFTPInfo();
}
/**
* Connect to FTP
*
* @return Object
*/
function _connect()
{
if($this->ftp_info->ftp_host)
{
$ftp_host = $this->ftp_info->ftp_host;
}
else
{
$ftp_host = "127.0.0.1";
}
$this->oFtp = new ftp();
if(!$this->oFtp->ftp_connect($ftp_host, $this->ftp_info->ftp_port))
{
return new BaseObject(-1, sprintf(lang('msg_ftp_not_connected'), 'host'));
}
if(!$this->oFtp->ftp_login($this->ftp_info->ftp_user, $this->ftp_password))
{
$this->_close();
return new BaseObject(-1, 'msg_ftp_invalid_auth_info');
}
$_SESSION['ftp_password'] = $this->ftp_password;
return new BaseObject();
}
/**
* Remove file
*
* @param string $path Path to remove
* @return Object
*/
function _removeFile($path)
{
if(substr($path, 0, 2) == "./")
{
$path = substr($path, 2);
}
$target_path = $this->ftp_info->ftp_root_path . $path;
if(!$this->oFtp->ftp_delete($target_path))
{
return new BaseObject(-1, sprintf(lang('msg_delete_file_failed'), $path));
}
return new BaseObject();
}
/**
* Remove directory
* @param string $path Path to remove
* @return Object
*/
function _removeDir_real($path)
{
if(substr($path, 0, 2) == "./")
{
$path = substr($path, 2);
}
$target_path = $this->ftp_info->ftp_root_path . $path;
if(!$this->oFtp->ftp_rmdir($target_path))
{
return new BaseObject(-1, sprintf(lang('msg_delete_dir_failed'), $path));
}
return new BaseObject();
}
/**
* Close
*
* @return void
*/
function _close()
{
$this->oFtp->ftp_quit();
}
/**
* Copy directory
*
* @param array $file_list File list to copy
* @return Object
*/
function _copyDir(&$file_list)
{
if(!$this->ftp_password)
{
return new BaseObject(-1, 'msg_ftp_password_input');
}
$output = $this->_connect();
if(!$output->toBool())
{
return $output;
}
$oFtp = &$this->oFtp;
$target_dir = $this->ftp_info->ftp_root_path . $this->target_path;
$copied = array();
if(is_array($file_list))
{
foreach($file_list as $k => $file)
{
$org_file = $file;
if($this->package->path == ".")
{
$file = substr($file, 3);
}
$path = FileHandler::getRealPath("./" . $this->target_path . "/" . $file);
$path_list = explode('/', dirname($this->target_path . "/" . $file));
$real_path = "./";
$ftp_path = $this->ftp_info->ftp_root_path;
for($i = 0; $i < count($path_list); $i++)
{
if($path_list == "")
{
continue;
}
$real_path .= $path_list[$i] . "/";
$ftp_path .= $path_list[$i] . "/";
if(!file_exists(FileHandler::getRealPath($real_path)))
{
$oFtp->ftp_mkdir($ftp_path);
$oFtp->ftp_site("CHMOD 755 " . $ftp_path);
}
}
$oFtp->ftp_put($target_dir . '/' . $file, FileHandler::getRealPath($this->download_path . "/" . $org_file));
$copied[] = $path;
}
}
FileHandler::clearStatCache($copied, true);
FileHandler::invalidateOpcache($copied);
$this->_close();
return new BaseObject();
}
}
/**
* Module installer for Direct. Not use FTP
* @author NAVER (developers@xpressengine.com)

View file

@ -39,6 +39,7 @@ $lang->msg_delete_file_failed = 'Failed to delete the file. %s.';
$lang->msg_delete_dir_failed = 'Failed to delete the directory. %s';
$lang->msg_ftp_password_input = 'No password entered.';
$lang->msg_sftp_not_supported = 'SFTP is not supported.';
$lang->msg_no_permission_to_install = 'Your web server does not have permission to update the installation path. Please check server permissions.';
$lang->msg_direct_install_not_supported = 'Use FTP because there is no write permission to the directories listed in the list below.';
$lang->msg_does_not_support_delete = 'Cannot delete this package (no moduleUninstall() in the module class).';
$lang->installed = 'Installed';

View file

@ -39,6 +39,7 @@ $lang->msg_delete_file_failed = '파일 삭제에 실패했습니다. %s.';
$lang->msg_delete_dir_failed = '디렉터리 삭제에 실패했습니다. %s';
$lang->msg_ftp_password_input = '입력된 비밀번호가 없습니다.';
$lang->msg_sftp_not_supported = 'SFTP를 지원하지 않는 환경입니다.';
$lang->msg_no_permission_to_install = '설치 경로에 쓰기 권한이 없습니다. 퍼미션을 확인해 주십시오.';
$lang->msg_direct_install_not_supported = '아래 목록에 나열된 디렉터리에 쓰기 권한이 없기 때문에 FTP를 사용합니다.';
$lang->msg_does_not_support_delete = '이 패키지가 삭제를 지원하지 않습니다(모듈 클래스에 moduleUninstall()이 없음).';
$lang->msg_update_core_title = 'Rhymix core가 업데이트 됩니다.';