202 lines
5.1 KiB
PHP
202 lines
5.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Vvveb
|
|
*
|
|
* Copyright (C) 2022 Ziadin Givan
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
namespace Vvveb\Controller\Editor;
|
|
|
|
use function Vvveb\__;
|
|
use Vvveb\Controller\Base;
|
|
use function Vvveb\sanitizeFileName;
|
|
|
|
class Code extends Base {
|
|
protected $saveDenyExtensions = ['php', 'tpl'];
|
|
|
|
function dirForType($type) {
|
|
switch ($type) {
|
|
case 'public':
|
|
$scandir = DIR_MEDIA;
|
|
|
|
break;
|
|
|
|
case 'plugins':
|
|
$scandir = DIR_PLUGINS;
|
|
|
|
break;
|
|
|
|
case 'themes':
|
|
$scandir = DIR_THEMES;
|
|
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
return $scandir;
|
|
}
|
|
|
|
function index() {
|
|
$type = $this->request->get['type'] ?? false;
|
|
$admin_path = \Vvveb\adminPath();
|
|
$controllerPath = $admin_path . 'index.php?module=editor/code';
|
|
|
|
if (! $type) {
|
|
return;
|
|
}
|
|
$this->view->scanUrl = "$controllerPath&action=scan&type=$type";
|
|
$this->view->uploadUrl = "$controllerPath&action=upload&type=$type";
|
|
$this->view->loadFileUrl = "$controllerPath&action=loadFile&type=$type";
|
|
$this->view->saveUrl = "$controllerPath&action=save&type=$type";
|
|
$this->view->type = $type;
|
|
|
|
if ($type) {
|
|
$this->view->mediaPath = str_replace('/media', "/$type", $this->view->mediaPath);
|
|
}
|
|
}
|
|
|
|
function sanitizeFileName($file, $type) {
|
|
if (V_SUBDIR_INSTALL && strpos($file, V_SUBDIR_INSTALL) === 0) {
|
|
//$path = str_replace(V_SUBDIR_INSTALL, '', $path);
|
|
$file = substr_replace($file, '', 0, strlen(V_SUBDIR_INSTALL));
|
|
}
|
|
|
|
$file = preg_replace("@^[\/]public@", '', $file);
|
|
|
|
if ($type == 'plugins') {
|
|
$file = DIR_PLUGINS . preg_replace("@^[\/]plugins[\/]@", '', $file);
|
|
} else {
|
|
if ($type == 'themes') {
|
|
$file = DIR_THEMES . preg_replace("@^[\/]themes[\/]@", '', $file);
|
|
} else {
|
|
$file = DIR_PUBLIC . $file;
|
|
}
|
|
}
|
|
|
|
$file = sanitizeFileName($file);
|
|
|
|
return $file;
|
|
}
|
|
|
|
function save() {
|
|
$type = $this->request->get['type'];
|
|
$file = $this->request->get['file'];
|
|
$content = $this->request->post['content'];
|
|
$file = $this->sanitizeFileName($file, $type);
|
|
|
|
$message = ['success' => false, 'message' => sprintf(__('Error saving: %s!'), $file)];
|
|
|
|
$extension = strtolower(substr($file, strrpos($file, '.') + 1));
|
|
|
|
if (in_array($extension, $this->saveDenyExtensions)) {
|
|
$message = ['success' => false, 'message' => sprintf(__('Saving not allowed for file type %s!'), trim($extension, '.'))];
|
|
$success = false;
|
|
} else {
|
|
if (! is_writable($file)) {
|
|
$message = ['success' => false, 'message' => sprintf(__('File not writable: %s Check if file has write permission.'), $file)];
|
|
} else {
|
|
if (file_put_contents($file, $content)) {
|
|
$message = ['success' => true, 'message' => __('File saved!')];
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->response->setType('json');
|
|
$this->response->output($message);
|
|
}
|
|
|
|
function loadFile() {
|
|
$type = $this->request->get['type'];
|
|
$file = $this->request->get['file'];
|
|
$file = $this->sanitizeFileName($file, $type);
|
|
|
|
if (! is_readable($file)) {
|
|
die("File not readable: $file");
|
|
}
|
|
|
|
if ($content = file_get_contents($file)) {
|
|
die($content);
|
|
}
|
|
|
|
die("Error loading: $file");
|
|
}
|
|
|
|
function scan() {
|
|
$type = $this->request->get['type'] ?? 'public';
|
|
$scandir = $this->dirForType($type);
|
|
|
|
if (! $scandir) {
|
|
return [];
|
|
}
|
|
|
|
// This function scans the files folder recursively, and builds a large array
|
|
$scan = function ($dir) use ($scandir, &$scan) {
|
|
$files = [];
|
|
|
|
// Is there actually such a folder/file?
|
|
|
|
if (file_exists($dir)) {
|
|
$listdir = @scandir($dir);
|
|
|
|
if ($listdir) {
|
|
foreach ($listdir as $f) {
|
|
if (! $f || $f[0] == '.' || $f == 'node_modules' || $f == 'vendor') {
|
|
continue; // Ignore hidden files
|
|
}
|
|
|
|
if (is_dir($dir . DS . $f)) {
|
|
// The path is a folder
|
|
|
|
$files[] = [
|
|
'name' => $f,
|
|
'type' => 'folder',
|
|
'path' => str_replace([$scandir, '\\'], ['', '/'], $dir) . '/' . $f,
|
|
'items' => $scan($dir . DS . $f), // Recursively get the contents of the folder
|
|
];
|
|
} else {
|
|
// It is a file
|
|
|
|
$files[] = [
|
|
'name' => $f,
|
|
'type' => 'file',
|
|
'path' => str_replace([$scandir, '\\'], ['', '/'], $dir) . '/' . $f,
|
|
'size' => @filesize($dir . DS . $f), // Gets the size of this file
|
|
];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $files;
|
|
};
|
|
|
|
$response = $scan($scandir);
|
|
|
|
// Output the directory listing as JSON
|
|
$this->response->setType('json');
|
|
$this->response->output([
|
|
'name' => '',
|
|
'type' => 'folder',
|
|
'path' => '',
|
|
'items' => $response,
|
|
]);
|
|
}
|
|
}
|