|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Api Controller
|
|
|
|
*/
|
|
|
|
require_once __DIR__ . '/../lib/DirScanner.php';
|
|
|
|
|
|
|
|
//引入验证码类
|
|
|
|
require_once __DIR__ . '/../plugins/Captcha/vendor/autoload.php';
|
|
|
|
use Gregwar\Captcha\CaptchaBuilder;
|
|
|
|
|
|
|
|
Class ApiController extends Controller {
|
|
|
|
protected $version = '1.0';
|
|
|
|
|
|
|
|
//show api list
|
|
|
|
public function actionIndex() {
|
|
|
|
$params = array(
|
|
|
|
'version' => $this->version,
|
|
|
|
'list' => array(
|
|
|
|
'列表' => '/api/ls/',
|
|
|
|
|
|
|
|
//文件操作
|
|
|
|
'重命名' => '/api/rename/',
|
|
|
|
'删除文件' => '/api/delete/',
|
|
|
|
'移动' => '/api/move/',
|
|
|
|
|
|
|
|
//目录操作
|
|
|
|
'创建目录' => '/api/mkdir/',
|
|
|
|
'删除目录' => '/api/rmdir/',
|
|
|
|
),
|
|
|
|
);
|
|
|
|
return $this->renderJson($params);
|
|
|
|
}
|
|
|
|
|
|
|
|
//目录、文件列表
|
|
|
|
public function actionLs() {
|
|
|
|
$code = 0;
|
|
|
|
$msg = $err = '';
|
|
|
|
$data = array();
|
|
|
|
|
|
|
|
|
|
|
|
$scanner = new DirScanner();
|
|
|
|
$scanner->setWebRoot(FSC::$app['config']['content_directory']);
|
|
|
|
$target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory'];
|
|
|
|
$maxLevels = 2;
|
|
|
|
$dirTree = $scanner->scan($target, $maxLevels);
|
|
|
|
$scanResults = $scanner->getScanResults();
|
|
|
|
|
|
|
|
//获取目录
|
|
|
|
$menus = $scanner->getMenus();
|
|
|
|
if (empty($menus)) {
|
|
|
|
$err = '没有任何目录/文件';
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
//排序
|
|
|
|
$menus_sorted = array(); //Readme_sort.txt 说明文件内容,一级目录菜单从上到下的排序
|
|
|
|
$readmeFile = $scanner->getDefaultReadme();
|
|
|
|
if (!empty($readmeFile)) {
|
|
|
|
if (!empty($readmeFile['sort'])) {
|
|
|
|
$menus_sorted = explode("\n", $readmeFile['sort']);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$sortedTree = $this->sortMenusAndDirTree($menus_sorted, $menus, $dirTree);
|
|
|
|
if (!empty($sortedTree)) {
|
|
|
|
$menus = $sortedTree['menus'];
|
|
|
|
$dirTree = $sortedTree['dirTree'];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$cateId = $this->get('id', $menus[0]['id']);
|
|
|
|
$data['menus'] = $menus;
|
|
|
|
$data['dirTree'] = $scanResults[$cateId];
|
|
|
|
|
|
|
|
$code = 1;
|
|
|
|
$msg = '';
|
|
|
|
$err = '';
|
|
|
|
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
//创建目录
|
|
|
|
//创建成功则在data中返回父目录数据结构
|
|
|
|
public function actionMkdir() {
|
|
|
|
$code = 0;
|
|
|
|
$msg = $err = '';
|
|
|
|
$data = array();
|
|
|
|
|
|
|
|
|
|
|
|
$parentDir = $this->post('parent', '');
|
|
|
|
$newDir = $this->post('dir', '');
|
|
|
|
$maxDirLen = 20;
|
|
|
|
if (empty($newDir) || mb_strlen($newDir, 'utf-8') > $maxDirLen) {
|
|
|
|
$err = "目录名不能为空且最长 {$maxDirLen} 个字符";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}else if (strpos($newDir, '/') !== false) {
|
|
|
|
$err = "待创建的目录名称中不能包含斜杠字符!";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory'];
|
|
|
|
if (!empty($parentDir)) {
|
|
|
|
$target = "{$target}/{$parentDir}";
|
|
|
|
}
|
|
|
|
if (!is_dir($target)) {
|
|
|
|
$err = "父目录{$parentDir}不存在";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$res = mkdir("{$target}/{$newDir}");
|
|
|
|
if ($res) {
|
|
|
|
//读取父目录数据,并返回包含新建的子目录在内的新数据
|
|
|
|
$scanner = new DirScanner();
|
|
|
|
$scanner->setWebRoot(FSC::$app['config']['content_directory']);
|
|
|
|
$maxLevels = 2;
|
|
|
|
$data = $scanner->scan($target, $maxLevels);
|
|
|
|
|
|
|
|
$code = 1;
|
|
|
|
$msg = '目录创建完成';
|
|
|
|
}else {
|
|
|
|
$err = '目录创建失败,请确认参数格式正确及父目录权限配置正确!';
|
|
|
|
}
|
|
|
|
}catch(Exception $e) {
|
|
|
|
$err = $e->getMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
//删除目录
|
|
|
|
public function actionRmdir() {
|
|
|
|
$code = 0;
|
|
|
|
$msg = $err = '';
|
|
|
|
$data = array();
|
|
|
|
|
|
|
|
|
|
|
|
$parentDir = $this->post('parent', '');
|
|
|
|
$delDir = $this->post('dir', '');
|
|
|
|
$maxDirLen = 20;
|
|
|
|
if (empty($delDir) || mb_strlen($delDir, 'utf-8') > $maxDirLen) {
|
|
|
|
$err = "目录名不能为空且最长 {$maxDirLen} 个字符";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}else if (strpos($delDir, '/') !== false) {
|
|
|
|
$err = "待删除的目录名称中不能包含斜杠字符!";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory'];
|
|
|
|
if (!empty($parentDir)) {
|
|
|
|
$target = "{$target}/{$parentDir}";
|
|
|
|
}
|
|
|
|
if (!is_dir($target)) {
|
|
|
|
$err = "父目录{$parentDir}不存在";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$res = rmdir("{$target}/{$delDir}");
|
|
|
|
if ($res) {
|
|
|
|
$code = 1;
|
|
|
|
$msg = '目录删除完成';
|
|
|
|
}else {
|
|
|
|
$err = '目录删除失败,请确认被删除目录存在及父目录权限配置正确!';
|
|
|
|
}
|
|
|
|
}catch(Exception $e) {
|
|
|
|
$err = $e->getMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
//移动目录或文件
|
|
|
|
public function actionMove() {
|
|
|
|
$code = 0;
|
|
|
|
$msg = $err = '';
|
|
|
|
$data = array();
|
|
|
|
|
|
|
|
|
|
|
|
$parentDir = $this->post('parent', '');
|
|
|
|
$fromDir = $this->post('from', '');
|
|
|
|
$toDir = $this->post('to', '');
|
|
|
|
$maxDirLen = 50;
|
|
|
|
if (empty($fromDir) || mb_strlen($fromDir, 'utf-8') > $maxDirLen || empty($toDir) || mb_strlen($toDir, 'utf-8') > $maxDirLen) {
|
|
|
|
$err = "目录名不能为空且最长 {$maxDirLen} 个字符";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory'];
|
|
|
|
if (!empty($parentDir)) {
|
|
|
|
$target = "{$target}/{$parentDir}";
|
|
|
|
}
|
|
|
|
if (!is_dir($target)) {
|
|
|
|
$err = "父目录{$parentDir}不存在";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$res = rename("{$target}/{$fromDir}", "{$target}/{$toDir}");
|
|
|
|
if ($res) {
|
|
|
|
$code = 1;
|
|
|
|
$msg = '目录/文件移动完成';
|
|
|
|
}else {
|
|
|
|
$err = '目录/文件移动失败,请确认被移动目录/文件存在及目标目录权限配置正确!';
|
|
|
|
}
|
|
|
|
}catch(Exception $e) {
|
|
|
|
$err = $e->getMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
//重命名目录或文件
|
|
|
|
public function actionRename() {
|
|
|
|
$code = 0;
|
|
|
|
$msg = $err = '';
|
|
|
|
$data = array();
|
|
|
|
|
|
|
|
|
|
|
|
$parentDir = $this->post('parent', '');
|
|
|
|
$fromDir = $this->post('from', '');
|
|
|
|
$toDir = $this->post('to', '');
|
|
|
|
$maxDirLen = 20;
|
|
|
|
if (empty($fromDir) || mb_strlen($fromDir, 'utf-8') > $maxDirLen || empty($toDir) || mb_strlen($toDir, 'utf-8') > $maxDirLen) {
|
|
|
|
$err = "目录名不能为空且最长 {$maxDirLen} 个字符";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}else if (strpos($fromDir, '/') !== false || strpos($toDir, '/') !== false) {
|
|
|
|
$err = "目录名称中不能包含斜杠字符!";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory'];
|
|
|
|
if (!empty($parentDir)) {
|
|
|
|
$target = "{$target}/{$parentDir}";
|
|
|
|
}
|
|
|
|
if (!is_dir($target)) {
|
|
|
|
$err = "父目录{$parentDir}不存在";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$res = rename("{$target}/{$fromDir}", "{$target}/{$toDir}");
|
|
|
|
if ($res) {
|
|
|
|
$code = 1;
|
|
|
|
$msg = '目录移动完成';
|
|
|
|
}else {
|
|
|
|
$err = '目录移动失败,请确认被移动目录存在及目标目录权限配置正确!';
|
|
|
|
}
|
|
|
|
}catch(Exception $e) {
|
|
|
|
$err = $e->getMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
//删除文件
|
|
|
|
public function actionDelete() {
|
|
|
|
$code = 0;
|
|
|
|
$msg = $err = '';
|
|
|
|
$data = array();
|
|
|
|
|
|
|
|
|
|
|
|
$parentDir = $this->post('parent', '');
|
|
|
|
$delFile = $this->post('file', '');
|
|
|
|
$maxDirLen = 30;
|
|
|
|
if (empty($delFile) || mb_strlen($delFile, 'utf-8') > $maxDirLen) {
|
|
|
|
$err = "文件名不能为空且最长 {$maxDirLen} 个字符";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}else if (strpos($delFile, '/') !== false) {
|
|
|
|
$err = "待删除的文件名称中不能包含斜杠字符!";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory'];
|
|
|
|
if (!empty($parentDir)) {
|
|
|
|
$target = "{$target}/{$parentDir}";
|
|
|
|
}
|
|
|
|
if (!is_dir($target)) {
|
|
|
|
$err = "父目录{$parentDir}不存在";
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$res = unlink("{$target}/{$delFile}");
|
|
|
|
if ($res) {
|
|
|
|
$code = 1;
|
|
|
|
$msg = '文件删除完成';
|
|
|
|
}else {
|
|
|
|
$err = '文件删除失败,请确认被删除文件存在及父目录权限配置正确!';
|
|
|
|
}
|
|
|
|
}catch(Exception $e) {
|
|
|
|
$err = $e->getMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
//验证码图片,data属性里返回图片base64编码格式
|
|
|
|
public function actionCaptcha() {
|
|
|
|
$code = 0;
|
|
|
|
$msg = $err = '';
|
|
|
|
$data = array();
|
|
|
|
|
|
|
|
$refresh = (int)$this->get('refresh', 0);
|
|
|
|
|
|
|
|
try {
|
|
|
|
$builder = new CaptchaBuilder;
|
|
|
|
$builder->build();
|
|
|
|
$captcha_jpg = $builder->get();
|
|
|
|
$captcha_code = $builder->getPhrase();
|
|
|
|
$data = 'data:image/jpeg;base64,' . base64_encode($captcha_jpg);
|
|
|
|
$code = 1;
|
|
|
|
$msg = '验证码图片已生成';
|
|
|
|
|
|
|
|
//save captcha code
|
|
|
|
$userData = $this->getAdmUserData();
|
|
|
|
$userData['captcha_code'] = $captcha_code;
|
|
|
|
$this->saveAdmUserData($userData);
|
|
|
|
}catch(Exception $e) {
|
|
|
|
$err = '验证码图片生成失败:' . $e->getMessage();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->renderJson(compact('code', 'msg', 'err', 'data'));
|
|
|
|
}
|
|
|
|
|
|
|
|
//从runtime/admin/目录里获取管理员当前ip相关的缓存数据
|
|
|
|
protected function getAdmUserData() {
|
|
|
|
$data = array();
|
|
|
|
|
|
|
|
$ip = $this->getUserIp();
|
|
|
|
$logDir = __DIR__ . '/../runtime/admin/';
|
|
|
|
$logFile = "{$logDir}{$ip}.cache";
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (file_exists($logFile)) {
|
|
|
|
$data = @json_decode(file_get_contents($logFile), true);
|
|
|
|
}
|
|
|
|
}catch(Exception $e) {}
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function saveAdmUserData($data) {
|
|
|
|
$ip = $this->getUserIp();
|
|
|
|
$logDir = __DIR__ . '/../runtime/admin/';
|
|
|
|
$logFile = "{$logDir}{$ip}.cache";
|
|
|
|
if (!is_dir($logDir)) { //try to mkdir
|
|
|
|
@mkdir($logDir, 0700, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
return @file_put_contents($logFile, json_encode($data));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|