mirror of
https://github.com/Yetangitu/ampache
synced 2025-10-03 09:49:30 +02:00
267 lines
9.8 KiB
PHP
267 lines
9.8 KiB
PHP
<?php
|
||
/* vim:set softtabstop=4 shiftwidth=4 expandtab: */
|
||
/**
|
||
*
|
||
* LICENSE: GNU General Public License, version 2 (GPLv2)
|
||
* Copyright 2001 - 2015 Ampache.org
|
||
*
|
||
* This program is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU General Public License v2
|
||
* as published by the Free Software Foundation.
|
||
*
|
||
* 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 General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program; if not, write to the Free Software
|
||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
*
|
||
*/
|
||
|
||
// jsTree file system browser
|
||
|
||
define('AJAX_INCLUDE','1');
|
||
|
||
require_once '../lib/init.php';
|
||
$rootdir = Upload::get_root();
|
||
if (empty($rootdir)) {
|
||
exit;
|
||
}
|
||
$rootdir .= DIRECTORY_SEPARATOR;
|
||
ini_set('open_basedir', $rootdir);
|
||
|
||
class fs
|
||
{
|
||
protected $base = null;
|
||
|
||
protected function real($path)
|
||
{
|
||
$temp = realpath($path);
|
||
if (!$temp) { throw new Exception('Path does not exist: ' . $path); }
|
||
if ($this->base && strlen($this->base)) {
|
||
if (strpos($temp, $this->base) !== 0) { throw new Exception('Path is not inside base ('.$this->base.'): ' . $temp); }
|
||
}
|
||
return $temp;
|
||
}
|
||
protected function path($id)
|
||
{
|
||
$id = str_replace('/', DIRECTORY_SEPARATOR, $id);
|
||
$id = trim($id, DIRECTORY_SEPARATOR);
|
||
$id = $this->real($this->base . DIRECTORY_SEPARATOR . $id);
|
||
return $id;
|
||
}
|
||
protected function id($path)
|
||
{
|
||
$path = $this->real($path);
|
||
$path = substr($path, strlen($this->base));
|
||
$path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
|
||
$path = trim($path, '/');
|
||
return strlen($path) ? $path : '/';
|
||
}
|
||
|
||
public function __construct($base)
|
||
{
|
||
$this->base = $this->real($base);
|
||
if (!$this->base) { throw new Exception('Base directory does not exist'); }
|
||
}
|
||
|
||
public function lst($id, $with_root = false)
|
||
{
|
||
$dir = $this->path($id);
|
||
$lst = @scandir($dir);
|
||
if (!$lst) { throw new Exception('Could not list path: ' . $dir); }
|
||
$res = array();
|
||
foreach ($lst as $item) {
|
||
if ($item == '.' || $item == '..' || $item === null) { continue; }
|
||
$tmp = preg_match('([^ a-zа-я-_0-9.]+)ui', $item);
|
||
if ($tmp === false || $tmp === 1) { continue; }
|
||
if (is_dir($dir . DIRECTORY_SEPARATOR . $item)) {
|
||
$res[] = array('text' => $item, 'children' => true, 'id' => $this->id($dir . DIRECTORY_SEPARATOR . $item), 'icon' => 'folder');
|
||
} else {
|
||
//$res[] = array('text' => $item, 'children' => false, 'id' => $this->id($dir . DIRECTORY_SEPARATOR . $item), 'type' => 'file', 'icon' => 'file file-'.substr($item, strrpos($item,'.') + 1));
|
||
}
|
||
}
|
||
if ($with_root && $this->id($dir) === '/') {
|
||
$res = array(array('text' => basename($this->base), 'children' => $res, 'id' => '/', 'icon'=>'folder', 'state' => array('opened' => true, 'disabled' => true)));
|
||
}
|
||
return $res;
|
||
}
|
||
|
||
public function data($id)
|
||
{
|
||
if (strpos($id, ":")) {
|
||
$id = array_map(array($this, 'id'), explode(':', $id));
|
||
return array('type'=>'multiple', 'content'=> 'Multiple selected: ' . implode(' ', $id));
|
||
}
|
||
$dir = $this->path($id);
|
||
if (is_dir($dir)) {
|
||
return array('type'=>'folder', 'content'=> $id);
|
||
}
|
||
if (is_file($dir)) {
|
||
$ext = strpos($dir, '.') !== FALSE ? substr($dir, strrpos($dir, '.') + 1) : '';
|
||
$dat = array('type' => $ext, 'content' => '');
|
||
switch ($ext) {
|
||
/*case 'txt':
|
||
case 'text':
|
||
case 'md':
|
||
case 'js':
|
||
case 'json':
|
||
case 'css':
|
||
case 'html':
|
||
case 'htm':
|
||
case 'xml':
|
||
case 'c':
|
||
case 'cpp':
|
||
case 'h':
|
||
case 'sql':
|
||
case 'log':
|
||
case 'py':
|
||
case 'rb':
|
||
case 'htaccess':
|
||
case 'php':
|
||
$dat['content'] = file_get_contents($dir);
|
||
break;
|
||
case 'jpg':
|
||
case 'jpeg':
|
||
case 'gif':
|
||
case 'png':
|
||
case 'bmp':
|
||
$dat['content'] = 'data:'.finfo_file(finfo_open(FILEINFO_MIME_TYPE), $dir).';base64,'.base64_encode(file_get_contents($dir));
|
||
break;*/
|
||
default:
|
||
$dat['content'] = 'File not recognized: '.$this->id($dir);
|
||
break;
|
||
}
|
||
return $dat;
|
||
}
|
||
throw new Exception('Not a valid selection: ' . $dir);
|
||
}
|
||
public function create($id, $name, $mkdir = false)
|
||
{
|
||
$dir = $this->path($id);
|
||
if (preg_match('([^ a-zа-я-_0-9.]+)ui', $name) || !strlen($name)) {
|
||
throw new Exception('Invalid name: ' . $name);
|
||
}
|
||
if ($mkdir) {
|
||
mkdir($dir . DIRECTORY_SEPARATOR . $name);
|
||
} else {
|
||
file_put_contents($dir . DIRECTORY_SEPARATOR . $name, '');
|
||
}
|
||
return array('id' => $this->id($dir . DIRECTORY_SEPARATOR . $name));
|
||
}
|
||
public function rename($id, $name)
|
||
{
|
||
$dir = $this->path($id);
|
||
if ($dir === $this->base) {
|
||
throw new Exception('Cannot rename root');
|
||
}
|
||
if (preg_match('([^ a-zа-я-_0-9.]+)ui', $name) || !strlen($name)) {
|
||
throw new Exception('Invalid name: ' . $name);
|
||
}
|
||
$new = explode(DIRECTORY_SEPARATOR, $dir);
|
||
array_pop($new);
|
||
array_push($new, $name);
|
||
$new = implode(DIRECTORY_SEPARATOR, $new);
|
||
if (is_file($new) || is_dir($new)) { throw new Exception('Path already exists: ' . $new); }
|
||
rename($dir, $new);
|
||
return array('id' => $this->id($new));
|
||
}
|
||
public function remove($id)
|
||
{
|
||
$dir = $this->path($id);
|
||
if ($dir === $this->base) {
|
||
throw new Exception('Cannot remove root');
|
||
}
|
||
if (is_dir($dir)) {
|
||
foreach (array_diff(scandir($dir), array(".", "..")) as $f) {
|
||
$this->remove($this->id($dir . DIRECTORY_SEPARATOR . $f));
|
||
}
|
||
rmdir($dir);
|
||
}
|
||
if (is_file($dir)) {
|
||
unlink($dir);
|
||
}
|
||
return array('status' => 'OK');
|
||
}
|
||
public function move($id, $par)
|
||
{
|
||
$dir = $this->path($id);
|
||
$par = $this->path($par);
|
||
$new = explode(DIRECTORY_SEPARATOR, $dir);
|
||
$new = array_pop($new);
|
||
$new = $par . DIRECTORY_SEPARATOR . $new;
|
||
rename($dir, $new);
|
||
return array('id' => $this->id($new));
|
||
}
|
||
public function copy($id, $par)
|
||
{
|
||
$dir = $this->path($id);
|
||
$par = $this->path($par);
|
||
$new = explode(DIRECTORY_SEPARATOR, $dir);
|
||
$new = array_pop($new);
|
||
$new = $par . DIRECTORY_SEPARATOR . $new;
|
||
if (is_file($new) || is_dir($new)) { throw new Exception('Path already exists: ' . $new); }
|
||
|
||
if (is_dir($dir)) {
|
||
mkdir($new);
|
||
foreach (array_diff(scandir($dir), array(".", "..")) as $f) {
|
||
$this->copy($this->id($dir . DIRECTORY_SEPARATOR . $f), $this->id($new));
|
||
}
|
||
}
|
||
if (is_file($dir)) {
|
||
copy($dir, $new);
|
||
}
|
||
return array('id' => $this->id($new));
|
||
}
|
||
}
|
||
|
||
if (isset($_GET['operation'])) {
|
||
|
||
$fs = new fs($rootdir);
|
||
try {
|
||
$rslt = null;
|
||
switch ($_GET['operation']) {
|
||
case 'get_node':
|
||
$node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
|
||
$rslt = $fs->lst($node, (isset($_GET['id']) && $_GET['id'] === '#'));
|
||
break;
|
||
case "get_content":
|
||
$node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
|
||
$rslt = $fs->data($node);
|
||
break;
|
||
case 'create_node':
|
||
$node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
|
||
$rslt = $fs->create($node, isset($_GET['text']) ? $_GET['text'] : '', (!isset($_GET['type']) || $_GET['type'] !== 'file'));
|
||
break;
|
||
case 'rename_node':
|
||
$node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
|
||
$rslt = $fs->rename($node, isset($_GET['text']) ? $_GET['text'] : '');
|
||
break;
|
||
case 'delete_node':
|
||
$node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
|
||
$rslt = $fs->remove($node);
|
||
break;
|
||
case 'move_node':
|
||
$node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
|
||
$parn = isset($_GET['parent']) && $_GET['parent'] !== '#' ? $_GET['parent'] : '/';
|
||
$rslt = $fs->move($node, $parn);
|
||
break;
|
||
case 'copy_node':
|
||
$node = isset($_GET['id']) && $_GET['id'] !== '#' ? $_GET['id'] : '/';
|
||
$parn = isset($_GET['parent']) && $_GET['parent'] !== '#' ? $_GET['parent'] : '/';
|
||
$rslt = $fs->copy($node, $parn);
|
||
break;
|
||
default:
|
||
throw new Exception('Unsupported operation: ' . $_GET['operation']);
|
||
}
|
||
header('Content-Type: application/json; charset=utf8');
|
||
echo json_encode($rslt);
|
||
} catch (Exception $e) {
|
||
header($_SERVER["SERVER_PROTOCOL"] . ' 500 Server Error');
|
||
header('Status: 500 Server Error');
|
||
echo $e->getMessage();
|
||
}
|
||
die();
|
||
}
|